Android仿Ios实现Dialog圆角弹窗

转载请标明出处:https://blog.csdn.net/m0_38074457/article/details/84979890 ,本文出自:【陈少华的博客】

一、先看效果

效果图

https://github.com/hnsycsxhzcsh/IosDialog/blob/master/img/18tkr-gc4gb.gif

实现原理:

1.使用控件DialogFragment,在初始化的时候设置背景为透明,无头部

2.xml大布局是一个四角椭圆

3.底部左侧是一个左下角椭圆,底部右侧是一个右下角椭圆

二、实现大布局layout_dialog_ensure.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/dialog_fragment_circle_background"
    android:orientation="vertical">

    <TextView
        android:id="@+id/tv_message"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:padding="10dp"
        android:textColor="@color/black"
        android:textSize="18sp"
        android:textStyle="bold" />

    <include layout="@layout/view_divide" />

    <include layout="@layout/dialog_ensure_bottom" />

</LinearLayout>

大布局的背景是dialog_fragment_circle_background.xml,是一个椭圆背景

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

    <solid android:color="#FFFFFF" />

    <size
        android:width="@dimen/shape_login_buttom_300px"
        android:height="@dimen/shape_login_buttom_64px" />

    <corners
        android:bottomLeftRadius="@dimen/shape_login_buttom_64px"
        android:bottomRightRadius="@dimen/shape_login_buttom_64px"
        android:topLeftRadius="@dimen/shape_login_buttom_64px"
        android:topRightRadius="@dimen/shape_login_buttom_64px" />

</shape>

底部布局是dialog_ensure_bottom.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/dialog_fragment_circle_background_single_ensure_selected"
    android:orientation="horizontal">

    <TextView
        android:id="@+id/tv_cancel"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:background="@drawable/dialog_fragment_ensure_cancel_selector"
        android:gravity="center"
        android:paddingBottom="10dp"
        android:paddingTop="10dp"
        android:text="@string/dialog_cancel"
        android:textColor="@color/actionsheet_blue"
        android:textSize="16sp" />

    <TextView
        android:id="@+id/tv_ensure"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="0.1dp"
        android:layout_weight="1"
        android:background="@drawable/dialog_fragment_ensure_ensure_selector"
        android:gravity="center"
        android:paddingBottom="10dp"
        android:paddingTop="10dp"
        android:text="@string/dialog_ok"
        android:textColor="@color/actionsheet_red"
        android:textSize="16sp" />

</LinearLayout>

底部左侧背景是dialog_fragment_ensure_cancel_selector.xml,放在drawable包下

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

    <item android:drawable="@drawable/dialog_fragment_circle_background_ensure_cancel_selected" android:state_pressed="true"/>
    <item android:drawable="@drawable/dialog_fragment_circle_background_ensure_cancel_selected" android:state_selected="true"/>
    <item android:drawable="@drawable/dialog_fragment_circle_background_ensure_cancel_selected" android:state_checked="true"/>
    <item android:drawable="@drawable/dialog_fragment_circle_background_ensure_cancel"/>

</selector>

dialog_fragment_circle_background_ensure_cancel_selected.xml为选中状态,放在drawable包下

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

    <solid android:color="#D9D9D9" />

    <size
        android:width="@dimen/shape_login_buttom_300px"
        android:height="@dimen/shape_login_buttom_64px" />

    <corners android:bottomLeftRadius="@dimen/shape_login_buttom_64px" />

</shape>

dialog_fragment_circle_background_ensure_cancel.xml为正常状态,放在drawable包下

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

    <solid android:color="#FFFFFF" />

    <size
        android:width="@dimen/shape_login_buttom_300px"
        android:height="@dimen/shape_login_buttom_64px" />

    <corners android:bottomLeftRadius="@dimen/shape_login_buttom_64px" />

</shape>

同理底部右侧,按照底部左侧来实现

三、创建基类BaseDialogFragment对象,EnsureDialog继承此基类

初始化的时候一定要设置 对话框内部背景设置透明,和无标题
getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
public abstract class BaseDialogFragment extends DialogFragment {
    protected static final int SIZE_DEFAULT = -1;
    protected static final int SIZE_LOADING = 1;

    protected static final float COLOR_DEFAULT = 1.0f;
    protected static final float COLOR_TRANSPARENT = 0.0f;

    private int size = -1;
    private float color = 1.0f;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
                             @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(getLayoutId(), container, false);
        init(view);
        initDialog();
        return view;
    }

    public abstract int getLayoutId();

    protected abstract void init(View view);

    private void initDialog() {
        //对话框内部背景设置透明
        getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
        getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
    }

    @Override
    public void onStart() {
        super.onStart();

        if (color != COLOR_DEFAULT) {
            //如果过不是默认颜色,就设置指定color背景颜色
            Window window = getDialog().getWindow();
            WindowManager.LayoutParams windowParams = window.getAttributes();
            windowParams.dimAmount = color;

            window.setAttributes(windowParams);
        }
    }

    protected void initWindowSize(int size) {
        this.size = size;
        initWindowSize();
    }

    protected void initWindowSize() {
        Dialog dialog = getDialog();
        if (dialog != null) {
            DisplayMetrics dm = new DisplayMetrics();
            getActivity().getWindowManager().getDefaultDisplay().getMetrics(dm);
            if (size == SIZE_LOADING) {
//                dialog.getWindow().setLayout((int) (dm.widthPixels * 0.5), (int) (dm.widthPixels * 0.5));
                dialog.getWindow().setLayout(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
            } else {
                dialog.getWindow().setLayout((int) (dm.widthPixels * 0.8), ViewGroup.LayoutParams.WRAP_CONTENT);
            }
        }
    }

    protected void setOutsideColor(float color) {
        this.color = color;
    }

}
public class EnsureDialog extends BaseDialogFragment {

    private TextView mTvCancel;
    private TextView mTvEnsure;
    private TextView mTvMessage;
    private IDialogEnsureClickListener listener;

    @Override
    public int getLayoutId() {
        return R.layout.layout_dialog_ensure;
    }

    @Override
    protected void init(View view) {
        mTvCancel = (TextView) view.findViewById(R.id.tv_cancel);
        mTvEnsure = (TextView) view.findViewById(R.id.tv_ensure);
        mTvMessage = (TextView) view.findViewById(R.id.tv_message);

        Bundle args = getArguments();
        if (args != null) {
            if (args.containsKey("message")) {
                String message = args.getString("message");
                mTvMessage.setText(message);
            }

            if (args.containsKey("left")) {
                String left = args.getString("left");
                if (!TextUtils.isEmpty(left)) {
                    mTvCancel.setText(left);
                }
            }

            if (args.containsKey("right")) {
                String right = args.getString("right");
                if (!TextUtils.isEmpty(right)) {
                    mTvEnsure.setText(right);
                }
            }
        }

        mTvCancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (listener != null) {
                    listener.onCancelClick();
                }
            }
        });

        mTvEnsure.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (listener != null) {
                    listener.onEnsureClick();
                }
            }
        });


    }

    public void setOnClickListener(IDialogEnsureClickListener listener) {
        this.listener = listener;
    }

    @Override
    public void onStart() {
        super.onStart();
        initWindowSize();
    }
}

四、实现弹窗

创建EnsureDialog对象,通过bundle把需要的数据传给EnsureDialog

mBtEnsure.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                final EnsureDialog ensureDialog = new EnsureDialog();
                Bundle bundle = new Bundle();
                bundle.putString("message", "这是简单的dialog");
                ensureDialog.setArguments(bundle);
                ensureDialog.show(getSupportFragmentManager(), "ensure");

                ensureDialog.setOnClickListener(new IDialogEnsureClickListener() {
                    @Override
                    public void onEnsureClick() {
                        Toast.makeText(MainActivity.this, "点击了OK", Toast.LENGTH_SHORT).show();
                        ensureDialog.dismiss();
                    }

                    @Override
                    public void onCancelClick() {
                        Toast.makeText(MainActivity.this, "点击了Cancel", Toast.LENGTH_SHORT).show();
                        ensureDialog.dismiss();
                    }
                });
            }
        });

备注:可在github上查看具体实现代码地址为   https://github.com/hnsycsxhzcsh/IosDialog,进入github后点击右上角star谢谢支持!

gradle可直接引用

1、根目录的build.gradle中设置

allprojects {
    repositories {
        maven { url "https://jitpack.io" }
    }
}

2、app的build.gradle中引用,最后的版本可能会变化,以github上最新版本为准

implementation "com.github.hnsycsxhzcsh:IosDialog:V1.1"

猜你喜欢

转载自blog.csdn.net/m0_38074457/article/details/84979890