Author: Jooyer, 2018.08.05

Github address, thumbs up,fork

If you look at GIF, you know it’s easy to customize, so why say it?

The main thing is that github has a lot of nice libraries written by the big guys, but with more features, more files, a lot of times to introduce a third party, we have to consider the number of methods, library size, etc., and sometimes, we don’t need that much functionality.

The frequency of use in the work is very high, every use of a custom, it is a waste of energy. This article has done some expansion on the big guy’s shoulder, the specific big guy link is given at the end of the article.

Okay, let’s get down to business (PS: source code eggs oh).

All you need is four classes and a few XML files, copy and use

Let’s explain it one by one:

  1. JAlertDialog
  2. JAlertController
  3. JDialogViewHelper
  4. OnJAlertDialogClickListener
  5. Several other XML files

First let’s look at the JAlertDialog:

public class JAlertDialog extends Dialog {

    private JAlertController mAlert;

    public JAlertDialog(Context context, int themeResId) {
        super(context, themeResId);
        mAlert = new JAlertController(this, getWindow());
    }


    public static class Builder {
        private final JAlertController.AlertParams mAlertParams;


        public Builder(Context context) {
            this(context, R.style.JDialogStyle);
        }

        public Builder(Context context, @StyleRes int themeRes) {
            mAlertParams = new JAlertController.AlertParams(context, themeRes);
        }

        public Builder setContentView(View view) {
            mAlertParams.mView = view;
            mAlertParams.mViewLayoutResId = 0;
            return this;
        }

        public Builder setContentView(int layoutResId) {
            mAlertParams.mView = null;
            mAlertParams.mViewLayoutResId = layoutResId;
            return this;
        }

        public Builder setCancelable(boolean cancelable) {
            mAlertParams.mCancelable = cancelable;
            return this;
        }


        public Builder setText(@IdRes int viewId, CharSequence text) {
            mAlertParams.mTextArr.put(viewId,text);
            return this;
        }


        public Builder setFromBottom() {
            mAlertParams.mGravity = Gravity.BOTTOM;
            return this;
        }

        public Builder setAnimation(@StyleRes int styleAnim) {
            mAlertParams.mAnimation = styleAnim;
            return this;
        }

        public Builder setHasAnimation(boolean hasAnimation) {
            mAlertParams.mHasAnimation = hasAnimation;
            return this;
        }

        public Builder setFullWidth() {
            mAlertParams.mWidth = ViewGroup.LayoutParams.MATCH_PARENT;
            return this;
        }

        public Builder setWidthAndHeight(int width,int height) {
            mAlertParams.mWidth = width;
            mAlertParams.mHeight = height;
            return this;
        }

        public Builder setOnClick(@IdRes int viewId) {
            mAlertParams.mClickArr.put(mAlertParams.mClickArr.size(),viewId);
            return this;
        }

        public Builder setOnJAlertDialogCLickListener(OnJAlertDialogClickListener onJAlertDialogClickListener) {
            mAlertParams.mOnJAlertDialogClickListener = onJAlertDialogClickListener;
            return this;
        }

        public Builder setOnCancelListener(OnCancelListener onCancelListener) {
            mAlertParams.mOnCancelListener = onCancelListener;
            return this;
        }

        public Builder setOnOnDismissListener(OnDismissListener onDismissListener) {
            mAlertParams.mOnDismissListener = onDismissListener;
            return this;
        }

        public Builder setOnKeyListener(OnKeyListener onKeyListener) {
            mAlertParams.mOnKeyListener = onKeyListener;
            return this;
        }


        public JAlertDialog create() {
            final JAlertDialog dialog = new JAlertDialog(mAlertParams.mContext, mAlertParams.mThemeRes);
            mAlertParams.apply(dialog.mAlert);
            dialog.setCancelable(mAlertParams.mCancelable);
            if (mAlertParams.mCancelable) {
                dialog.setCanceledOnTouchOutside(true);
            }
            dialog.setOnCancelListener(mAlertParams.mOnCancelListener);
            dialog.setOnDismissListener(mAlertParams.mOnDismissListener);
            if(mAlertParams.mOnKeyListener ! = null) { dialog.setOnKeyListener(mAlertParams.mOnKeyListener); }return dialog;
        }

        public JAlertDialog show() {
            JAlertDialog dialog = create();
            dialog.show();
            returndialog; }}}Copy the code

The code does not have any comments, it is very simple, is a builder mode, mimicking the system, nothing very special…

Then let’s look at JAlertController:

public class JAlertController {

    private JAlertDialog mDialog;
    private Window mWindow;

    public JAlertController(JAlertDialog dialog, Window window) {
        mDialog = dialog;
        mWindow = window;
    }

    public JAlertDialog getDialog() {
        return mDialog;
    }

    public Window getWindow() {
        returnmWindow; } public static class AlertParams { public Context mContext; /** * Dialog theme, has a default theme */ public int mThemeRes; Public SparseArray<CharSequence> mTextArr = new SparseArray<>(); /** * Public SparseIntArray mClickArr = new SparseIntArray(); /** * public Boolean mCancelable =false; / * * * Dialog cancel listening * / public DialogInterface. OnCancelListener mOnCancelListener; / * * * Dialog disappear to monitor * / public DialogInterface. OnDismissListener mOnDismissListener; / * * * Dialog button to monitor * / public DialogInterface. OnKeyListener mOnKeyListener; /** * public View mView; /** * Dialog layout ID */ public int mViewLayoutResId; public int mWidth = ViewGroup.LayoutParams.WRAP_CONTENT; public int mHeight = ViewGroup.LayoutParams.WRAP_CONTENT; public int mGravity = Gravity.CENTER; public int mAnimation = R.style.JDialogAnimation; public boolean mHasAnimation =true; public OnJAlertDialogClickListener mOnJAlertDialogClickListener; public AlertParams(Context context, @StyleRes int themeRes) { mContext = context; mThemeRes = themeRes; } /** * set parameters */ public void apply(JAlertController alert) {JDialogViewHelper viewHelper = null; 1. Set the layoutif (0 != mViewLayoutResId) {
                viewHelper = new JDialogViewHelper(mContext, mViewLayoutResId);
            }

            if(null ! = mView) { viewHelper = new JDialogViewHelper(mContext, mView); }if (null == viewHelper) {
                throw new IllegalArgumentException("Please set Dialog layout"); } alert.getDialog().setContentView(viewHelper.getContentView()); viewHelper.setOnJAlertDialogClickListener(mOnJAlertDialogClickListener); // 2. Set a one-to-one correspondence between text, controls and text contentfor(int i = 0, len = mTextArr.size(); i < len; i++) { viewHelper.setText(mTextArr.keyAt(i), mTextArr.valueAt(i)); } // 3. Set the click eventfor(int i = 0, len = mClickArr.size(); i < len; i++) { viewHelper.setOnClick(mClickArr.keyAt(i), mClickArr.valueAt(i)); } // 4. Set dialog width and height animation etc Window Window = alert.getwindow (); window.setGravity(mGravity);if(mHasAnimation) { window.setWindowAnimations(mAnimation); } WindowManager.LayoutParams params = window.getAttributes(); params.width = mWidth; params.height = mHeight; window.setAttributes(params); alert.getDialog().setOnCancelListener(mOnCancelListener); alert.getDialog().setOnDismissListener(mOnDismissListener); }}}Copy the code

Here, the interesting point is, note 3, click events, I have made some optimization on click events by expanding the effect of similar text Settings, see the specific use of the code, do not worry!

Then take a look at the layout file :JDialogViewHelper

public class JDialogViewHelper {
    private Context mContext;
    private View mContentView;
    private SparseArray<WeakReference<View>> mViews;
    public OnJAlertDialogClickListener mOnJAlertDialogClickListener;
    public JDialogViewHelper(Context context, int viewLayoutResId) {
        mViews = new SparseArray<>();
        mContentView = LayoutInflater.from(context).inflate(viewLayoutResId, null);
    }

    public JDialogViewHelper(Context context, View view) {
        mViews = new SparseArray<>();
        mContentView = view;
    }

    public void setText(@IdRes int viewId, CharSequence charSequence) {
        TextView textView = getView(viewId);
        if(null ! = textView) { textView.setText(charSequence); } } public voidsetOnClick(final int position, @IdRes int viewId) {
        View view = getView(viewId);
        if(null ! = view) { view.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if(null ! = mOnJAlertDialogClickListener){ mOnJAlertDialogClickListener.onClick(v,position); }}}); } } public ViewgetContentView() {
        return mContentView;
    }

    @SuppressWarnings("unchecked")
    public <T extends View> T getView(int viewId) {
        View view = null;
        WeakReference<View> viewWeakReference = mViews.get(viewId);
        if(null ! = viewWeakReference) { view = viewWeakReference.get(); }if (null == view) {
            view = mContentView.findViewById(viewId);
            if(null ! = view) mViews.put(viewId, new WeakReference<View>(view)); }return (T) view;
    }

Copy the code

Using a custom ViewHolder similar to the ListView

The penultimate second is to see ha callback, paste a code, to gather the number of lines…. , ha ha

    public void setOnJAlertDialogClickListener(OnJAlertDialogClickListener onJAlertDialogClickListener) { mOnJAlertDialogClickListener = onJAlertDialogClickListener; }}Copy the code

A simple callback, what can I say…

Finally is a few I all throw out, ready to take it!!

1. Create the animation you need in Res/Anim. I paste the GIF animation here

Jdialog_enter. XML –> This must be the default effect, of course, if you copy the source code modified also can not be…

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

Jdialog_exit. XML –> This must be the default effect, of course, if you copy the source code modified also can not be…

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

update_scale_fade_in.xml

<? xml version="1.0" encoding="utf-8"? > <set xmlns:android="http://schemas.android.com/apk/res/android">

    <scale
        android:fromXScale="0.0"
        android:fromYScale="0.0"
        android:toXScale="1.0"
        android:toYScale="1.0"
        android:duration="400"
        android:pivotX="50%"
        android:pivotY="50%"
        />

    <alpha
           android:duration="400"
           android:fromAlpha="0.0"
           android:toAlpha="1.0" >

    </alpha>

</set>
Copy the code

update_scale_fade_out.xml

<? xml version="1.0" encoding="utf-8"? > <set xmlns:android="http://schemas.android.com/apk/res/android">

    <scale
        android:fromXScale="1.0"
        android:fromYScale="1.0"
        android:toXScale="0.0"
        android:toYScale="0.0"
        android:duration="400"
        android:pivotX="50%"
        android:pivotY="50%"
        />

    <alpha
           android:duration="400"
           android:fromAlpha="1.0"
           android:toAlpha="0.0" >

    </alpha>

</set>
Copy the code
  1. Set the Dialog property and animation in res/values/style.xml

    <! -- Default use, so must copy this style, this must be, the default effect, of course, if you copy the source code modified also can not... --> <style name="JDialogStyle" parent="@android:style/Theme.Dialog"> <! -- Background transparency --> <item name="android:windowBackground">@android:color/transparent</item>
        <item name="android:windowContentOverlay">@null</item> <! Float above the Activity --> <item name="android:windowIsFloating">true</item> <! -- border --> <item name="android:windowFrame">@null</item> <! -- Region blur outside Dialog --> <item name="android:backgroundDimEnabled">true</item> <! -- determines background transparency --> <item name="android:backgroundDimAmount"> 0.3 < / item > <! -- no title --> <item name="android:windowNoTitle">true</item> <! --> <item name="android:windowIsTranslucent">true</item> <! -- Dialog enters and exits the animation, so that all using this style have the animation, can be specified separately --> <! --<item name="android:windowAnimationStyle">@style/JDialogAnimation</item>--> </style> <! -- Default use, so must copy this style, this must be, the default effect, of course, if you copy the source code modified also can not... -- > <! Custom animation can be used with the system, i.e. put parent= directly behind it"android:windowAnimationStyle">   -->
    <style name="JDialogAnimation" parent="@android:style/Animation.Dialog">
        <item name="android:windowEnterAnimation">@anim/jdialog_enter</item>
        <item name="android:windowExitAnimation">@anim/jdialog_exit</item> </style> <! < span style = "max-width: 100%; clear: both; min-height: 1em"UpdateAnimation" parent="@android:style/Animation.Dialog">
        <item name="android:windowEnterAnimation">@anim/update_scale_fade_in</item>
        <item name="android:windowExitAnimation">@anim/update_scale_fade_out</item>
    </style>
    Copy the code

    That’s pretty much it, isn’t it pretty simple?

    Let’s look at the basic usage

    class MainActivity : AppCompatActivity() {
        private lateinit var mBottomDialog: JAlertDialog;
        private lateinit var mUpdateDialog: JAlertDialog;
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main) initBottomDialog() initUpdateDialog() tv_center.setOnClickListener { MBottomDialog. The show ()} tv_updpate. SetOnClickListener {mUpdateDialog. The show ()}} / * * * at the bottom of the pop-up * / private funinitBottomDialog() {mBottomDialog = jalertdialog.builder (this).setContentView(r.layout.dialog)false)
                    .setHasAnimation(true) // Whether to have animation, defaulttrue, //.setAnimation() // Sets the animation, which overwrites the default animation.settext (R.i.b.tn_left,"test1") / / set space text, if there are multiple, many times the call. The setFromBottom () / / is it from the bottom of the pop-up, specific effect can try it yourself, be more obvious. The setFullWidth () / / / / width covered with screen .setwidthandHeight () // You can specify the width and height. .setonclick (R.i.b.tn_left) // the first clicked view. setOnClick(R.I.b.tn_right) // the second clicked View Note the position begins with 0. SetOnJAlertDialogCLickListener (OnJAlertDialogClickListener {view, position - >if(mbottomdialog.isshowing) {mbottomdialog.dismiss ()} when (position) { Toast.makeText(this@MainActivity,"Click the left button.",  Toast.LENGTH_SHORT).show()
                            1 -> Toast.makeText(this@MainActivity, "Click the right button", toast.length_short).show()}}).create()} /** *initUpdateDialog() { val view = LayoutInflater.from(this).inflate(R.layout.dialog_update_app, null); // Create a custom ArcBackgroundDrawable to solve the problem of setting the background of the bottom TextViev without rounded corners. @! val tv_bottom_update = view.findViewById<TextView>(R.id.tv_bottom_update); tv_bottom_update.background = ArcBackgroundDrawable() mUpdateDialog = JAlertDialog.Builder(this) .setAnimation(R.style.UpdateAnimation) .setCancelable(false) .setContentView(view) .setOnClick(R.id.iv_close_update) .setOnClick(R.id.tv_bottom_update) .setOnJAlertDialogCLickListener { view, Position -> when (position) {0 -> {// close mupdateDialog.dismiss ()} 1 -> {// Close mupdatedialog.dismiss ()} } .create() } }Copy the code

    Note that the use of the area, I have a hint ha, in fact, is to customize a layout, and then need to set the text and click, to the Settings, and finally where to pop up to change the Settings. Basically it’s ok! I don’t have too much to provide animation effects, what kind of play you need! This is more convenient in use, we use more than one project oh!

    Haha, the egg is the source code has a custom arc ArcBackgroundDrawable, you can go to see ha, is to upgrade the popover at the bottom of the arc, can solve such as a circular background, but the bottom button to the background after the arc disappeared!

    A god to be worshipped:

    1. https://www.jianshu.com/p/87288925ee1f