Android动态的编辑标签布局,可添加,可删除。标签颜色随机变换。

时间:2024-04-09 20:55:11

先看下效果图-------------------

Android动态的编辑标签布局,可添加,可删除。标签颜色随机变换。

首先说一下思路,看到这个设计图的时候首先想到的是流式布局,flowlayou。这个方法可以实现,但是在做删除处理的时候有点难度(也可以实现),后来我就想如果是个recuyclerview就好操作了,于是有了接下来的自定义layoutmanager。

先看一下layoutmanager代码如下:::

//
// (powered by Fernflower decompiler)
//

package com.library.flowlayout;

import android.graphics.Rect;
import android.support.v7.widget.RecyclerView.LayoutManager;
import android.support.v7.widget.RecyclerView.LayoutParams;
import android.support.v7.widget.RecyclerView.Recycler;
import android.support.v7.widget.RecyclerView.State;
import android.util.Log;
import android.util.SparseArray;
import android.view.View;
import java.util.ArrayList;
import java.util.List;

public class FlowLayoutManager extends LayoutManager {
    private static final String TAG = FlowLayoutManager.class.getSimpleName();
    final FlowLayoutManager self = this;
    protected int width;
    protected int height;
    private int left;
    private int top;
    private int right;
    private int usedMaxWidth;
    private int verticalScrollOffset = 0;
    protected int totalHeight = 0;
    private FlowLayoutManager.Row row = new FlowLayoutManager.Row();
    private List<FlowLayoutManager.Row> lineRows = new ArrayList();
    private SparseArray<Rect> allItemFrames = new SparseArray();

    public int getTotalHeight() {
        return this.totalHeight;
    }

    public FlowLayoutManager() {
        this.setAutoMeasureEnabled(true);
    }

    public LayoutParams generateDefaultLayoutParams() {
        return new LayoutParams(-2, -2);
    }

    public void onLayoutChildren(Recycler recycler, State state) {
        Log.d(TAG, "onLayoutChildren");
        if (this.getItemCount() == 0) {
            this.detachAndScrapAttachedViews(recycler);
            this.verticalScrollOffset = 0;
        } else if (this.getChildCount() != 0 || !state.isPreLayout()) {
            this.detachAndScrapAttachedViews(recycler);
            if (this.getChildCount() == 0) {
                this.width = this.getWidth();
                this.height = this.getHeight();
                this.left = this.getPaddingLeft();
                this.right = this.getPaddingRight();
                this.top = this.getPaddingTop();
                this.usedMaxWidth = this.width - this.left - this.right;
            }

            this.totalHeight = 0;
            int cuLineTop = this.top;
            int cuLineWidth = 0;
            int maxHeightItem = 0;
            this.row = new FlowLayoutManager.Row();
            this.lineRows.clear();
            this.allItemFrames.clear();
            this.removeAllViews();

            for(int i = 0; i < this.getItemCount(); ++i) {
                Log.d(TAG, "index:" + i);
                View childAt = recycler.getViewForPosition(i);
                if (8 != childAt.getVisibility()) {
                    this.measureChildWithMargins(childAt, 0, 0);
                    int childWidth = this.getDecoratedMeasuredWidth(childAt);
                    int childHeight = this.getDecoratedMeasuredHeight(childAt);
                    int itemLeft;
                    Rect frame;
                    if (cuLineWidth + childWidth <= this.usedMaxWidth) {
                        itemLeft = this.left + cuLineWidth;
                        frame = (Rect)this.allItemFrames.get(i);
                        if (frame == null) {
                            frame = new Rect();
                        }

                        frame.set(itemLeft, cuLineTop, itemLeft + childWidth, cuLineTop + childHeight);
                        this.allItemFrames.put(i, frame);
                        cuLineWidth += childWidth;
                        maxHeightItem = Math.max(maxHeightItem, childHeight);
                        this.row.addViews(new FlowLayoutManager.Item(childHeight, childAt, frame));
                        this.row.setCuTop((float)cuLineTop);
                        this.row.setMaxHeight((float)maxHeightItem);
                    } else {
                        this.formatAboveRow();
                        cuLineTop += maxHeightItem;
                        this.totalHeight += maxHeightItem;
                        itemLeft = this.left;
                        frame = (Rect)this.allItemFrames.get(i);
                        if (frame == null) {
                            frame = new Rect();
                        }

                        frame.set(itemLeft, cuLineTop, itemLeft + childWidth, cuLineTop + childHeight);
                        this.allItemFrames.put(i, frame);
                        cuLineWidth = childWidth;
                        maxHeightItem = childHeight;
                        this.row.addViews(new FlowLayoutManager.Item(childHeight, childAt, frame));
                        this.row.setCuTop((float)cuLineTop);
                        this.row.setMaxHeight((float)childHeight);
                    }

                    if (i == this.getItemCount() - 1) {
                        this.formatAboveRow();
                        this.totalHeight += maxHeightItem;
                    }
                }
            }

            this.totalHeight = Math.max(this.totalHeight, this.getVerticalSpace());
            this.fillLayout(recycler, state);
        }
    }

    private void fillLayout(Recycler recycler, State state) {
        if (!state.isPreLayout()) {
            Rect displayFrame = new Rect(this.getPaddingLeft(), this.getPaddingTop() + this.verticalScrollOffset, this.getWidth() - this.getPaddingRight(), this.verticalScrollOffset + (this.getHeight() - this.getPaddingBottom()));

            for(int j = 0; j < this.lineRows.size(); ++j) {
                FlowLayoutManager.Row row = (FlowLayoutManager.Row)this.lineRows.get(j);
                float lineTop = row.cuTop;
                float lineBottom = lineTop + row.maxHeight;
                List views;
                int i;
                View scrap;
                if (lineTop < (float)displayFrame.bottom && (float)displayFrame.top < lineBottom) {
                    views = row.views;

                    for(i = 0; i < views.size(); ++i) {
                        scrap = ((FlowLayoutManager.Item)views.get(i)).view;
                        this.measureChildWithMargins(scrap, 0, 0);
                        this.addView(scrap);
                        Rect frame = ((FlowLayoutManager.Item)views.get(i)).rect;
                        this.layoutDecoratedWithMargins(scrap, frame.left, frame.top - this.verticalScrollOffset, frame.right, frame.bottom - this.verticalScrollOffset);
                    }
                } else {
                    views = row.views;

                    for(i = 0; i < views.size(); ++i) {
                        scrap = ((FlowLayoutManager.Item)views.get(i)).view;
                        this.removeAndRecycleView(scrap, recycler);
                    }
                }
            }

        }
    }

    private void formatAboveRow() {
        List<FlowLayoutManager.Item> views = this.row.views;

        for(int i = 0; i < views.size(); ++i) {
            FlowLayoutManager.Item item = (FlowLayoutManager.Item)views.get(i);
            View view = item.view;
            int position = this.getPosition(view);
            if ((float)((Rect)this.allItemFrames.get(position)).top < this.row.cuTop + (this.row.maxHeight - (float)((FlowLayoutManager.Item)views.get(i)).useHeight) / 2.0F) {
                Rect frame = (Rect)this.allItemFrames.get(position);
                if (frame == null) {
                    frame = new Rect();
                }

                frame.set(((Rect)this.allItemFrames.get(position)).left, (int)(this.row.cuTop + (this.row.maxHeight - (float)((FlowLayoutManager.Item)views.get(i)).useHeight) / 2.0F), ((Rect)this.allItemFrames.get(position)).right, (int)(this.row.cuTop + (this.row.maxHeight - (float)((FlowLayoutManager.Item)views.get(i)).useHeight) / 2.0F + (float)this.getDecoratedMeasuredHeight(view)));
                this.allItemFrames.put(position, frame);
                item.setRect(frame);
                views.set(i, item);
            }
        }

        this.row.views = views;
        this.lineRows.add(this.row);
        this.row = new FlowLayoutManager.Row();
    }

    public boolean canScrollVertically() {
        return true;
    }

    public int scrollVerticallyBy(int dy, Recycler recycler, State state) {
        Log.d("TAG", "totalHeight:" + this.totalHeight);
        int travel = dy;
        if (this.verticalScrollOffset + dy < 0) {
            travel = -this.verticalScrollOffset;
        } else if (this.verticalScrollOffset + dy > this.totalHeight - this.getVerticalSpace()) {
            travel = this.totalHeight - this.getVerticalSpace() - this.verticalScrollOffset;
        }

        this.verticalScrollOffset += travel;
        this.offsetChildrenVertical(-travel);
        this.fillLayout(recycler, state);
        return travel;
    }

    private int getVerticalSpace() {
        return this.self.getHeight() - this.self.getPaddingBottom() - this.self.getPaddingTop();
    }

    public int getHorizontalSpace() {
        return this.self.getWidth() - this.self.getPaddingLeft() - this.self.getPaddingRight();
    }

    public class Row {
        float cuTop;
        float maxHeight;
        List<FlowLayoutManager.Item> views = new ArrayList();

        public Row() {
        }

        public void setCuTop(float cuTop) {
            this.cuTop = cuTop;
        }

        public void setMaxHeight(float maxHeight) {
            this.maxHeight = maxHeight;
        }

        public void addViews(FlowLayoutManager.Item view) {
            this.views.add(view);
        }
    }

    public class Item {
        int useHeight;
        View view;
        Rect rect;

        public void setRect(Rect rect) {
            this.rect = rect;
        }

        public Item(int useHeight, View view, Rect rect) {
            this.useHeight = useHeight;
            this.view = view;
            this.rect = rect;
        }
    }
}

下面是Mainactivity代码就非常简单了 :::
package com.example.taglayout;

import android.content.Intent;
import android.graphics.Color;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.AdapterView;

import com.chad.library.adapter.base.BaseQuickAdapter;
import com.library.flowlayout.FlowLayoutManager;
import com.library.flowlayout.SpaceItemDecoration;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {
    public static final String TAG = MainActivity.class.getSimpleName();
    private RecyclerView lv;
    private FlowAdapter mAdapter;
    private List<String> mStrings = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }

    private void initView() {
        View view = LayoutInflater.from(this).inflate(R.layout.footer, null, false);
        lv = (RecyclerView) findViewById(R.id.lv);
        FlowLayoutManager flowLayoutManager = new FlowLayoutManager();
        //LinearLayoutManager linearLayoutManager=new LinearLayoutManager()//
        //  GridLayoutManager gridLayoutManager=new GridLayoutManager(this,5);
//设置每一个item间距
        lv.setLayoutManager(flowLayoutManager);
        mAdapter = new FlowAdapter(R.layout.tv, getStrings());
        //  mAdapter.addFooterView(view);
//        mAdapter.setFooterView(view);
//        mAdapter.setFooterViewAsFlow(true);
        lv.setAdapter(mAdapter);
        mAdapter.setOnItemChildLongClickListener(new BaseQuickAdapter.OnItemChildLongClickListener() {
            @Override
            public boolean onItemChildLongClick(BaseQuickAdapter adapter, View view, int position) {

//                mStrings.remove(position);
//
//                mAdapter.replaceData(mStrings);

                //
                  onClickPopWhite(view);
                return false;
            }
        });

    }

    private List<String> getStrings() {
        List<String> data = new ArrayList<>();
        data.add("Android");
        data.add("ios");
        data.add("德玛西亚");
        data.add("小甜甜");
        data.add("西南航空大学");
        data.add("成都机场");
        data.add("Android");
        data.add("ios");
        data.add("德玛西亚");
        data.add("小甜甜");
        data.add("西南航空大学");
        data.add("成都机场");
        data.add("添加");
        mStrings = data;
        return data;
    }

    //带有三角号的下拉菜单框  仿qq
    public void onClickPopWhite(View view) {
        DropPopMenu dropPopMenu = new DropPopMenu(this);
        dropPopMenu.setTriangleIndicatorViewColor(Color.WHITE);
        dropPopMenu.setBackgroundResource(R.drawable.bg_drop_pop_menu_white_shap);
        dropPopMenu.setItemTextColor(Color.BLACK);

        dropPopMenu.setOnItemClickListener(new DropPopMenu.OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int position, long id, MenuItem menuItem) {
                //  Toast.makeText(this, "点击了 " + menuItem.getItemId(), Toast.LENGTH_SHORT).show();
            }
        });
        dropPopMenu.setMenuList(getMenuList());

        dropPopMenu.show(view);
    }

    private List<MenuItem> getMenuList() {
        List<MenuItem> list = new ArrayList<>();
        list.add(new MenuItem(1, "删除"));
        return list;
    }
}

///最后提示一句如果是可以动态添加item中的布局应该是一个edittext而不是textview并且edittext是可以点击吗的但是不可编辑

只有最后一个item是可以编辑的  adapter代码如下   :::

package com.example.taglayout;

import android.support.annotation.Nullable;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.EditText;

import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.BaseViewHolder;

import java.util.ArrayList;
import java.util.List;

//作者:        冯浩  on 2018/9/12 14:06
//                          _ooOoo_
//                         o8888888o                            
//                         88" . "88                             
//                         (| ^_^ |)                              
//                         O\  =  /O                              
//                      ____/`---'\____                          
//                    .'  \\|     |//  `.                         
//                   /  \\|||  :  |||//  \                        
//                  /  _||||| -:- |||||-  \                       
//                  |   | \\\  -  /// |   |                       
//                  | \_|  ''\---/''  |   |                      
//                  \  .-\__  `-`  ___/-. /                      
//                ___`. .'  /--.--\  `. . ___                     
//              ."" '<  `.___\_<|>_/___.'  >'"".                  
//            | | :  `- \`.;`\ _ /`;.`/ - ` : | |                 
//            \  \ `-.   \_ __\ /__ _/   .-` /  /                
//      ========`-.____`-.___\_____/___.-`____.-'========        
//                           `=---='                              
//      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^        
//         佛祖保佑       永无BUG     永不修改                    
//                      程序员之歌    作者:冯浩(字:德明)       
//         十年生死两茫茫 ,写程序,到天亮。                      
//             千行代码 ,Bug何处藏 ?                            
//         纵使上线又怎样 ,朝令改 ,夕断肠。                     
//                                                                
//         领导每天新想法 ,日日改 ,夜夜忙。                     
//             相顾无言 ,唯有泪千行。                            
//         每晚灯火阑珊处 ,夜难寐 ,加班狂。 
// ************************************************************************************************
class FlowAdapter extends BaseQuickAdapter<String, BaseViewHolder> {
    List<String> data = new ArrayList<>();

    public FlowAdapter(int layoutResId, @Nullable List<String> data) {
        super(layoutResId, data);
        this.data = data;
    }

    @Override
    protected void convert(BaseViewHolder helper, String item) {
        EditText view =(EditText) helper.getView(R.id.tv);
        if (data.size() - 1 == helper.getPosition()) {
            helper.getView(R.id.tv).setEnabled(true);
            view.setHint("添加");


        }else {
            helper.addOnLongClickListener(R.id.tv);
            helper.setText(R.id.tv, item);
            view.setCursorVisible(false);
            view.setFocusable(false);
            view.setFocusableInTouchMode(false);
        }

    }
}