更好用的DialogFragment

工作中总是要用到各式各样的对话框,通常我们首先会想到的就是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

你可能感兴趣的:(对话框,android,android开发)