Lazy Man Necessary Universal Dialog Bullet Window sdk

Posted by Sassci on Tue, 17 Sep 2019 09:15:55 +0200

Catalog

Preface

The Origin of XDialog

Analysis of Use Method

Analysis of Frame Principle

 

 

Preface

I've seen a lot of Dialog packages, but I think they all have shortcomings, so I'll take one of them to support Android X. I hope you can give valuable comments.

 

The Origin of XDialog

All frameworks are designed to solve problems more conveniently and efficiently, and XDialog is also used to achieve more efficient project window effect. XDialog is inherited from Dialog Fragment for packaging. Most developers prefer Alert Dialog provided by the system when they implement window effect; however, they use the system. The most common scenario is that when the screen rotates, the Dialog pop-up window disappears and a system is thrown out. This exception does not cause an abnormal crash, because Google developers know this problem and deal with it. Dialog is actually simpler to use, but Google recommends trying to make it as easy as possible. Use Dialog Fragment.

1. Advantages of Dialog Fragment

  • Dialog Fragment itself is a subclass of Fragment, which has the same life cycle as Fragment. Dialog Fragment is used to manage dialog boxes, which can better manage the life cycle when the screen is rotated and the back key is pressed.
  • Dialog Fragment-based dialog boxes will be automatically rebuilt by Fragment Manager when mobile phone configuration changes lead to Activity re-creation, such as rotating screen. However, Dialog-based dialog boxes do not have the ability to \\\ use 1. Adding dependencies a. Adding dependencies in repositories of Engineering build.gradle files
allprojects {
    repositories {
        google()
        jcenter()
        maven { url 'https://jitpack.io' }
        
    }
}

b. Add build.gradle file under model

Support Androidx
implementation 'com.github.cl-6666:xDialog:v1.0.1'

2. Use Activity or Fragment

        new XDialog.Builder(getSupportFragmentManager())
                .setLayoutRes(R.layout.dialog_click)    //Setting up the xml layout for the bullet window display
//                setDialogView(view) // Set the layout of the bullet window and pass it directly into View
                .setWidth(600)  //Set the window width (px)
                .setHeight(800)  //Setting the height of bullet window (px)
                .setScreenWidthAspect(this, 0.8f)   //Set the pop-up window width (parameter aspect is 0 - 1F for screen width ratio)
                .setScreenHeightAspect(this, 0.3f)  //Set the height of the bullet window (parameter aspect is 0 - 1F of screen width ratio)
                .setGravity(Gravity.CENTER)     //Setting the display position of the bullet window
                .setTag("DialogTest")   //Set Tag
                .setDimAmount(0.6f)     //Set the background transparency of the bullet window (0-1f)
                .setCancelableOutside(true)     //Can the Bullet Window Click Cancel Outside the Interface
                .setDialogAnimationRes(R.style.animate_dialog)  //Setting Bullet Window Animation
                .setOnDismissListener(new DialogInterface.OnDismissListener() { //Callback Method for Bullet Window Hiding
                    @Override
                    public void onDismiss(DialogInterface dialog) {
                        Toast.makeText(DiffentDialogActivity.this, "Bullet window disappearance callback", Toast.LENGTH_SHORT).show();
                    }
                })
                .setOnBindViewListener(new OnBindViewListener() {   //Get the control object through BindViewHolder and modify it
                    @Override
                    public void bindView(BindViewHolder bindViewHolder) {
                        bindViewHolder.setText(R.id.tv_content, "abcdef");
                        bindViewHolder.setText(R.id.tv_title, "I am Title");
                    }
                })
                .addOnClickListener(R.id.btn_left, R.id.btn_right, R.id.tv_title)   //Add the id of the click Control
                .setOnViewClickListener(new OnViewClickListener() {     //View control click event callback
                    @Override
                    public void onViewClick(BindViewHolder viewHolder, View view, TDialog tDialog) {
                        switch (view.getId()) {
                            case R.id.btn_left:
                                Toast.makeText(DiffentDialogActivity.this, "left clicked", Toast.LENGTH_SHORT).show();
                                break;
                            case R.id.btn_right:
                                Toast.makeText(DiffentDialogActivity.this, "right clicked", Toast.LENGTH_SHORT).show();
                                tDialog.dismiss();
                                break;
                            case R.id.tv_title:
                                Toast.makeText(DiffentDialogActivity.this, "title clicked", Toast.LENGTH_SHORT).show();
                                viewHolder.setText(R.id.tv_title, "Title Click.");
                                break;
                        }
                    }
                })
                .setOnKeyListener(new DialogInterface.OnKeyListener() {
                    @Override
                    public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
                        return false;
                    }
                })
                .create()   //Create TDialog
                .show();    //Exhibition

Add animation posture

New File of Fill-in Animation
enter.xml
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="300"
    android:fromYDelta="100%p"
    android:toYDelta="0%p">

</translate>
exit.xml
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="300"
    android:fromYDelta="0%p"
    android:toYDelta="100%p">

</translate>
style.xml file
<style name="animate_dialog">
    <item name="android:windowEnterAnimation">@anim/enter</item>
    <item name="android:windowExitAnimation">@anim/exit</item>
</style>

Analysis of Use Method

The principle of XDialog is similar to that of system Dialog. It mainly uses Builder design pattern to implement 1. Create a bullet window, pass in an xml layout file or a View control, and set its own background color, because the default is transparent background color.

new XDialog.Builder(getSupportFragmentManager())
        .setLayoutRes(R.layout.dialog_click)
        .setDialogView(view)
        .create()
        .show();

2. Set the width and height of the pop-up window (if not, the height of the package content is used by default)

   new XDialog.Builder(getSupportFragmentManager())
            .setLayoutRes(R.layout.dialog_click)
            .setWidth(600)  //Set the fixed width of the bullet window (unit: px)
            .setHeight(800)//Setting the Fixed Height of Bullet Window
            .setScreenWidthAspect(Activity.this,0.5f) //Set the window width to the percentage of screen width dynamically (value 0-1f)
            .setScreenHeightAspect(Activity.this,0.6f)//Set the height of the bullet window as a percentage of the screen height (value 0-1f)
            .create()
            .show();

3. Setting up the display position of the bullet window

.setGravity(Gravity.CENTER)
Other locations are: Gravity.Bottom / Gravity.LEFT and so on, as well as setting control locations.

4. Set the background color transparency of the bullet window (0-1f,0 is transparent)

.setDimAmount(0.6f)

5. Set whether the outside of the pop-up window can be cancelled by clicking (default can be cancelled), whether the pop-up window can be cancelled by default, and how to call back when the pop-up window is hidden.

.setCancelableOutside(true)
.setOnDismissListener(new DialogInterface.OnDismissListener() { //Callback Method for Bullet Window Hiding
    @Override
    public void onDismiss(DialogInterface dialog) {
        Toast.makeText(DiffentDialogActivity.this, "Bullet window hidden callback", Toast.LENGTH_SHORT).show();
    }
})

6. When the bullet window needs to dynamically change the content of the control sub-view, the design idea of RecyclerView.Adapter is used for reference, and a BindViewHolder is encapsulated inside.

.setOnBindViewListener(new OnBindViewListener() {
    @Override
    public void bindView(BindViewHolder bindViewHolder) {
        bindViewHolder.setText(R.id.tv_content, "abcdef");
    bindViewHolder.setText(R.id.tv_title,"I am Title");        
    }
})

7. To monitor click events of pop-up window control, addOnClickListener(ids []) is also implemented internally through BindViewHolder. It only needs to pass in the id of click event control and set the callback interface setOnViewClickListener().

.addOnClickListener(R.id.btn_right, R.id.tv_title)
.setOnViewClickListener(new OnViewClickListener() {
    @Override
    public void onViewClick(BindViewHolder viewHolder,View view1, TDialog tDialog) {
        switch (view1.getId()) {
            case R.id.btn_right:
                Toast.makeText(DialogEncapActivity.this, "btn_right", Toast.LENGTH_SHORT).show();
                tDialog.dismiss();
                break;
            case R.id.tv_title:
                Toast.makeText(DialogEncapActivity.this, "tv_title", Toast.LENGTH_SHORT).show();
                break;
        }
    }
})

8. Setting Bullet Window Animation

.setDialogAnimationRes(R.style.animate_dialog) 

9. To monitor the return key click event, you need to use it in conjunction with the setCancelableOutside(false) method.

.setOnKeyListener(new DialogInterface.OnKeyListener() {
    @Override
    public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
           if (keyCode == KeyEvent.KEYCODE_BACK) {
                Toast.makeText(DiffentDialogActivity.this, "Return key is invalid. Please use it after forced upgrade.", Toast.LENGTH_SHORT).show();
                 return true;
           }
           return false;  //Default return value
     }
})

a. List Bullet Window - Using XListDialog,XListDialog inherits from XDialog, can use all methods of the parent class, and expand list data to show rich setAdapter() and item click event callback method setOnAdapter ItemClickListener ()

new XListDialog.Builder(getSupportFragmentManager())
        .setHeight(600)
        .setScreenWidthAspect(this, 0.8f)
        .setGravity(Gravity.CENTER)
        .setAdapter(new TBaseAdapter<String>(R.layout.item_simple_text, Arrays.asList(data)) {

            @Override
            protected void onBind(BindViewHolder holder, int position, String s) {
                holder.setText(R.id.tv, s);
            }
        })
        .setOnAdapterItemClickListener(new TBaseAdapter.OnAdapterItemClickListener<String>() {
            @Override
            public void onItemClick(BindViewHolder holder, int position, String s, TDialog tDialog) {
                Toast.makeText(DiffentDialogActivity.this, "click:" + s, Toast.LENGTH_SHORT).show();
                tDialog.dismiss();
            }
        })
        .create()
        .show();

List pop-up

For ease of use:

  1. Instead of passing in the layoutRes layout file, a default RecyclerView layout is set inside the TDialog, and the control id of RecyclerView is recycler_view with the background of #ffffff.
  2. Set Adapter, set the adapter of recycler view. In order to encapsulate the item click event of the adapter, the imported adapter needs to be the implementation class of TBaseAdapter.
  3. setOnAdapterItemClickListener(), setting the click event of adapter
<?xml version="1.0" encoding="utf-8"?>
<androidx.recyclerview.widget.RecyclerView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/recycler_view"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#ffffff"
    android:orientation="vertical" />

XBaseAdapter implementation: xml layout that requires users to pass in item, and List data

public abstract class XBaseAdapter<T> extends RecyclerView.Adapter<BindViewHolder> {

    private final int layoutRes;
    private List<T> datas;
    private OnAdapterItemClickListener adapterItemClickListener;
    private XDialog dialog;

    protected abstract void onBind(BindViewHolder holder, int position, T t);

    public XBaseAdapter(@LayoutRes int layoutRes, List<T> datas) {
        this.layoutRes = layoutRes;
        this.datas = datas;
    }

    @Override
    public BindViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return new BindViewHolder(LayoutInflater.from(parent.getContext()).inflate(layoutRes, parent, false));
    }

    @Override
    public void onBindViewHolder(final BindViewHolder holder, final int position) {
        onBind(holder, position, datas.get(position));
        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                adapterItemClickListener.onItemClick(holder, position, datas.get(position), dialog);
            }
        });
    }

    @Override
    public int getItemCount() {
        return datas.size();
    }

    public void setTDialog(XDialog xDialog) {
        this.dialog = tDialog;
    }

    public interface OnAdapterItemClickListener<T> {
        void onItemClick(BindViewHolder holder, int position, T t, XDialog xDialog);
    }

    public void setOnAdapterItemClickListener(OnAdapterItemClickListener listener) {
        this.adapterItemClickListener = listener;
    }

}

If users need to use their own list layout, they can use the setListLayoutRes(layotuRes,LayoutManager) method to set the xml layout and layout manager LayoutManager. Keep in mind that the id of RecyclerView in the xml layout must be set to recycler_view (such as the sharing bullet window in the effect map).

//Bottom sharing
public void shareDialog(View view) {
    new XListDialog.Builder(getSupportFragmentManager())
            .setListLayoutRes(R.layout.dialog_share_recycler, LinearLayoutManager.HORIZONTAL)
            .setScreenWidthAspect(this, 1.0f)
            .setGravity(Gravity.BOTTOM)
            .setAdapter(new TBaseAdapter<String>(R.layout.item_share, Arrays.asList(sharePlatform)) {
                @Override
                protected void onBind(BindViewHolder holder, int position, String s) {
                    holder.setText(R.id.tv, s);
                }
            })
            .setOnAdapterItemClickListener(new TBaseAdapter.OnAdapterItemClickListener<String>() {
                @Override
                public void onItemClick(BindViewHolder holder, int position, String item, TDialog tDialog) {
                    Toast.makeText(DiffentDialogActivity.this, item, Toast.LENGTH_SHORT).show();
                    tDialog.dismiss();
                }
            })
            .create()
            .show();
}

Custom List Layout

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#242424">

    <TextView
        android:id="@+id/textView3"
        android:layout_width="0dp"
        android:layout_height="50dp"
        android:gravity="center"
        android:text="Share to"
        android:textColor="@color/white"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView3" />

</android.support.constraint.ConstraintLayout>

Analysis of Frame Principle

The implementation principle of XDialog is mainly divided into three steps.

  1. Instantiate the XDialog.Builer object builder, and then call various setXXX() methods to set the data, which are stored in the XController.XParams instance.
  2. The XDialog object is instantiated after the create() method call, and the data set in XController.XParams is passed to the XDialog attribute XController object.
  3. show() method call display window

 

Topics: Android xml Fragment encoding