前言
这个是一个底部弹出的对话框,简单明了且容易使用,不会笨重。接口外露ListView适配器itemView的组装,让你可以满足各种Ui要求。
效果图:
代码部分
需要使用的布局文件,这里使用布局是想降低构造布局的复杂度,用纯代码构造布局使用起来更麻烦更复杂。只省一个布局有点本末倒置。为什么要注明这个,是因为本人以前经常干用代码实现布局的对话框,这个不是好主意。
dialog_bottom_single.xml
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/root_layout" android:background="@drawable/bg_while_rectangle_radius"> <TextView android:id="@+id/left_btn" android:layout_width="0dp" android:layout_height="wrap_content" android:gravity="left|center_vertical" android:paddingLeft="25dp" android:paddingTop="13dp" android:paddingBottom="13dp" android:textColor="@color/color_181818" android:textSize="18sp" app:layout_constraintTop_toTopOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toLeftOf="@id/title" /> <TextView android:id="@+id/title" android:layout_width="0dp" android:layout_height="wrap_content" android:gravity="center" android:paddingTop="13dp" android:paddingBottom="13dp" android:singleLine="true" android:textColor="@color/color_181818" android:textSize="18sp" app:layout_constraintTop_toTopOf="parent" app:layout_constraintLeft_toRightOf="@id/left_btn" app:layout_constraintRight_toLeftOf="@id/right_btn" /> <TextView android:id="@+id/right_btn" android:layout_width="0dp" android:layout_height="wrap_content" android:gravity="right|center_vertical" android:paddingTop="13dp" android:paddingRight="25dp" android:paddingBottom="13dp" android:textColor="@color/color_181818" android:textSize="18sp" app:layout_constraintTop_toTopOf="parent" app:layout_constraintLeft_toRightOf="@id/title" app:layout_constraintRight_toRightOf="parent" /> <View android:id="@+id/line" android:layout_width="0dp" android:layout_height="1dp" android:background="@color/color_72" app:layout_constraintTop_toBottomOf="@id/title" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent"/> <ListView android:id="@+id/content_list" android:layout_width="0dp" android:layout_height="wrap_content" app:layout_constraintTop_toBottomOf="@id/line" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent"/> </androidx.constraintlayout.widget.ConstraintLayout>
bg_while_rectangle_radius.xml
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <solid android:color="@color/ColorWhite"/> <corners android:topLeftRadius="10dp" android:topRightRadius="10dp"/> </shape>
Java代码部分
import android.content.Context; import android.content.DialogInterface; import android.graphics.drawable.ColorDrawable; import android.os.Bundle; import android.text.TextUtils; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.constraintlayout.widget.ConstraintLayout; import androidx.fragment.app.DialogFragment; import net.wt.gate.R; import java.util.List; /** * content: 底部显示的单选对话框 * time: 2020-3-16 * * @author: zhouqiang */ public class BottomSingleDialog<T> extends DialogFragment { private ConstraintLayout mRootLayout; private TextView mLeftBtn; private TextView mTitle; private TextView mRightBtn; private ListView mContentList; private OnBuildView mOnBuildView; private OnBottomSingleDialogListener<T> mListener; private BottomSingleDialogAdapter<T> mAdapter; private String mTitleContent; private String mLeftContent; private String mRightContent; private int mSelectedPosition; private BottomSingleDialog() { } public BottomSingleDialog(Context context, String title, String left, String right, int resource, @NonNull List<T> dataList, OnBuildView<T> onBuildView) { mTitleContent = title; mLeftContent = left; mRightContent = right; mOnBuildView = onBuildView; mAdapter = new BottomSingleDialogAdapter<T>(context, resource, dataList); } @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { return inflater.inflate(R.layout.dialog_bottom_single, container, false); } @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); mRootLayout = (ConstraintLayout) view.findViewById(R.id.root_layout); mLeftBtn = (TextView) view.findViewById(R.id.left_btn); mTitle = (TextView) view.findViewById(R.id.title); mRightBtn = (TextView) view.findViewById(R.id.right_btn); mContentList = (ListView) view.findViewById(R.id.content_list); mContentList.setAdapter(mAdapter); if (!TextUtils.isEmpty(mTitleContent)) { mTitle.setText(mTitleContent); } if (!TextUtils.isEmpty(mLeftContent)) { mLeftBtn.setText(mLeftContent); } if (!TextUtils.isEmpty(mRightContent)) { mRightBtn.setText(mRightContent); } initListener(); if (mListener != null) { mListener.onViewCreated(view, this); } } @Override public void onStart() { super.onStart(); WindowManager.LayoutParams params = getDialog().getWindow().getAttributes(); params.width = ViewGroup.LayoutParams.MATCH_PARENT;//设置宽度为铺满 params.gravity = Gravity.BOTTOM; getDialog().getWindow().setAttributes((WindowManager.LayoutParams) params); getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(getContext().getResources().getColor(R.color.transparent))); } @Override public void onResume() { super.onResume(); } @Override public void onStop() { super.onStop(); } @Override public void onDestroy() { super.onDestroy(); } public ConstraintLayout getRootLayout() { return mRootLayout; } public TextView getLeftBtn() { return mLeftBtn; } public TextView getTitle() { return mTitle; } public TextView getRightBtn() { return mRightBtn; } public void setOnBottomSingleDialogListener(OnBottomSingleDialogListener<T> listener) { mListener = listener; } /** * 设置选中item * * @param position */ public void setSelectedItem(int position) { mSelectedPosition = position; if (mAdapter == null) { return; } mAdapter.notifyDataSetChanged(); } /** * 更新列表内容 */ public void listNotifyDataSetChanged() { if (mAdapter == null) { return; } mAdapter.notifyDataSetChanged(); } /** * 设置指定item数量的高度 * * @param targetCount */ public void setItemCountHeight(int targetCount) { mContentList.post(new Runnable() { @Override public void run() { View view = mContentList.getChildAt(0); if (view == null) { return; } if (mContentList.getCount() < targetCount) { return; } ViewGroup.LayoutParams layoutParams = mContentList.getLayoutParams(); layoutParams.height = view.getHeight() * targetCount; mContentList.setLayoutParams(layoutParams); } }); } /** * 设置是否点击外部取消Dialog * @param isCanceledOnTouchOutside */ public void setCanceledOnTouchOutside(boolean isCanceledOnTouchOutside) { if (getDialog() != null) { getDialog().setCanceledOnTouchOutside(isCanceledOnTouchOutside); } } private void initListener() { mLeftBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (mListener != null) { mListener.onClickLeftBtn(BottomSingleDialog.this); } } }); mRightBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (mListener != null) { mListener.onClickRightBtn(BottomSingleDialog.this); } } }); getDialog().setOnCancelListener(new DialogInterface.OnCancelListener() { @Override public void onCancel(DialogInterface dialog) { if (mListener != null) { mListener.onCancel(BottomSingleDialog.this); } } }); mContentList.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { if (mListener != null) { mListener.onClickItem(position, view, BottomSingleDialog.this); } } }); } public abstract static class OnBottomSingleDialogListener<T> { /** * 对话框View在创建的时候回调,在这个回调里,你可以修改对话框所有View的Ui效果 * * @param view * @param dialog */ public void onViewCreated(View view, BottomSingleDialog<T> dialog) { } /** * 左边按钮点击 * * @param dialog */ public void onClickLeftBtn(BottomSingleDialog<T> dialog) { } /** * 右边按钮点击 * * @param dialog */ public void onClickRightBtn(BottomSingleDialog<T> dialog) { } /** * 点击ListView中的item * * @param position 点击位置 * @param itemView 点击itemView * @param dialog */ public void onClickItem(int position, View itemView, BottomSingleDialog<T> dialog) { } /** * 对话框取消 * * @param dialog */ public void onCancel(BottomSingleDialog<T> dialog) { } } public interface OnBuildView<T> { /** * 组装view并且返回 * * @param position 当前位置 * @param selectedPosition 当前选中item位置 * @param parent 父类布局 * @param layoutRes 导入的布局id * @param dataList 导入数据集合 * @return */ View onBuildView(int position, int selectedPosition, @NonNull ViewGroup parent, int layoutRes, List<T> dataList); } public class BottomSingleDialogAdapter<T> extends ArrayAdapter<T> { private int layoutRes = 0; private List<T> list; public BottomSingleDialogAdapter(@NonNull Context context, int resource, @NonNull List<T> objects) { super(context, resource, objects); layoutRes = resource; this.list = objects; } @NonNull @Override public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { if (mOnBuildView != null) { return mOnBuildView.onBuildView(position, mSelectedPosition, parent, layoutRes, list); } return super.getView(position, convertView, parent); } } }
使用例子
private void initAllReadDialog() { List<String> list = new ArrayList<>(); list.add(getString(R.string.mark_all_as_read)); list.add(getString(R.string.cancel)); mAllReadDialog = new BottomSingleDialog<String>(getContext(), getString(R.string.mark_all_notifications_of_a_message_as_read), "", "", R.layout.item_all_read_dialog, list, new BottomSingleDialog.OnBuildView<String>() { @Override public View onBuildView(int position, int selectedPosition, @NonNull ViewGroup parent, int layoutRes, List<String> dataList) { View view = LayoutInflater.from(parent.getContext()).inflate(layoutRes, parent, false); TextView textView = view.findViewById(R.id.text); textView.setText(dataList.get(position)); if (position == 0) { textView.setTextColor(getResources().getColor(R.color.color_text_yellow)); } else { textView.setTextColor(getResources().getColor(R.color.color_181818)); } return view; } }); mAllReadDialog.setOnBottomSingleDialogListener(new BottomSingleDialog.OnBottomSingleDialogListener<String>() { @Override public void onViewCreated(View view, BottomSingleDialog<String> dialog) { dialog.getLeftBtn().setVisibility(View.GONE); dialog.getRightBtn().setVisibility(View.GONE); dialog.getTitle().setTextSize(16); dialog.getTitle().setTextColor(getResources().getColor(R.color.gray99)); ViewGroup.LayoutParams layoutParams = dialog.getTitle().getLayoutParams(); layoutParams.height = UnitConversionUtil.dip2px(getContext(), 50); dialog.getTitle().setLayoutParams(layoutParams); } @Override public void onClickItem(int position, View itemView, BottomSingleDialog<String> dialog) { mAllReadDialog.dismiss(); if (position == 0) { mMessageViewModel.setMessageAllRead(); return; } } }); } private void show() { mAllReadDialog.show(getChildFragmentManager(), "AllReadDialog"); }
End