欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android?自定義?Dialog?實(shí)現(xiàn)列表?單選、多選、搜索功能

 更新時間:2024年10月25日 10:50:18   作者:約翰先森不喝酒  
Android開發(fā)經(jīng)常需要用到對話框來進(jìn)行信息的篩選和搜索,本文詳細(xì)介紹了如何使用自定義Dialog結(jié)合RecyclerView和搜索框?qū)崿F(xiàn)這一功能,通過Builder模式構(gòu)建復(fù)雜的Dialog對象,使得代碼更加靈活和易于維護(hù),文中提供了詳細(xì)的步驟和代碼注釋

前言

在Android開發(fā)中,通過對話框讓用戶選擇,篩選信息是很方便也很常見的操作。本文詳細(xì)介紹了如何使用自定義 Dialog、RecyclerView 以及自定義搜索框 來實(shí)現(xiàn)選中狀態(tài)和用戶交互,文中大本分代碼都有明確注釋,主打一個簡單明了,實(shí)際效果如下,可單選,全選,精準(zhǔn)查找,選擇狀態(tài)變化,以及信息回調(diào)

一、Builder 模式

說到自定義 Dialog,就不得不提到 Builder模式,

Android系統(tǒng)中的Builder設(shè)計模式是一種創(chuàng)建型設(shè)計模式,它主要用于構(gòu)建一個復(fù)雜對象,并將其構(gòu)建過程與表示分離,Builder設(shè)計模式通過將一個復(fù)雜對象的構(gòu)建過程拆解成一系列簡單的步驟,使得構(gòu)建過程更加靈活、可讀和易于擴(kuò)展。它允許用戶在不知道內(nèi)部構(gòu)建細(xì)節(jié)的情況下,可以更精細(xì)地控制對象的構(gòu)造流程。

在Android開發(fā)中,Builder模式的一個常見應(yīng)用是AlertDialog.Builder。AlertDialog是一個復(fù)雜的對話框?qū)ο螅鄠€屬性和方法。使用AlertDialog.Builder可以方便地構(gòu)建和顯示對話框,而無需直接操作AlertDialog對象。例如:

AlertDialog.Builder builder = new AlertDialog.Builder(context);  
builder.setIcon(R.drawable.icon);  
builder.setTitle("頭部");  
builder.setMessage("內(nèi)容");  
builder.setPositiveButton("Button1", new DialogInterface.OnClickListener() {  
    public void onClick(DialogInterface dialog, int whichButton) {  
        // 處理點(diǎn)擊事件  
    }  
});  
builder.create().show(); // 構(gòu)建并顯示對話框

綜上所述,Builder設(shè)計模式在Android開發(fā)中具有重要的應(yīng)用價值。它可以幫助開發(fā)者構(gòu)建復(fù)雜對象,提高代碼的可讀性和可維護(hù)性,同時支持靈活的構(gòu)建過程和對象變種。

二、使用步驟

1. 自定義 SerachSelectDialog

public class SerachSelectDialog extends Dialog {
    private static SearchSelectAdapter sa;
    private static String result;
    private static List<String> resultList = new ArrayList<>();
    private static List<String> selectedItems;
    private static int searchPosition;
    public SerachSelectDialog(Context context, int themeResId) {
        super(context, themeResId);
    }
    /**
     * 設(shè)置 Dialog的大小
     *
     * @param x 寬比例
     * @param y 高比例
     */
    public void setDialogWindowAttr(double x, double y, Activity activity) {
        if (x < 0 || x > 1 || y < 0 || y > 1) {
            return;
        }
        Window window = this.getWindow();
        WindowManager.LayoutParams lp = window.getAttributes();
        WindowManager manager = activity.getWindowManager();
        DisplayMetrics outMetrics = new DisplayMetrics();
        manager.getDefaultDisplay().getMetrics(outMetrics);
        int width = outMetrics.widthPixels;
        int height = outMetrics.heightPixels;
        lp.gravity = Gravity.BOTTOM;
        lp.width = (int) (width * x);
        lp.height = (int) (height * y);
        this.getWindow().setAttributes(lp);
    }
    public static class Builder {
        private String title;
        private View contentView;
        private String positiveButtonText;
        private String negativeButtonText;
        private List<ItemModel> listData;
        private View.OnClickListener positiveButtonClickListener;
        private View.OnClickListener negativeButtonClickListener;
        private View.OnClickListener singleButtonClickListener;
        private View layout;
        private Context context;
        private SerachSelectDialog dialog;
        private OnSelectedListiner selectedListiner;
        SearchView searchView;
        LinearLayout closeBtn;
        LinearLayout okBtn;
        TextView titleView;
        private boolean state = false;
        private RecyclerView itemLv;
        private final TextView qxTv;
        //初始化
        public Builder(Context context) {
            //這里傳入自定義的style,直接影響此Dialog的顯示效果。style具體實(shí)現(xiàn)見style.xml
            this.context = context;
            dialog = new SerachSelectDialog(context, R.style.selectDialog);
            LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            layout = inflater.inflate(R.layout.dialog_select_search, null);
            qxTv = layout.findViewById(R.id.qx_tv);
            itemLv = layout.findViewById(R.id.item_lv);
            searchView = layout.findViewById(R.id.searchView);
            closeBtn = layout.findViewById(R.id.diss_layout);
            okBtn = layout.findViewById(R.id.ok_layout);
            titleView = layout.findViewById(R.id.title_tv);
            dialog.addContentView(layout, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
        }
        public Builder setTitle(String title) {
            this.title = title;
            return this;
        }
        public void setListData(List<ItemModel> listData) {
            this.listData = listData;
        }
        /**
         * 單按鈕對話框和雙按鈕對話框的公共部分在這里設(shè)置
         */
        private SerachSelectDialog create() {
            GridLayoutManager gridLayoutManager = new GridLayoutManager(context, 3);
            sa = new SearchSelectAdapter(listData);
            itemLv.setLayoutManager(gridLayoutManager);
            itemLv.setAdapter(sa);
            //搜索事件
            searchView.setSearchViewListener(new SearchView.onSearchViewListener() {
                @Override
                public boolean onQueryTextChange(String text) {
                    updateLayout(searchItem(text));
                    return false;
                }
            });
            //全選
            qxTv.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (sa.getSelectedItemPositions().size() == sa.getItemCount()) {
                        sa.clearSelection();
                    } else {
                        sa.selectAll();
                        resultList = sa.getSelectedItems();
                    }
                }
            });
            //取消按鈕
            closeBtn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    dialog.dismiss();
                    resultList.clear();
                }
            });
            //確認(rèn)按鈕
            okBtn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    String json = new Gson().toJson(resultList);
                    selectedListiner.onSelected(json);
                    dialog.dismiss();
                    resultList.clear();
                }
            });
            dialog.setOnDismissListener(new OnDismissListener() {
                @Override
                public void onDismiss(DialogInterface dialog) {
                }
            });
            //item點(diǎn)擊事件
            sa.setOnItemClickListener(new SearchSelectAdapter.OnItemClickListener() {
                @Override
                public void onItemClick(int position) {
                    boolean selected = listData.get(position).isSelected();
                    result = listData.get(position).getItemName();
                    if (selected == true) {
                        resultList.add(result);
                    } else {
                        resultList.remove(result);
                    }
                    Log.i("U--", resultList.toString() + selected + "");
                }
            });
            dialog.setContentView(layout);
            //用戶可以點(diǎn)擊手機(jī)Back鍵取消對話框顯示
            dialog.setCancelable(true);
            //用戶不能通過點(diǎn)擊對話框之外的地方取消對話框顯示
            dialog.setCanceledOnTouchOutside(false);
            return dialog;
        }
        //在數(shù)據(jù)源中查找匹配的數(shù)據(jù)
        public List<ItemModel> searchItem(String name) {
            ArrayList<ItemModel> mSearchList = new ArrayList<ItemModel>();
            for (int i = 0; i < listData.size(); i++) {
                int index = listData.get(i).getItemName().indexOf(name);
                // 存在匹配的數(shù)據(jù)
                if (index != -1) {
                    mSearchList.add(listData.get(i));
                    Log.i("U--", i + "搜索位置");
                    searchPosition = i;
                }
            }
            return mSearchList;
        }
        //提供匹配后的的數(shù)據(jù)進(jìn)行數(shù)據(jù)回調(diào)
        public void updateLayout(List<ItemModel> newList) {
            final SearchSelectAdapter sa = new SearchSelectAdapter(newList);
            GridLayoutManager gridLayoutManager = new GridLayoutManager(context, 3);
            itemLv.setLayoutManager(gridLayoutManager);
            itemLv.setAdapter(sa);
            //item點(diǎn)擊事件
            sa.setOnItemClickListener(new SearchSelectAdapter.OnItemClickListener() {
                @Override
                public void onItemClick(int position) {
                    result = newList.get(position).getItemName();
                    boolean selected = listData.get(searchPosition).isSelected();
                    if (selected == true) {
                        resultList.add(result);
                    } else {
                        resultList.remove(result);
                    }
                    Log.i("U--", resultList.toString() + selected + "");
                }
            });
        }
        //自定義接口進(jìn)行數(shù)據(jù)點(diǎn)擊回傳
        public static abstract class OnSelectedListiner {
            public abstract void onSelected(String String);
        }
        public void setSelectedListiner(SerachSelectDialog.Builder.OnSelectedListiner selectedListiner) {
            this.selectedListiner = selectedListiner;
        }
        //彈框展示
        public SerachSelectDialog show() {
            create();
            dialog.show();
            return dialog;
        }
    }
}

2.自定義搜索框 SearchView

UI 主要包括輸入框,刪除鍵 ,主要通過監(jiān)聽EditText 的文本以及輸入框的變化,設(shè)置搜索回調(diào)接口來實(shí)現(xiàn)

public class SearchView extends LinearLayout implements View.OnClickListener {
    /**
     * 輸入框
     */
    private EditText etInput;
    /**
     * 刪除鍵
     */
    private ImageView ivDelete;
    /**
     * 上下文對象
     */
    private Context mContext;
    /**
     * 搜索回調(diào)接口
     */
    private onSearchViewListener mListener;
    /**
     * 設(shè)置搜索回調(diào)接口
     *
     * @param listener 監(jiān)聽者
     */
    public void setSearchViewListener(onSearchViewListener listener) {
        mListener = listener;
    }
    public SearchView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
        LayoutInflater.from(context).inflate(R.layout.view_search_layout, this);
        initViews();
    }
    private void initViews() {
        etInput = (EditText) findViewById(R.id.et_search_text);
        ivDelete = (ImageView) findViewById(R.id.imb_search_clear);
        ivDelete.setOnClickListener(this);
        etInput.addTextChangedListener(new EditChangedListener());
        etInput.setOnClickListener(this);
    }
    private class EditChangedListener implements TextWatcher {
        @Override
        public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) {
        }
        @Override
        public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) {
            if (!"".equals(charSequence.toString())) {
                ivDelete.setVisibility(VISIBLE);
                //更新autoComplete數(shù)據(jù)
                if (mListener != null) {
                    mListener.onQueryTextChange(charSequence + "");
                }
            } else {
                ivDelete.setVisibility(GONE);
            }
        }
        @Override
        public void afterTextChanged(Editable editable) {
        }
    }
    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.imb_search_clear:
                etInput.setText("");
                if (mListener != null) {
                    mListener.onQueryTextChange("");
                }
                ivDelete.setVisibility(GONE);
                break;
        }
    }
    /**
     * search view回調(diào)方法
     */
    public interface onSearchViewListener {
        boolean onQueryTextChange(String text);
    }
}  

3.SearchSelectAdapter

主要實(shí)現(xiàn)條目的點(diǎn)擊事件以及數(shù)據(jù)回調(diào)

public class SearchSelectAdapter extends RecyclerView.Adapter<SearchSelectAdapter.ViewHolder> {
    private List<ItemModel> itemList;
    private List<Integer> selectedItemPositions;
    //聲明接口
    private OnItemClickListener onItemClickListener;
    public SearchSelectAdapter(List<ItemModel> itemList) {
        this.itemList = itemList;
        selectedItemPositions = new ArrayList<>();
    }
    @Override
    public int getItemCount() {
        return itemList.size();
    }
    public void setOnItemClickListener(OnItemClickListener listener) {
        this.onItemClickListener = listener;
    }
    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        // 創(chuàng)建ViewHolder
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_cell_select_single, parent, false);
        return new ViewHolder(view);
    }
    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        // 綁定數(shù)據(jù)到ViewHolder
        ItemModel item = itemList.get(position);
        holder.textView.setText(item.getItemName());
        //給條目布局設(shè)置點(diǎn)擊事件
        holder.itemLayout.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (selectedItemPositions.contains(position)) {
                    selectedItemPositions.remove(Integer.valueOf(position));
                    holder.textView.setTextColor(Color.BLACK);
                    holder.itemView.setBackgroundResource(R.drawable.item_grey_layout_bg);
                    item.setSelected(false);
                } else {
                    selectedItemPositions.add(position);
                    holder.textView.setTextColor(Color.WHITE);
                    holder.itemView.setBackgroundResource(R.drawable.item_blue_layout_bg);
                    item.setSelected(true);
                }
                if (onItemClickListener != null) {
                    onItemClickListener.onItemClick(position);
                }
            }
        });
        if (selectedItemPositions.contains(position)) {
            holder.textView.setTextColor(Color.WHITE);
            holder.itemView.setBackgroundResource(R.drawable.item_blue_layout_bg);
        } else {
            holder.textView.setTextColor(Color.BLACK);
            holder.itemView.setBackgroundResource(R.drawable.item_grey_layout_bg);
        }
    }
    /**
     * 接口回調(diào)
     */
    public interface OnItemClickListener {
        void onItemClick(int position);
    }
    public void selectAll() {
        selectedItemPositions.clear();
        for (int i = 0; i < itemList.size(); i++) {
            selectedItemPositions.add(i);
        }
        notifyDataSetChanged();
    }
    public void clearSelection() {
        selectedItemPositions.clear();
        notifyDataSetChanged();
    }
    public List<Integer> getSelectedItemPositions() {
        return selectedItemPositions;
    }
    public List<String> getSelectedItems() {
        List<String> selectedItems = new ArrayList<>();
        for (int position : selectedItemPositions) {
            selectedItems.add(itemList.get(position).getItemName());
        }
        return selectedItems;
    }
    public static class ViewHolder extends RecyclerView.ViewHolder {
        private final TextView textView;
        private final LinearLayout itemLayout;
        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            textView = itemView.findViewById(R.id.tv_select_info);
            itemLayout = itemView.findViewById(R.id.item_layout);
        }
    }
}

4.xml 布局

dialog_select_search.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="match_parent"
    android:orientation="vertical">
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/item_white_layout"
        android:orientation="vertical">
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="50dp">
            <TextView
                android:id="@+id/title_tv"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerInParent="true"
                android:text="崗位選擇"
                android:textColor="@color/black" />
        </RelativeLayout>
        <com.example.dialoglistview.SearchView
            android:id="@+id/searchView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
        <TextView
            android:id="@+id/qx_tv"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="20dp"
            android:layout_marginTop="@dimen/dp_10"
            android:text="全選"
            android:textSize="16sp" />
        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/item_lv"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
        <View
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:background="@color/grey" />
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:background="@color/transparent"
            android:gravity="center"
            android:orientation="horizontal">
            <LinearLayout
                android:id="@+id/diss_layout"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:gravity="center">
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="取消"
                    android:textColor="@color/sea_blue" />
            </LinearLayout>
            <View
                android:layout_width="1dp"
                android:layout_height="match_parent"
                android:background="@color/grey" />
            <LinearLayout
                android:id="@+id/ok_layout"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:gravity="center">
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="確定"
                    android:textColor="@color/sea_blue" />
            </LinearLayout>
        </LinearLayout>
    </LinearLayout>
</LinearLayout>

view_search_layout.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="50dp"
    android:background="#ffffff"
    android:gravity="center"
    android:orientation="vertical">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="35dp"
        android:layout_marginLeft="15dp"
        android:layout_marginRight="15dp"
        android:background="@drawable/item_search_layout"
        android:gravity="center_vertical"
        android:orientation="horizontal">
        <ImageButton
            android:id="@+id/imb_search_search"
            android:layout_width="20dp"
            android:layout_height="20dp"
            android:layout_marginLeft="15dp"
            android:background="#F0F0F0"
            android:scaleType="centerInside"
            android:src="@mipmap/im_search_back" />
        <EditText
            android:id="@+id/et_search_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="15dp"
            android:layout_weight="1"
            android:background="@null"
            android:hint="請輸入搜索內(nèi)容"
            android:lines="1"
            android:textSize="14sp" />
        <ImageButton
            android:id="@+id/imb_search_clear"
            android:layout_width="35dp"
            android:layout_height="35dp"
            android:layout_marginRight="20dp"
            android:background="#F0F0F0"
            android:padding="12.5dp"
            android:scaleType="centerInside"
            android:src="@mipmap/delet_zhaopian_1x"
            android:visibility="gone" />
    </LinearLayout>
</LinearLayout>

5.數(shù)據(jù)支持

// 創(chuàng)建數(shù)據(jù)列表
itemList = new ArrayList<>();
itemList.add(new ItemModel("醫(yī)生", false));
itemList.add(new ItemModel("警察", false));
itemList.add(new ItemModel("護(hù)士", false));
itemList.add(new ItemModel("農(nóng)民", false));
itemList.add(new ItemModel("工人", false));
itemList.add(new ItemModel("司機(jī)", false));
public class ItemModel {
    private String itemName;
    private boolean isSelected;
    public ItemModel(String itemName, boolean isSelected) {
        this.itemName = itemName;
        this.isSelected = isSelected;
    }
    public String getItemName() {
        return itemName;
    }
    public void setItemName(String itemName) {
        this.itemName = itemName;
    }
    public boolean isSelected() {
        return isSelected;
    }
    public void setSelected(boolean selected) {
        isSelected = selected;
    }
}

6.實(shí)際應(yīng)用

    private void openSearchSelectDialog() {
        SerachSelectDialog.Builder alert = new SerachSelectDialog.Builder(this);
        alert.setListData(itemList);
        alert.setTitle("崗位選擇");
        alert.setSelectedListiner(new SerachSelectDialog.Builder.OnSelectedListiner() {
            @Override
            public void onSelected(String info) {
                okTv.setText(info);
            }
        });
        SerachSelectDialog mDialog = alert.show();
        //設(shè)置Dialog 尺寸
        mDialog.setDialogWindowAttr(0.9, 0.9, this);
    }

三、總結(jié)

后續(xù) Demo 會上傳

到此這篇關(guān)于Android 自定義 Dialog 實(shí)現(xiàn)列表 單選,多選,搜索功能的文章就介紹到這了,更多相關(guān)Android 自定義 Dialog 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論