Android精美自定义多选控件_多选Spinner_MultiSpinner_拿来即用

交互设计

  1.首先去定义该控件:MPopListView package com.maddox.mmrrr1;import android.app.AlertDialog;import android.content.Context;import android.graphics.drawable.Drawable;import android.util.AttributeSet;import android.view.LayoutInflater;import android.view.View;import android.view.WindowManager;import android.widget.AdapterView;import android.widget.CheckBox;import android.widget.GridView;import android.widget.ImageView;import android.widget.LinearLayout;import android.widget.TextView;import android.widget.Toast;import androidx.annotation.Nullable;import java.util.ArrayList;import java.util.List;/** * @author Maddox * 2021-11-30 */public class MPopListView exts LinearLayout { private Context mContext; private MFlowLayout flowLayout; private ImageView iv_arrow; private List<DataModel> allDatas; public MPopListView(Context context) { this(context, null); } public MPopListView(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); } public MPopListView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mContext = context; LayoutInflater.from(mContext).inflate(R.layout.layout_pop_list_view, this, true); initView(); } private void initView() { allDatas = new ArrayList<>(); flowLayout = findViewById(R.id.mflowlayout); iv_arrow = findViewById(R.id.iv_arrow); iv_arrow.setOnClickListener(v -> { showPopWindow(this); }); flowLayout.setOnItemClickListener(new MFlowLayout.OnItemClickListener() { @Override public void onItemClick(View itemView, int position) { String removeName = flowLayout.removeItem(position); for (DataModel allData : allDatas) { if (allData.getText().equals(removeName)) { allData.setSelected(false); } } } }); } /** * 外部调用 * 初始化数据 * 设置所有待展示的数据 * * @param list 展示的数据 */ public void setInitList(List<DataModel> list) { allDatas.clear(); allDatas.addAll(list); } /** * 外部调用 * 返回已选择的所有数据 * * @return */ public List<DataModel> getSelectedList() { List<DataModel> selectedList = new ArrayList<>(); for (DataModel data : allDatas) { if (data.getSelected()) { selectedList.add(data); } } return selectedList; } /** * 外部调用 * 设置展示的子条目文本颜色 * * @param color 颜色值 */ public void setItemTextColor(int color) { flowLayout.setItemTextColor(color); } /** * 外部调用 * 设置展示的子条目背景颜色 * * @param drawable 自定义的Drawable类型 */ public void setItemBackgroundDrawable(Drawable drawable) { flowLayout.setItemBackgroundDrawable(drawable); } /** * 外部调用 * 设置展示的子条目文本右侧小图标,默认是x * * @param imgRes 图片资源id */ public void setItemTextIcon(int imgRes) { flowLayout.setItemTextIcon(imgRes); } /** * 外部调用 * 设置调出弹窗的图片 * * @param imgRes 图片资源 */ public void setArrowImage(int imgRes) { iv_arrow.setImageResource(imgRes); } private void setSelectDataList(List<DataModel> list) { flowLayout.setData(list); //更新所有数据中已选中的状态 for (DataModel model : list) { if (allDatas.contains(model)) { int index = allDatas.indexOf(model); allDatas.get(index).setSelected(model.getSelected()); } } } private void showPopWindow(MPopListView popListView) { View contentView = LayoutInflater.from(mContext).inflate(R.layout.layout_pop_list_view_fly_content, null, false); GridView gridView = contentView.findViewById(R.id.fly_grid_view); TextView cancleBtn = contentView.findViewById(R.id.tv_dialog_cancle); TextView confirmBtn = contentView.findViewById(R.id.tv_dialog_confirm); ListItemAdapter itemAdapter = new ListItemAdapter(mContext, allDatas, R.layout.layout_pop_list_view_fly_content_item); gridView.setAdapter(itemAdapter); gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Toast.makeText(mContext, allDatas.get(position).getText(), Toast.LENGTH_SHORT).show(); DataModel item = itemAdapter.getItem(position); item.setSelected(!item.getSelected()); itemAdapter.notifyDataSetChanged(); } }); AlertDialog alertDialog = new AlertDialog.Builder(mContext) .setView(contentView) .create(); cancleBtn.setOnClickListener(v -> { if (alertDialog != null && alertDialog.isShowing()) { alertDialog.dismiss(); } }); confirmBtn.setOnClickListener(v -> { if (alertDialog != null && alertDialog.isShowing()) { alertDialog.dismiss(); //获取已选择的 popListView.setSelectDataList(itemAdapter.getSelectedList()); } }); alertDialog.getWindow().setBackgroundDrawableResource(android.R.color.transparent); WindowManager.LayoutParams lp = alertDialog.getWindow().getAttributes(); lp.width = LayoutParams.WRAP_CONTENT; lp.height = LayoutParams.WRAP_CONTENT; alertDialog.getWindow().setAttributes(lp); alertDialog.show(); } private class ListItemAdapter exts CommonAdapter<DataModel> { public ListItemAdapter(Context mContext, List<DataModel> datas, int layoutId) { super(mContext, datas, layoutId); } @Override public void bindView(ViewHolder holder, DataModel dataModel, int position) { holder.setText(R.id.item_text, dataModel.getText()); CheckBox checkBox = holder.getView(R.id.item_checkbox); if (dataModel.getSelected()) { checkBox.setChecked(true); } else { checkBox.setChecked(false); } } public List<DataModel> getSelectedList() { List<DataModel> datas = getDatas(); List<DataModel> haveChoose = new ArrayList<>(); for (DataModel data : datas) { if (data.getSelected()) { haveChoose.add(data); } } return haveChoose; } }} 2.里面用到的类: package com.maddox.mmrrr1;import android.app.ActionBar;import android.content.Context;import android.graphics.Color;import android.graphics.drawable.Drawable;import android.util.AttributeSet;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.ImageView;import android.widget.TextView;import java.util.ArrayList;import java.util.List;import java.util.Random;/** * 流式布局 * * @author Maddox */public class MFlowLayout exts ViewGroup { private Context mContext; private int textColor = Color.WHITE;//默认展示的文本颜色 private Drawable textDrawable;//展示的文本背景色 //记录所有行的View列表 private List<List<View>> mViews = new ArrayList<>(); //记录所有行的各自最大高度 private List<Integer> mLineHeight = new ArrayList<>(); //记录当前绘制的实体数据 private List<DataModel> itemList = new ArrayList<>(); private int textIcon;//文本右侧小图片 public MFlowLayout(Context context) { this(context, null); } public MFlowLayout(Context context, AttributeSet attrs) { this(context, attrs, 0); } public MFlowLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mContext = context; } public String removeItem(int position) { String name = itemList.get(position).getText(); itemList.remove(position); List<DataModel> newList = new ArrayList<>(); newList.addAll(itemList); setData(newList); return name; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); int widthMode = MeasureSpec.getMode(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); //当前布局的最大宽度和高度 int width = 0; int height = 0; //每一行子view的宽高 int lineWidth = 0; int lineHeight = 0; int count = getChildCount(); for (int i = 0; i < count; i++) { View child = getChildAt(i); if (child.getVisibility() == GONE) { continue; } measureChild(child, widthMeasureSpec, heightMeasureSpec); MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams(); //获取每个子View的宽度 int childWidth = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin; //获取每个子View的高度 int childHeight = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin; //如果当前子View与当前行的已使用宽度超出了父布局的宽度大小,则进入下一行 if (lineWidth + childWidth > widthSize - getPaddingLeft() - getPaddingRight()) { //超出一行,先记录当前行的宽度,再去新建一行 width = Math.max(width, lineWidth); //新的一行宽度等于当前子View的宽度 lineWidth = childWidth; //记录行总高度 height += lineHeight; //记录新一行的高度 lineHeight = childHeight; } else { //如果没有换行,则累加当前子View的宽度到当前行宽度 lineWidth += childWidth; //得到行子View的最大行高度 lineHeight = Math.max(lineHeight, childHeight); } //处理最后一个子View的情况 if (i == count - 1) { width = Math.max(lineWidth, width); height += lineHeight; } } //当父布局的宽高为具体值时,就使用设置的具体值,否则使用子View的总体宽高 int resultW = widthMode == MeasureSpec.EXACTLY ? widthSize : width + getPaddingLeft() + getPaddingRight(); int resultH = heightMode == MeasureSpec.EXACTLY ? heightSize : height + getPaddingTop() + getPaddingBottom(); //设置父布局的大小 setMeasuredDimension(resultW, resultH); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { mViews.clear(); mLineHeight.clear(); //获取当前ViewGroup的宽度 int width = getWidth(); int lineWidth = 0; int lingHeight = 0; //记录当前行的View List<View> lineViews = new ArrayList<>(); int count = getChildCount(); for (int i = 0; i < count; i++) { View child = getChildAt(i); MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams(); int childWidth = child.getMeasuredWidth(); int childHeight = child.getMeasuredHeight(); if (childWidth + lineWidth + lp.leftMargin + lp.rightMargin > width - getPaddingLeft() - getPaddingRight()) { mLineHeight.add(lingHeight); mViews.add(lineViews); lineWidth = 0; lingHeight = childHeight + lp.topMargin + lp.bottomMargin; lineViews = new ArrayList<>(); } lineWidth += childWidth + lp.leftMargin + lp.rightMargin; lingHeight = Math.max(lingHeight, childHeight + lp.topMargin + lp.bottomMargin); lineViews.add(child); } //记录每行高度,为后面设置子View单独top做准备,比如 gravity mLineHeight.add(lingHeight); mViews.add(lineViews); int left = getPaddingLeft(); int top = getPaddingTop(); int lineCount = mViews.size(); for (int i = 0; i < lineCount; i++) { lineViews = mViews.get(i); lingHeight = mLineHeight.get(i); int lineViewCount = lineViews.size(); for (int j = 0; j < lineViewCount; j++) { View child = lineViews.get(j); if (child.getVisibility() == GONE) { continue; } MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams(); int cLeft = left + lp.leftMargin; int cTop = top + lp.topMargin; int cRight = child.getMeasuredWidth() + cLeft; int cBottom = cTop + child.getMeasuredHeight(); child.layout(cLeft, cTop, cRight, cBottom); left += child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin; } left = 0; top += lingHeight; } } /** * 设置填充数据 * * @param data */ public void setData(List<DataModel> data) { removeAllViews(); if (data == null data.size() <= 0) { return; } itemList.clear(); itemList.addAll(data); MarginLayoutParams lp = new MarginLayoutParams(LayoutParams.WRAP_CONTENT, ActionBar.LayoutParams.WRAP_CONTENT); lp.leftMargin = 5; lp.rightMargin = 5; lp.topMargin = 5; lp.bottomMargin = 5; //初始化布局加载器 for (int i = 0; i < data.size(); i++) { View itemView = LayoutInflater.from(mContext).inflate(R.layout.layout_flow_item, null, false); TextView itemText = itemView.findViewById(R.id.tv_item_name); ImageView itemIcon = itemView.findViewById(R.id.iv_item_icon); itemText.setText(data.get(i).getText()); itemText.setTextColor(textColor); if (textDrawable != null) { itemView.setBackground(textDrawable); } if (textIcon != 0) { itemIcon.setImageResource(textIcon); } addView(itemView, lp); } //因为是新创建的View,需要重新加载监听器 if (clickListener != null) { setOnItemClickListener(clickListener); } } private int randomColor() { Random random = new Random(); return Color.rgb(random.nextInt(256), random.nextInt(256), random.nextInt(256)); } private OnItemClickListener clickListener; /** * 设置点击事件 * * @param clickListener 点击回调 */ public void setOnItemClickListener(OnItemClickListener clickListener) { if (clickListener == null) return; this.clickListener = clickListener; int count = getChildCount(); for (int i = 0; i < count; i++) { View child = getChildAt(i); int index = i; child.setOnClickListener(v -> { this.clickListener.onItemClick(child, index); }); } } public List<DataModel> getItemList() { return itemList; } @Override public LayoutParams generateLayoutParams(AttributeSet attrs) { return new MarginLayoutParams(getContext(), attrs); } public void setItemTextColor(int color) { textColor = color; } public void setItemBackgroundDrawable(Drawable drawable) { textDrawable = drawable; } public void setItemTextIcon(int imgRes) { textIcon = imgRes; } public static interface OnItemClickListener { void onItemClick(View itemView, int position); }} 3.然后上面这个类中用到的xml layout_flow_item.xml <?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/selector_flow_item" android:padding="8dp" android:gravity="center_vertical" android:orientation="horizontal"> <TextView android:id="@+id/tv_item_name" android:layout_width="wrap_content" android:textSize="16dp" android:layout_height="wrap_content" android:clickable="true" android:textColor="#fff" tools:text="北京市" /> <ImageView android:id="@+id/iv_item_icon" android:layout_width="15dp" android:layout_height="15dp" android:layout_marginStart="5dp" android:src="@mipmap/icon_item_close" /></LinearLayout> 4.然后最上面那个自定义工具类中用到的xml文件 layout_pop_list_view.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:background="@drawable/selector_stroke_theme" android:padding="10dp" android:orientation="horizontal"> <com.maddox.mmrrr1.MFlowLayout android:id="@+id/mflowlayout" android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content" /> <ImageView android:id="@+id/iv_arrow" android:layout_width="35dp" android:layout_height="35dp" android:layout_gravity="center_vertical" android:layout_marginEnd="10dp" android:src="@mipmap/icon_select_list" /></LinearLayout> 5.然后就是上面xml文件中用到的小图片 icon_select_list ​ 这个图标仅仅是个案例,可以自己去找心仪的. 6.然后最上面控件中用到的xml文件 layout_pop_list_view_fly_content.xml package com.maddox.mmrrr1;import android.app.AlertDialog;import android.content.Context;import android.graphics.drawable.Drawable;import android.util.AttributeSet;import android.view.LayoutInflater;import android.view.View;import android.view.WindowManager;import android.widget.AdapterView;import android.widget.CheckBox;import android.widget.GridView;import android.widget.ImageView;import android.widget.LinearLayout;import android.widget.TextView;import android.widget.Toast;import androidx.annotation.Nullable;import java.util.ArrayList;import java.util.List;/** * @author Maddox * 2021-11-30 */public class MPopListView exts LinearLayout { private Context mContext; private MFlowLayout flowLayout; private ImageView iv_arrow; private List<DataModel> allDatas; public MPopListView(Context context) { this(context, null); } public MPopListView(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); } public MPopListView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mContext = context; LayoutInflater.from(mContext).inflate(R.layout.layout_pop_list_view, this, true); initView(); } private void initView() { allDatas = new ArrayList<>(); flowLayout = findViewById(R.id.mflowlayout); iv_arrow = findViewById(R.id.iv_arrow); iv_arrow.setOnClickListener(v -> { showPopWindow(this); }); flowLayout.setOnItemClickListener(new MFlowLayout.OnItemClickListener() { @Override public void onItemClick(View itemView, int position) { String removeName = flowLayout.removeItem(position); for (DataModel allData : allDatas) { if (allData.getText().equals(removeName)) { allData.setSelected(false); } } } }); } /** * 外部调用 * 初始化数据 * 设置所有待展示的数据 * * @param list 展示的数据 */ public void setInitList(List<DataModel> list) { allDatas.clear(); allDatas.addAll(list); } /** * 外部调用 * 返回已选择的所有数据 * * @return */ public List<DataModel> getSelectedList() { List<DataModel> selectedList = new ArrayList<>(); for (DataModel data : allDatas) { if (data.getSelected()) { selectedList.add(data); } } return selectedList; } /** * 外部调用 * 设置展示的子条目文本颜色 * * @param color 颜色值 */ public void setItemTextColor(int color) { flowLayout.setItemTextColor(color); } /** * 外部调用 * 设置展示的子条目背景颜色 * * @param drawable 自定义的Drawable类型 */ public void setItemBackgroundDrawable(Drawable drawable) { flowLayout.setItemBackgroundDrawable(drawable); } /** * 外部调用 * 设置展示的子条目文本右侧小图标,默认是x * * @param imgRes 图片资源id */ public void setItemTextIcon(int imgRes) { flowLayout.setItemTextIcon(imgRes); } /** * 外部调用 * 设置调出弹窗的图片 * * @param imgRes 图片资源 */ public void setArrowImage(int imgRes) { iv_arrow.setImageResource(imgRes); } private void setSelectDataList(List<DataModel> list) { flowLayout.setData(list); //更新所有数据中已选中的状态 for (DataModel model : list) { if (allDatas.contains(model)) { int index = allDatas.indexOf(model); allDatas.get(index).setSelected(model.getSelected()); } } } private void showPopWindow(MPopListView popListView) { View contentView = LayoutInflater.from(mContext).inflate(R.layout.layout_pop_list_view_fly_content, null, false); GridView gridView = contentView.findViewById(R.id.fly_grid_view); TextView cancleBtn = contentView.findViewById(R.id.tv_dialog_cancle); TextView confirmBtn = contentView.findViewById(R.id.tv_dialog_confirm); ListItemAdapter itemAdapter = new ListItemAdapter(mContext, allDatas, R.layout.layout_pop_list_view_fly_content_item); gridView.setAdapter(itemAdapter); gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Toast.makeText(mContext, allDatas.get(position).getText(), Toast.LENGTH_SHORT).show(); DataModel item = itemAdapter.getItem(position); item.setSelected(!item.getSelected()); itemAdapter.notifyDataSetChanged(); } }); AlertDialog alertDialog = new AlertDialog.Builder(mContext) .setView(contentView) .create(); cancleBtn.setOnClickListener(v -> { if (alertDialog != null && alertDialog.isShowing()) { alertDialog.dismiss(); } }); confirmBtn.setOnClickListener(v -> { if (alertDialog != null && alertDialog.isShowing()) { alertDialog.dismiss(); //获取已选择的 popListView.setSelectDataList(itemAdapter.getSelectedList()); } }); alertDialog.getWindow().setBackgroundDrawableResource(android.R.color.transparent); WindowManager.LayoutParams lp = alertDialog.getWindow().getAttributes(); lp.width = LayoutParams.WRAP_CONTENT; lp.height = LayoutParams.WRAP_CONTENT; alertDialog.getWindow().setAttributes(lp); alertDialog.show(); } private class ListItemAdapter exts CommonAdapter<DataModel> { public ListItemAdapter(Context mContext, List<DataModel> datas, int layoutId) { super(mContext, datas, layoutId); } @Override public void bindView(ViewHolder holder, DataModel dataModel, int position) { holder.setText(R.id.item_text, dataModel.getText()); CheckBox checkBox = holder.getView(R.id.item_checkbox); if (dataModel.getSelected()) { checkBox.setChecked(true); } else { checkBox.setChecked(false); } } public List<DataModel> getSelectedList() { List<DataModel> datas = getDatas(); List<DataModel> haveChoose = new ArrayList<>(); for (DataModel data : datas) { if (data.getSelected()) { haveChoose.add(data); } } return haveChoose; } }} 7.上面xml中用到的xml shape_corner_white.xml <?xml version="1.0" encoding="utf-8"?><shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <corners android:radius="15dp" /> <solid android:color="@android:color/white" /></shape> 8.最上面类中,用到的xml文件layout_pop_list_view_fly_content_item.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" xmlns:tools="http://schemas.android.com/tools" android:gravity="center_vertical" android:orientation="horizontal"> <CheckBox android:id="@+id/item_checkbox" android:layout_width="wrap_content" android:focusable="false" android:focusableInTouchMode="false" android:clickable="false" android:layout_height="wrap_content" /> <TextView android:id="@+id/item_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:ellipsize="" android:maxLines="1" tools:text="选中的条目内容" android:textColor="#000" android:textSize="17dp" /></LinearLayout> 9.上面的 layout_pop_list_view_fly_content.xml 文件中用到的xml文件 selector_tv_bg1.xml <?xml version="1.0" encoding="utf-8"?><selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="false"> <shape android:shape="rectangle"> <corners android:radius="5dp"/> <solid android:color="#f3f7f8"/> </shape> </item> <item android:state_pressed="true"> <shape android:shape="rectangle"> <corners android:radius="5dp"/> <solid android:color="#884176AC"/> </shape> </item></selector> 10.然后layout_pop_list_view.xml文件中用到的xml文件:selector_stroke_theme.xml <?xml version="1.0" encoding="utf-8"?><selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="false"> <shape android:shape="rectangle"> <corners android:radius="5dp" /> <stroke android:width="2dp" android:color="#369484"/> </shape> </item> <item android:state_pressed="true"> <shape android:shape="rectangle"> <corners android:radius="5dp" /> <stroke android:width="2dp" android:color="#26C6DA"/> </shape> </item></selector> 11.然后,我们继续看,用到的放数据的实体类: DataModel.java 接口 package com.maddox.mmrrr1;/** * 抽象出的数据类接口,以便列表用于展现数据文本 * 子类必须重写equals 和 hashcode方法 * 子类必须重写equals 和 hashcode方法 */public interface DataModel { //数据用于展示的文本 public String getText(); //获取选中状态 public boolean getSelected(); //设置选中状态 public void setSelected(boolean selected);} 12.然后 DemoModel.java 实现接口的实体类 package com.maddox.mmrrr1;import java.util.Objects;/** * @author Maddox * 2021-11-30 * 展示文本的实体实现 示例 * 必须重写equals 和 hashcode方法 * 必须重写equals 和 hashcode方法 * 必须重写equals 和 hashcode方法 * 必须重写equals 和 hashcode方法 */public class DemoModel implements DataModel { public int id;//数据id public String content;//数据内容 public boolean selected;//数据是否选中 public DemoModel() { } public DemoModel(int id, String content, boolean selected) { this.id = id; this.content = content; this.selected = selected; } @Override public String getText() { return content; } @Override public boolean getSelected() { return selected; } @Override public void setSelected(boolean selected) { this.selected = selected; } @Override public String toString() { return "DemoModel{" + "id=" + id + ", content='" + content + '\'' + ", selected=" + selected + '}'; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null getClass() != o.getClass()) return false; DemoModel demoModel = (DemoModel) o; return id == demoModel.id && Objects.equals(content, demoModel.content); } @Override public int hashCode() { return Objects.hash(id, content); }} 13.然后再去看适配器: package com.maddox.mmrrr1;import android.content.Context;import android.graphics.Bitmap;import android.util.SparseArray;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.ImageView;import android.widget.TextView;import java.util.ArrayList;import java.util.List;/** * Created by Maddox on 2022/11/15. * 通用数据适配器 Listview gridview */public abstract class CommonAdapter<T> exts BaseAdapter { /** * 数据源 */ private List<T> datas = new ArrayList<>(); private Context mContext; private int layoutId;//布局id public CommonAdapter(Context mContext, List<T> datas, int layoutId) { this.mContext = mContext; this.layoutId = layoutId; if (datas != null) this.datas.addAll(datas); } @Override public int getCount() { return datas.size(); } @Override public T getItem(int position) { return datas.get(position); } @Override public long getItemId(int position) { return position; } public List<T> getDatas() { return datas; } /** * 添加一条数据 * * @param t 数据 */ public void addOneData(T t) { datas.add(t); notifyDataSetChanged(); } public void addAll(List<T> das) { if (das != null) { datas.addAll(das); notifyDataSetChanged(); } } /** * 添加数据到指定位置 * * @param t 数据 * @param index 位置下标 */ public void addOneData(T t, int index) { datas.add(index, t); notifyDataSetChanged(); } public void clearData() { datas.clear(); notifyDataSetChanged(); } /** * 判断已有数据中是否包含t * * @param t * @return */ public boolean contains(T t) { return datas.contains(t); } /** * 移除一条数据 * * @param t */ public void removeOneData(T t) { datas.remove(t); notifyDataSetChanged(); } @Overri

标签: 交互设计