废话不多说,先直接上最终的效果图(完整代码链接在底部)
注:“小米超神”是在代码中固定添加的,为的是模拟自己新建标签功能。
FlexBoxLayout实现思路
1.为了更方便的实现选中与未选中状态,我使用的是checkbox
2.让它实现自动换行采用的FlexboxLayoutManager实现
3.为了达到复用的效果,我采取的是recycleview来实现
4.将选中的标签保存以及展示之前选中的标签,并且回传到上个页面
5.长按事件和点击事件的实现
实现过程
步骤1:呃......略过(只是样式调整,外带2个选择器。底部有完整项目的链接)。只要注意文字颜色的选择器要放在res/color文件夹下就行了。
步骤2,3:这里主要是采用recycleview+FlexBoxLayoutManager 来实现的,前者是为了达到复用的效果,减少内存消耗,后者是为了达到自动换行的效果。
首先需要在g'radle文件中添加flexbox的依赖
implementation 'com.google.android:flexbox:1.0.0'
然后再recycleview的setManager方法中加入FlexBoxLayoutManager。
FlexboxLayoutManager manager = new FlexboxLayoutManager(this);
adapter = new RecyAdapter(this, R.layout.item_recyle_layout, datas);
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(manager);
步骤4:通过使用集合存储的方式,将选中的标签放在集合中,并且转成json数据的形式回传过去
String jsonStr = "";
if (checkList.size() > 0) {
//固定添加“小米超神”标签
if (!checkList.contains("小米超神"))
checkList.add("小米超神");
jsonStr = JsonUtils.toJson(checkList);
}
Intent intent = new Intent();
intent.putExtra("jsonStr", jsonStr);
setResult(Activity.RESULT_OK, intent);
finish();
同样,需要展示之前选中的标签的话,同样也需要将之前选中的json数据格式的字符串,带到这个页面(标签中有个isCheck属性,这个在adapter中用于显示展示的状态)
//去重操作
String jsonStr = getIntent().getStringExtra("jsonStr");
if (!TextUtils.isEmpty(jsonStr)) {
checkList.addAll(JsonUtils.json2arr(jsonStr));
for (String title : checkList) {
for (int i = 0; i < datas.size(); i++) {
if (datas.get(i).getTitle().equalsIgnoreCase(title)) {//总的标签里面含有这个标签
datas.get(i).setCheck(true);
break;
} else {
if (i == datas.size() - 1)
datas.add(new TagInfo(title).setCheck(true));//不存在 ----这种情况是属于自己能够创建新标签,这个功能没做
}
}
}
}
步骤5:该步骤主要是通过recycleView的适配器来实现item的点击事件与长按事件(实现可以直接使用basequickAdapter或者自己封装)
adapter.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(ViewGroup parent, View view, Object o, int position) {
Log.i("TAG", "这个是点击事件");
String tag = datas.get(position).getTitle();
if (checkList.contains(tag)) { //当前已选中标签集合里面有该元素就删除
checkList.remove(tag);
} else {
checkList.add(tag);
}
}
@Override
public boolean onItemLongClick(ViewGroup parent, View view, Object o, int position) {
Toast.makeText(mActivity, "这个是长按事件", Toast.LENGTH_SHORT).show();
return true;
}
});
对于FlexBoxLayout想要了解更多的可以参考下面的博客
FlexboxLayout的开源地址
Google 开源的 Android 排版库:FlexboxLayout
Android可伸缩布局-FlexboxLayout(支持RecyclerView集成)
TagFlowLayout实现思路
这种方法实现的思路,就很简单了。直接采用鸿洋的开源库。具体使用方法网上一大堆,具体参考hongyangAndroid该方法使用简单粗暴,只要按照提示,集成并不困难。这里不作详细介绍。这里需要提一下的是:
该方案不支持长按事件,需要自己实现!
该方案不支持长按事件,需要自己实现!
该方案不支持长按事件,需要自己实现!
如果不需要长按需求的同学建议使用该方案,需要长按需求的也可以使用该方案。接下来就贴出该方案的长按实现方法,主要在TagAdapter中的getView()方法中实现:
@Override
public View getView(FlowLayout parent, final int position, final TagInfo info) {
final CheckBox checkBox = (CheckBox) LayoutInflater.from(mContext)
.inflate(R.layout.item_recyle_layout, mFlowLayout, false);
checkBox.setText(info.getTitle());
//通过获取父布局,来设置长点击事件
checkBox.post(new Runnable() {
@Override
public void run() { //避免创建事件监听的时候,控件还未实例化而造成空指针异常
//为了避免影响选中事件,需要对其父控件(TagView)添加长按事件
ViewParent parent1 = checkBox.getParent();
if (null == parent1) return;
TagView tagView = (TagView) parent1;
tagView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
checkBox.setTag(R.id.id_view_tag, position);
if (null != onLongClick) {
onLongClick.diyOnLongClick(position, info);
}
return true; //返回未true,onclick事件与onlongclick事件不同时发生
}
});
}
});
return checkBox;
}
通过自己定义的长按事件,在标签触发长按事件的时候,回调自己申明的长按事件。
/**
* 自定义的长按事件
*/
public interface DiyLongOnClickListener {
void diyOnLongClick(int position, TagInfo info);
}
private DiyLongOnClickListener onLongClick;
public FlowTagAdapter setOnLongClick(DiyLongOnClickListener onLongClick) {
this.onLongClick = onLongClick;
return this;
}
至此,通过上段代码,可以在该方案中实现长按事件。
最后附上完整的demo代码链接