preface

This post has been posted on my Github blog. Welcome to my humble abode:

My GIthub blog

Mind mapping


Why should we learn DialogFragment

Are you still using Dialog?

Are you still bothered by all the weird things that happen to Dialog when the screen flips?

Do you want to reduce coupling?

If you have one of the troubles, then congratulations to you, met DialogFragment, he happened to solve the above problem, if interested, with the author to see it!


Second, the background

Android officially recommends using DialogFragment instead of Dialog for greater reusability (less coupling) and greater convenience (better handling screen flip cases).

There are two ways to create a DialogFragment:

  • Method 1: overwrite itonCreateDialogmethods

It is generally used to create a scene to replace the traditional Dialog Dialog box. The UI is simple and the function is single. It is not suitable for multi-threading (such as network request) (null pointer exception will be generated because the current Fragment state cannot be correctly obtained).

  • Method two: overwrite itonCreateViewmethods

Generally used to create complex content pop-ups or full-screen display scenes, complex UI, complex functions, generally have asynchronous operations such as network requests


Three, the application

3.1 What is the basic usage

Method one:

A. Create a simple Dialog and return it

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
    // Sets the theme constructor
    // AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(), R.style.CustomDialog);
 builder.setTitle("Attention:")  .setMessage("Exit the application?")  .setPositiveButton("Sure".null)  .setNegativeButton("Cancel".null)  .setCancelable(false);  //builder.show(); // The show() method cannot be used here  return builder.create(); } Copy the code
Run a screenshot

B. You can also use custom views to create:

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
    // Sets the theme constructor
    // AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(), R.style.CustomDialog);
 LayoutInflater inflater = getActivity().getLayoutInflater();  View view = inflater.inflate(R.layout.fragment_dialog, null);  builder.setView(view)  // Do Someting,eg: TextView tv = view.findViewById(R.id.tv);  return builder.create(); } Copy the code
Run a screenshot

There are many different ways to create dialogs, such as the following one.

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    LayoutInflater inflater = getActivity().getLayoutInflater();
    View view = inflater.inflate(R.layout.fragment_dialog, null);
    Dialog dialog = new Dialog(getActivity());
 // Sets the theme constructor  // Dialog dialog = new Dialog(getActivity(), R.style.CustomDialog);  dialog.setContentView(view);  // Do Someting  return dialog; } Copy the code
Run a screenshot

In this case, the white part above the title content is actually the default title bar, which can be hidden if necessary (described below).

3.2 How do I Handle screen Flip

If you use a traditional Dialog, you need to handle the screen flip manually, but if you use a DialogFragment, you don’t need to do anything. FragmentManager automatically manages the DialogFragment life cycle.

3.3 How do I Hide the Title Bar

In the basic usage of code comments there is a setting of the theme, the following details the two methods of setting no title bar:

Method one:

@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    LayoutInflater inflater = Objects.requireNonNull(getActivity()).getLayoutInflater();
    @SuppressLint("InflateParams") View view = inflater.inflate(R.layout.fragment_i_o_s_dialog, null);
 Dialog dialog = new Dialog(getActivity());  // Close the title bar, called before setContentView()  dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);  dialog.setContentView(view);  dialog.setCanceledOnTouchOutside(true);  return dialog; } Copy the code

Method 2:

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setStyle(DialogFragment.STYLE_NO_TITLE, 0);
}
Copy the code

3.4 How Can I Achieve Full Screen

Most commonly used forms are as wide as the screen width, height adaptive, the following directly look at the code:

Method one:

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    LayoutInflater inflater = getActivity().getLayoutInflater();
    View view = inflater.inflate(R.layout.fragment_dialog, null);
    Dialog dialog = new Dialog(getActivity(), 0);
 dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);  dialog.setContentView(view);  dialog.setCanceledOnTouchOutside(true);  //Do something  // Set the width to the screen width, near the bottom of the screen  Window window = dialog.getWindow();  // Set the window background color to transparent, this step is necessary  // <color name="transparent">#50000000</color>  window.setBackgroundDrawableResource(R.color.transparent);  WindowManager.LayoutParams wlp = window.getAttributes();  wlp.gravity = Gravity.BOTTOM;  // Set the width of the window to MATCH_PARENT, which is the same as the screen width  wlp.width = WindowManager.LayoutParams.MATCH_PARENT;  wlp.height = WindowManager.LayoutParams.WRAP_CONTENT;  window.setAttributes(wlp);  return dialog; } Copy the code

Method 2:

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setStyle(DialogFragment.STYLE_NO_TITLE, 0);
}
 @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {  getDialog().setCanceledOnTouchOutside(true);  View rootView = inflater.inflate(R.layout.fragment_dialog, container, false);  //Do something  // Set the width to screen width, near the bottom of the screen.  final Window window = getDialog().getWindow();  // This step is required  window.setBackgroundDrawableResource(R.color.transparent);  // If necessary, set the padding. This step is also required. The content cannot be filled with the full width and height  window.getDecorView().setPadding(0.0.0.0);  WindowManager.LayoutParams wlp = window.getAttributes();  wlp.gravity = Gravity.BOTTOM;  wlp.width = WindowManager.LayoutParams.MATCH_PARENT;  wlp.height = WindowManager.LayoutParams.WRAP_CONTENT;  window.setAttributes(wlp);  return rootView; } Copy the code

3.5 What are the differences in Application Scenarios

At the beginning of the article, the application scenarios of Method 1 and Method 2 were briefly summarized. Here are the explanations:

  • Method 1: simple substitutionDialogProvides a very convenient way to create, but in the case of using multiple threads (such as network requests), does not get the current correctlyFragmentThe null pointer exception will be generated
  • Method two: there is no such as the overhead pointer problem, and its creation mode by default using customViewIt is easier to deal with complexityUIThe scene of

3.6 How Do I Interact with Activities?

Use the callback method

A. In DialogFragment:

public interface OnDialogListener {
    void onDialogClick(String person);
}

private OnDialogListener mlistener;
 public void setOnDialogListener(OnDialogListener dialogListener){  this.mlistener = dialogListener; } Copy the code

In the DialogFragment click event:

public OnDialogListener mlistener;
@Override
public void onClick(View view) {
    switch (view.getId()) {
        case R.id.tv1:
 mlistener.onDialogClick("1");  dismiss();  break;  case R.id.tv2:  mlistener.onDialogClick("2");  dismiss();  break;  case R.id.tv3:  mlistener.onDialogClick("3");  dismiss();  break;  case R.id.tv4:  mlistener.onDialogClick("4");  dismiss();  break;  } } Copy the code

B. in the Activity

dialogFragment.setOnDialogListener(new PersonDialogFragment.OnDialogListener() {
    @Override
    public void onDialogClick(String person) {
        ToastUtil.showToast(person);
    }
}); Copy the code

3.7 How to use it in combination with animation

A. Set the animation that pops up from bottom to top

private void slideToUp(View view) {
    Animation slide = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 1.0 f, Animation.RELATIVE_TO_SELF, 0);
    slide.setDuration(400);
    slide.setFillEnabled(true);
    slide.setFillAfter(true);
 view.startAnimation(slide); } Copy the code

B. Set the animation that pops up from top to bottom

private boolean isAnimation = false;// To determine if multiple clicks are used. Prevent multiple executions

public void slideToDown(View view) {
    Animation slide = new TranslateAnimation(
            Animation.RELATIVE_TO_SELF, 0.0 f. Animation.RELATIVE_TO_SELF, 0.0 f. Animation.RELATIVE_TO_SELF, 0.0 f. Animation.RELATIVE_TO_SELF, 1.0 f);  slide.setDuration(400);  slide.setFillEnabled(true);  slide.setFillAfter(true);  view.startAnimation(slide);  slide.setAnimationListener(new Animation.AnimationListener() {  @Override  public void onAnimationStart(Animation animation) {  }   @Override  public void onAnimationEnd(Animation animation) {  // To determine if multiple clicks are used. Prevent multiple executions  isAnimation = false;  // The popbox disappears  IOSDialogFragment.this.dismiss();  }   @Override  public void onAnimationRepeat(Animation animation) {  }  }); } Copy the code

C. Encapsulate pop-up animations from top to bottom

Plus determine if you click multiple times. Prevent multiple executions

private void dialogFinish(a) {
    if (isAnimation) {
        return;
    }
    isAnimation = true;
 slideToDown(rootView); } Copy the code

3.8 how do I display DialogFragment in the Activity?

mBtn.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        IOSDialogFragment fragment = new IOSDialogFragment();
        // The second argument is tag
 fragment.show(getSupportFragmentManager(), "android");  } }); Copy the code

3.9 How can I use animation when clicking the blank space to close?

Set onTouchListener directly to the DecorView

window.getDecorView().setOnTouchListener(new View.OnTouchListener() {
    public boolean onTouch(View v, MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_UP) {
            // Popbox disappearing animation executes relevant code
..  }  return true;  } });  Copy the code

Four, conclusion

Finally finished with the duck! Dead duck! If there is something else that is not clear, you can take a look at the sample Demo I wrote



If the article is a little help to you, I hope you can click on it. Your click on it is my motivation

References:

  • Project requirements discussion – implementation and analysis of imitation ios bottom pop-up box
  • DialogFragment+ Interacts with Activity data is displayed at the bottom
  • Android will know will – DialogFragment use summary

This article is formatted using MDNICE