阅读 570

Android 自动换行的布局 AutoNextLineLinearLayout 实现标签墙排列

前言

最近公司项目有个标签集功能 用户通过标签筛选 生成一系列操作 实现漏斗筛选 并最终推荐药品

废话不多说 看下是不是想要的效果

实现效果

1

实现代码 AutoNextLineLinearLayout

很多人会遇到满行就自动换到下一行的界面需求, 而Android自带的LinearLayout布局自能横排或者竖排,不够显示就加ScrollView,横竖混排就不行了。

/**
 * 自动换行的LinearLayout
 */
public class AutoNextLineLinearLayout extends LinearLayout {

    int mLeft, mRight, mTop, mBottom;
    Hashtable map = new Hashtable();

    public AutoNextLineLinearLayout(Context context) {
        super(context);
    }

    public AutoNextLineLinearLayout(Context context, int horizontalSpacing, int verticalSpacing) {
        super(context);
    }

    public AutoNextLineLinearLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        int mWidth = MeasureSpec.getSize(widthMeasureSpec);
        int mCount = getChildCount();
        int mX = 0;
        int mY = 0;
        mLeft = 0;
        mRight = 0;
        mTop = 5;
        mBottom = 0;

        int j = 0;

        for (int i = 0; i < mCount; i++) {
            final View child = getChildAt(i);
            LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) child.getLayoutParams();
            child.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
            // 此处增加onlayout中的换行判断,用于计算所需的高度
            int childw = child.getMeasuredWidth()+params.leftMargin + params.rightMargin;
            int childh = child.getMeasuredHeight();
            mX += childw; // 将每次子控件宽度进行统计叠加,如果大于设定的高度则需要换行,高度即Top坐标也需重新设置

            Position position = new Position();
            mLeft = getPosition(i - j, i);
            mRight = mLeft + child.getMeasuredWidth();
            if (mX >= mWidth) {
                mX = childw;
                mY += childh;
                j = i;
                mLeft = 0;
                mRight = mLeft + child.getMeasuredWidth();
                mTop = mY + params.topMargin;
            // PS:如果发现高度还是有问题就得自己再细调了
            }
            mBottom = mTop + child.getMeasuredHeight()+params.bottomMargin;
            mY = mTop; // 每次的高度必须记录 否则控件会叠加到一起
            position.left = mLeft;
            position.top = mTop + 3;
            position.right = mRight;
            position.bottom = mBottom;
            map.put(child, position);
        }
        setMeasuredDimension(mWidth, mBottom);
    }

    @Override
    protected LayoutParams generateDefaultLayoutParams() {
        return new LayoutParams(0, 0); // default of 1px spacing
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {

        int count = getChildCount();
        for (int i = 0; i < count; i++) {
            View child = getChildAt(i);
            Position pos = (Position) map.get(child);
            if (pos != null) {
                child.layout(pos.left, pos.top, pos.right, pos.bottom);
            } else {
                Log.i("MyLayout", "error");
            }
        }
    }

    private static class Position {
        int left, top, right, bottom;
    }

    public int getPosition(int IndexInRow, int childIndex) {
        if (IndexInRow > 0) {
            return getPosition(IndexInRow - 1, childIndex - 1) + getChildAt(childIndex - 1).getMeasuredWidth()+30;
        }
        return getPaddingLeft();
    }
}
复制代码

在布局中使用 和普通布局一样

 <com.jk.house.shopping_main.view.AutoNextLineLinearLayout
                android:id="@+id/tagLayout"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginLeft="30dp"
                android:layout_marginTop="10dp"
                android:layout_marginRight="30dp"
                android:orientation="horizontal"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/tv_tips" />
复制代码

实体类中运用

//往AutoNextLineLinearLayout容器里添加数据
tagLayout.removeAllViews();
        for (int i = 0; i < detailsSymptomList.size(); i++) {
            DetailsSymptomBean detailsSymptomBean = detailsSymptomList.get(i);
            if (detailsSymptomBean.getDepartname().equals(type)) {
                for (String taboo : detailsSymptomBean.getTaboo()) {
                    TextView textView = new TextView(getActivity());
                    textView.setText(taboo);
                    textView.setBackgroundResource(R.drawable.selector_checkbox_bg_add_personal_info);
                    AutoNextLineLinearLayout.LayoutParams params = new AutoNextLineLinearLayout
                            .LayoutParams(AutoNextLineLinearLayout.LayoutParams.WRAP_CONTENT, 
                            AutoNextLineLinearLayout.LayoutParams.WRAP_CONTENT);
					//通过这个属性可以控制 排列方式
                    params.setMargins(20, 20, 0, 0);
                    textView.setLayoutParams(params);
                    //通过这个属性可以控制 排列方式
                    textView.setPadding(40, 20, 40, 20);
                    textView.setTextColor(getActivity().getResources().
                    getColorStateList(R.drawable.selector_checkbox_text_color_add_personal_info));
                    textView.setTextSize(30);
                    textView.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            if (view.isSelected()) {
                                view.setSelected(false);
                                tabooList.remove(((TextView) view).getText().toString());
                            } else {
                                view.setSelected(true);
                                tabooList.add(((TextView) view).getText().toString());
                            }
                        }
                    });
                    tagLayout.addView(textView);
                }
            }
        }
复制代码

总结

在使用中 可能遇到标签排列问题 我尝试改变间距和padding 来控制标签的显示问题

//这个是控制单个标签在 布局中的位置
params.setMargins(20, 20, 0, 0);
//这个是标签内容在TextView中的排列
textView.setPadding(40, 20, 40, 20);
复制代码

每个人项目要求 可能不一样 所以我们要灵活的感觉 内容来排列 来达到一个满意效果

最后 2021 请再努力一点 继续加油~

文章分类
Android
文章标签