工作中总是要用到各式各样的对话框,通常我们首先会想到的就是Dialog。在以前的时候我通常都会自定义一个Dialog,然后在里面写一个接口,让需要创建这个Dialog的界面继承这个接口,实现点击事件的监听。其中大概代码是这样的:
/**
* @date 创建时间: 2017/11/22 22:25
* @author zh_legendd
* @Description 自定义的dialog
* @Email [email protected]
* @Version 1.0
*/
public class SureExitDialog extends Dialog {
private Button btn_cancel, btn_sure;
private SureListener mSureListener;
public interface SureListener {
void sureExit();
}
public void setSureListener(SureListener mSureListener){
this.mSureListener=mSureListener;
}
public SureExitDialog(Context context) {
super(context, R.style.PayDialog);
initWindow();
show();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_dialog);
btn_sure = (Button) findViewById(R.id.btn_sure);
btn_cancel = (Button) findViewById(R.id.btn_cancel);
btn_cancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
dismiss();
}
});
btn_sure.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mSureListener.sureExit();
dismiss();
}
});
}
/**
* 初始化window参数
*/
private void initWindow() {
Window dialogWindow = getWindow();
dialogWindow.getDecorView().setPadding(0, 0, 0, 0);
dialogWindow.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
dialogWindow.setBackgroundDrawableResource(android.R.color.transparent);
dialogWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
WindowManager.LayoutParams lp = dialogWindow.getAttributes();
lp.width = WindowManager.LayoutParams.MATCH_PARENT;
lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
lp.gravity = Gravity.CENTER;
dialogWindow.setAttributes(lp);
}
}
- 其实感觉这样写也并没有什么不好的,以前我也看到过其他人写的文章说现在官方推荐使用DialogFragment,但是看了几篇文章并没有感觉有多好用。直到我看了《Android编程权威指南》之后,我觉得真的有必要的使用一下DialogFragment了。现在基本上都会在Activity里面放很多fragment。因此接下来我们要做的一个DialogFragment的场景也是在镶嵌到Activity的Fragment中调起的Fragment的并且不通过设置接口来传递数据,而是通过Fragment中特有的属性设置Tag,来辨别不同的Fragment(这也许就是DialogFragment的精华所在吧),take is cheap show me the code。
- 首先创建一个承载Fragment的Activity
/**
* @date 创建时间: 2017/11/22 0022 22:32
* @author zh_legendd
* @Description 承载Fragment的Activity
* @Email [email protected]
* @Version 1.0
*/
public class FDActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fd);
//替换fragment
initView();
}
public void initView(){
FragmentManager supportFragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = supportFragmentManager.beginTransaction();
transaction.add(R.id.fl_context,TrFragment.newInstance());
transaction.commit();
// transaction.add()
}
}
- 然后创建一个镶嵌在Activity里面的Fragment,在这个Fragment的布局中只有一个按钮所以就不贴布局的代码了,一会可以看源码。这里注意的主要有两点:
- 1 调起DialogFragment :因为DialogFragment的父类也是Fragment,所以我们首先也是需要得到FragmentManager ,但是又有和Fragment不同的是显示DialogFragment的时候需要调用show方法。在这里还需要设置一个返回值的tag,用于在onActivityResult回调的时候得到DialogFragment回传过来的信息。相当与我们自定义的Dialog中使用接口一样。但是后面的show方法里面的Tag好像是现在没有什么用。
- 2 一般情况下我们调起Dialog无非就是一些提示语,然后让用户选择确认或者取消。接下来说的就是在DialogFragment中当用户点击确定或取消之后,怎么回传用户行为,我想看过上面一段话肯定就已经知道了,那就是在onActivityResult中进行。
- 3 在DialogFragment中并没有设置接口监听,却能在Fragment直接相互传递数据主要还是应用的我上一篇讲的在onActivityResult中进行回调。
- 4 因为在Fragment中调起DialogFragment的时候,Fragment中有一个可以设置Tag的属性,所以不需要设置回调监听,直接使用onActivityResult回调监听就可以。但是在Activity就不同了,反正我是找了好久,就必须要设置接口监听。
/**
* @date 创建时间: 2017/11/22 0022 22:34
* @author zh_legendd
* @Description 镶嵌在Activity的Fragment
* @Email [email protected]
* @Version 1.0
*/
public class TrFragment extends Fragment {
private static final int REQUEST_DATE=0;
//fragment的TAG
private static final String DIALOG_DATE="DialogDate";
private Button bt_jump;
public static TrFragment newInstance(){
//fargment与Activity之间传递数据
// Bundle args =new Bundle();
// args.putString();
TrFragment trFragment=new TrFragment();
// trFragment.setArguments(args);
return trFragment;
}
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View inflate = inflater.inflate(R.layout.fragment_tr, null);
bt_jump=(Button)inflate.findViewById(R.id.bt_jump);
bt_jump.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// MyToast.showText("点击了");
FragmentManager fragmentManager = getFragmentManager();
TestDialogFragment dialog = TestDialogFragment.newInstance("test");
dialog.setTargetFragment(TrFragment.this,REQUEST_DATE);
dialog.show(fragmentManager,DIALOG_DATE);
}
});
return inflate;
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if(resultCode!= Activity.RESULT_OK){
return;
}
if(requestCode==REQUEST_DATE){
MyToast.showText(data.getStringExtra(TestDialogFragment.EXTRA_STR));
}
}
}
- 接下来就是在我们的DialogFragment中让我们正式的显示自己想要样式的Dialog。自定义的话,当时我心里面是有二个疑惑的首先就是怎么设置样式,然后就是怎么设置布局:
- 第一个疑惑:这可能是有点麻烦了,需要谷歌一下。最后被我找到了,只要在这里设置属性就OK,这样你的DialogFragment就可以引用自定义的样式了。
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStyle(STYLE_NO_TITLE,R.style.PayDialog);
}
- 第二个的话,很多文章里面都写的有直接在onCreateView里面设置布局就可以,当然自定义的话需要把标题给去掉,只用调用这一句方法就行getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE);然后在onStart方法里面设置就像我们自定义的Dialog一样初始化window,就这么简单就可以实现和自定义Dialog一样的布局了。
/**
* @date 创建时间: 2017/11/22 0022 22:44
* @author zh_legendd
* @Description 在DialogFragment布局
* @Email [email protected]
* @Version 1.0
*/
public class TestDialogFragment extends DialogFragment {
private static final String ARG_TEST="test";
public static final String EXTRA_STR="extra_str";
private Button btn_cancel, btn_sure;
public static TestDialogFragment newInstance(String str){
Bundle bundle=new Bundle();
bundle.putString(ARG_TEST,str);
TestDialogFragment testDialogFragment=new TestDialogFragment();
testDialogFragment.setArguments(bundle);
return testDialogFragment;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStyle(STYLE_NO_TITLE,R.style.PayDialog);
}
@Override
public void onStart() {
super.onStart();
initWindow();
}
/**
* 初始化window参数
*/
private void initWindow() {
Window dialogWindow = getDialog().getWindow();
dialogWindow.getDecorView().setPadding(0, 0, 0, 0);
dialogWindow.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
dialogWindow.setBackgroundDrawableResource(android.R.color.transparent);
dialogWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
WindowManager.LayoutParams lp = dialogWindow.getAttributes();
lp.width = WindowManager.LayoutParams.MATCH_PARENT;
lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
lp.gravity= Gravity.CENTER;
dialogWindow.setAttributes(lp);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE);
View inflate = inflater.inflate(R.layout.fragment_dialog, null);
btn_sure = (Button) inflate.findViewById(R.id.btn_sure);
btn_cancel = (Button) inflate.findViewById(R.id.btn_cancel);
btn_sure.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
sendResult(Activity.RESULT_OK,"str");
}
});
return inflate;
}
private void sendResult(int resultCode,String str){
if(getTargetFragment()==null){
return;
}
Intent intent=new Intent();
intent.putExtra(EXTRA_STR,str);
getTargetFragment().onActivityResult(getTargetRequestCode(),resultCode,intent);
}
}
总结一下,我感觉DialogFragment中主要有两点相对应Dialog来说有点难。第一个是数据传递,第二个就自定义布局。感觉我上面说的还比较清楚吧(┬_┬)。Demo下载地址
DialogFragment