美文网首页Android自定义控件
热门标签,流式标签的实现

热门标签,流式标签的实现

作者: 木小伍 | 来源:发表于2018-07-13 13:47 被阅读152次
    废话不多说,先直接上最终的效果图(完整代码链接在底部) flexboxLayout.png
    选中的标签.png

    注:“小米超神”是在代码中固定添加的,为的是模拟自己新建标签功能。

    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.<String>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代码链接

    相关文章

      网友评论

        本文标题:热门标签,流式标签的实现

        本文链接:https://www.haomeiwen.com/subject/cijzuftx.html