前言
這個是一個底部彈出的對話框,簡單明了且容易使用,不會笨重。接口外露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