android自动循环筛选,Android实现类似京东筛选的流式布局标签(可单选/多选)

前言:很久以前的一篇文章《Android自定义PopupWindow实现流式布局筛选控件(一)》使用原生的GridLayout的实现了流式标签筛选控件不过只能单选,因为项目重构需求改变,需要能多选标签,类似京东的多条件筛选。本篇文章记录自定义TypeLabelGridLayout实现带标题类型及分割线的流式布局标签,根据属性方法可自行设置单选还是多选,是否默认选中首项等功能,并且能重置数据。

效果图:

a149c2f4d319

带标题类型的流式标签

技术实现

1.自定义GridLayout

2.GridLayout属性设置

3.TextView标签属性设置

1.重写GridLayout的属性方法

public TypeLabelGridLayout(Context context, AttributeSet attrs, int defStyle) {

super(context, attrs, defStyle);

this.context=context;

}

public TypeLabelGridLayout(Context context, AttributeSet attrs) {

super(context, attrs);

this.context=context;

}

public TypeLabelGridLayout(Context context) {

super(context);

this.context=context;

}

2.设置GridLayout的数据、属性及标签添加

2.1 添加类型描述标题

//显示每个条目类型的控件

TextView tvType = new TextView(context);

tvType.setText(listData.get(i).getTypeName());

tvType.setTextColor(titleTextColor);

tvType.setTextSize(titleTextSize);

//配置列 第一个参数是起始列标 第二个参数是占几列 title(筛选类型)应该占满整行,so -> 总列数

GridLayout.Spec columnSpec = GridLayout.spec(0,columnCount);

//配置行 第一个参数是起始行标 起始行+起始列就是一个确定的位置

GridLayout.Spec rowSpec = GridLayout.spec(row);

//将Spec传入GridLayout.LayoutParams并设置宽高为0或者WRAP_CONTENT,必须设置宽高,否则视图异常

GridLayout.LayoutParams layoutParams = new GridLayout.LayoutParams(rowSpec, columnSpec);

layoutParams.width = GridLayout.LayoutParams.WRAP_CONTENT;

layoutParams.height = GridLayout.LayoutParams.WRAP_CONTENT;

layoutParams.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);

layoutParams.bottomMargin = context.getResources().getDimensionPixelSize(R.dimen.dp_8);

addView(tvType,layoutParams);

2.2 添加类型与标签的分割线

//添加分割线

View view=new View(context);

GridLayout.LayoutParams layoutParams1 = new GridLayout.LayoutParams(rowSpec, columnSpec);

layoutParams1.width = GridLayout.LayoutParams.WRAP_CONTENT;

layoutParams1.height = context.getResources().getDimensionPixelSize(R.dimen.dp_1);

layoutParams1.setGravity(Gravity.CENTER| Gravity.BOTTOM);

view.setBackgroundColor(lineColor);

addView(view,layoutParams1);

2.3 设置GridLayout的数据及属性

/**

* 将数据设置给GridLayout

*/

@SuppressLint("RtlHardcoded")

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)

public void setGridData(List listData) {

//设置列数

setColumnCount(columnCount);

//设置行数

setRowCount(getRowCount(listData));

//将数据源设置到每个标签

for (int i = 0; i < listData.size(); i++){

//行数++

++row;

//显示每个条目类型的控件

//配置列 第一个参数是起始列标 第二个参数是占几列,so -> 总列数

GridLayout.Spec columnSpec = spec(0,columnCount);

//配置行 第一个参数是起始行标 起始行+起始列就是一个确定的位置

GridLayout.Spec rowSpec = spec(row);

//将Spec传入GridLayout.LayoutParams并设置宽高为0或者WRAP_CONTENT,必须设置宽高,否则视图异常

GridLayout.LayoutParams layoutParams = new GridLayout.LayoutParams(rowSpec, columnSpec);

//设置宽度

layoutParams.width = GridLayout.LayoutParams.WRAP_CONTENT;

//设置高度

layoutParams.height = GridLayout.LayoutParams.WRAP_CONTENT;

//设置位置

layoutParams.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);

//设置间距

layoutParams.bottomMargin = context.getResources().getDimensionPixelSize(R.dimen.dp_8);

//根据mulEnable属性值添加tab标签

if (mulEnable){

//多选

mulAddTabs(listData.get(i));

}else {

//单选

singleAddTabs(listData.get(i));

}

}

}

3.GridLayout添加单选/多选标签

3.1 添加单选标签及属性

/**

* 添加tab标签

* @param model 数据bean

* @param labelIndex 标签的标号

*/

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)

private void addSingleTabs(final FilterBean model, final int labelIndex){

boolean isSelect=false;//判断是否有选中的标签

List tabs = model.getTabs();

for (int i = 0; i < tabs.size(); i++){

if (i % columnCount == 0){

row ++;

}

final FilterBean.TableMode tab = tabs.get(i);

//显示标签的控件

final TextView label = new TextView(context);

//循环判断是否有选中的标签

isSelect = setDefaultFirst(model, isSelect, tabs, i, tab, label);

//设置标签属性

setLabel(i, tab, label);

//记录上次选中状态

if (tabs.get(i) == model.getTab()){

label.setSelected(true);

//将上次记录的标签添加到集合

labelLists.add(model.getTypeName()+"-"+tab.name);

}

//标签的点击事件

label.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

//if (tab != model.getTab()){

Log.e("rcw","index--->"+getIndex(model,labelIndex));

//清空上次选中的状态

getChildAt(getIndex(model,labelIndex)).setSelected(false);

//设置当前点击选中的tab值

model.setTab(tab);

label.setSelected(true);

selectLabel.add(label);

String labelText=label.getText().toString();

//解决tab未被点击时 ,不添加默认的“不限”数据到集合中

int flag=-1;//用于记录需要替换的位置

//默认选中

for (int i=0;i

String tvDes=labelLists.get(i);

//判断当前集合中是否包含TypeName

if (tvDes.contains(model.getTypeName())){

flag=i;

}

}

if (flag!=-1){

//先删除返回数据集合中的之前选中的

labelLists.remove(flag);

//添加当前选中的数据到集合

labelLists.add(flag,model.getTypeName()+"-"+labelText);

}

//记录选中状态下

recordStatus(labelText, flag, model);

//labelLists.add(model.getTypeName()+"-"+labelText);

Log.e("rcw","labelText--->"+model.getTypeName()+"-"+labelText);

}

// }

});

}

}

3.2 添加多选标签

/**

* 添加tab多选标签

* @param model 数据bean

*/

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)

private void mulAddTabs(final FilterBean model){

boolean isSelect=false;

List tabs = model.getTabs();

for (int i = 0; i < tabs.size(); i++){

if (i % columnCount == 0){

row ++;

}

final FilterBean.TableMode tab = tabs.get(i);

//显示标签的控件

final TextView label = new TextView(context);

//是否默认选中第一项

isSelect = setDefaultFirst(model, isSelect, tabs, i, tab, label);

//设置标签

setLabel(i, tab, label);

//记录上次选中状态

if (model.getLabels()!=null){

//存储上次选中的集合

for (int j=0;j

if (tab == model.getLabels().get(j)){

label.setSelected(true);

//解决不点击label情况下记录上次选中的状态及参数

selectTab.add(tab);

labelLists.add(model.getTypeName()+"-"+tab.name);

selectLabel.add(label);

}

}

}

//标签的点击事件

label.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

if (label.isSelected()){

label.setSelected(false);

labelLists.remove(model.getTypeName()+"-"+label.getText().toString());

Log.e("rcw","labelLists="+labelLists);

selectTab.remove(tab);

Log.e("rcw","selectTab="+selectTab.size());

Log.e("rcw","selectTab="+selectTab);

selectLabel.remove(label);

}else {

label.setSelected(true);

labelLists.add(model.getTypeName()+"-"+label.getText().toString());

Log.e("rcw","labelLists="+labelLists);

selectTab.add(tab);

Log.e("rcw","selectTab="+selectTab.size());

Log.e("rcw","selectTab="+selectTab);

selectLabel.add(label);

}

//记录选中的label

model.setLabels(selectTab);

}

});

}

//记录选中的label

model.setLabels(selectTab);

}

3.3 设置TextView标签的属性

/**

* 设置标签的属性

* @param tabIndex 标签的位置

* @param tab 标签数据

* @param label 标签控件

*/

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)

private void setLabel(int tabIndex, FilterBean.TableMode tab, TextView label) {

label.setTextSize(tabTextSize);

label.setTextColor(context.getResources().getColorStateList(labelTextColor));

label.setBackgroundDrawable(context.getResources().getDrawable(labelBg));

label.setSingleLine(true);

label.setGravity(Gravity.CENTER);

label.setEllipsize(TextUtils.TruncateAt.MIDDLE);

//上下padding值

int paddingT = context.getResources().getDimensionPixelSize(R.dimen.dp_8);

//左右padding值

int paddingL = context.getResources().getDimensionPixelSize(R.dimen.dp_8);

label.setPadding(paddingL,paddingT,paddingL,paddingT);

//getItemLayoutParams用于设置label标签的参数

addView(label,getItemLayoutParams(tabIndex,row));

label.setText(tab.name);

}

注:颜色及padding值需要使用getResourese方法获取

3.4 默认选中的方法

/**

* 设置是否默认选中

* @param model model

* @param isSelect boolean

* @param tabs tabs

* @param i 下标

* @param tab tab

* @param label 标签

* @return boolean

*/

private boolean setDefaultFirst(FilterBean model, boolean isSelect, List tabs, int i, FilterBean.TableMode tab, TextView label) {

//循环判断是否有选中的标签

for (int j = 0; j < tabs.size(); j++){

if (tabs.get(j) == model.getTab()){

isSelect=true;

}

}

//没有选中的标签则,设置默认选中第一个

if (i==0&&!isSelect&&defaultFirst) {

//每个tab的第一个设置为选中

label.setSelected(true);

//记录选中的tab值

model.setTab(tab);

}

return isSelect;

}

4.自定义TypeLabelGridLayout的公共属性方法

4.1 标签字体大小

/**

* tab标签字体大小

* @param tabTextSize 标签字体大小

*/

public void setLabelSize(int tabTextSize) {

this.tabTextSize = tabTextSize;

}

4.2 标签字体颜色

/**

* tab标签字体颜色

* @param labelTextColor 颜色

*/

public void setLabelColor(int labelTextColor) {

this.labelTextColor = labelTextColor;

}

注:color属性是res文件下的color不是values文件下的color

4.3 标题的字体大小

/**

* 标题字体大小

* @param titleTextSize 字体大小

*/

public void setTitleSize(int titleTextSize) {

this.titleTextSize = titleTextSize;

}

4.4 标题的字体颜色

/**

* 标题字体颜色

* @param titleTextColor 颜色

*/

public void setTitleColor(int titleTextColor) {

this.titleTextColor = titleTextColor;

}

4.5 标签背景色

/**

* 设置标签的背景色

* @param labelBg 背景色(drawable)

*/

public void setLabelBg(int labelBg) {

this.labelBg = labelBg;

}

4.6 设置是否能多选

/**

* 设置标签是否可以多选

* @param mulEnable 是否可以多选标签

*/

public void setMulEnable(boolean mulEnable){

this.mulEnable = mulEnable;

}

4.7 设置GridLayout的列数

/**

* 设置gridLayout的列数

* @param columnCount 列数

*/

public void setColumnCount(int columnCount){

this.columnCount = columnCount;

}

4.8 重置数据的方法

/**

* 重置数据

*/

public void resetData(){

for (int i=0;i

selectLabel.get(i).setSelected(false);

}

selectTab.clear();

labelLists.clear();

}

4.9 设置是否默认选中第一项

/**

* 设置标签是否默认选中首项

* @param defaultFirst 是否默认选中首项

*/

public void setDefaultFirst(boolean defaultFirst){

this.defaultFirst = defaultFirst;

}

5.控件使用

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)

private void setViewData() {

if (isMul){

tvTitle.setText("带标题的标签(多选)");

lglLabel.setMulEnable(true);

}else {

tvTitle.setText("带标题的标签(单选)");

lglLabel.setMulEnable(false);

}

lglLabel.setColumnCount(3);

lglLabel.setLabelBg(R.drawable.flow_popup);

lglLabel.setGridData(labelLists);

}

总结:通过自定义TypeLabelGridLayout的方式,实现了类似京东筛选的流式布局的筛选控件,并通过属性方法设置标签属性及实现可控制的单选或多选。

如有任何疑问,欢迎评论留言,谢谢!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值