Linear layout with word wrapping

Without further ado, let’s go directly to the code:

/**
 * Word wrap layout
 * Created by 马占柱 on 2018/4/20.
 */
public class WrapLayout extends ViewGroup {
    private static final String TAG = "WrapLayout";
    /**
     * style of TextView
     */
    public int TEXTVIEW_STYLE = 0;
    /**
     * Button's style
     */
    public int BUTTON_STYLE = 1;
    private int style;
    private View btn;
    private MarkClickListener markClickListener;
    /**
     * Store all Views, record by row
     */
    private List<List<View>> mAllViews = new ArrayList<>();
    /**
     * Record the maximum height of each line
     */
    private List<Integer> mLineHeight = new ArrayList<>();

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

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

    public WrapLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public void setData(List<String> data, Context context, int textSize) {
        String[] mydata = null;
        if (data != null) {
            int length = data.size();
            mydata = new String[length];
            for (int i = 0; i < length; i++) {
                mydata[i] = data.get(i);
            }
        }
        createChild(mydata, context, textSize, 8, 5, 5,
                8, 5, 5, 5, 5);
    }

    private void createChild(String[] data, final Context context, int textSize, int pl, int pt, int pr, int pb, int ml, int mt, int mr, int mb) {
        int size = data.length;
        for (int i = 0; i < size; i++) {
            String text = data[i];
            //By judging whether the style is TextView or Button for different operations, you can continue to add different views
            if (style == TEXTVIEW_STYLE) {
                btn = LayoutInflater.from(context).inflate(R.layout.textview, null);
                ((TextView) btn).setGravity(Gravity.CENTER);
                ((TextView) btn).setText(text);
                ((TextView) btn).setTextSize(textSize);
            } else if (style == BUTTON_STYLE) {
                btn = new Button(context);
                ((Button) btn).setGravity(Gravity.CENTER);
                ((Button) btn).setText(text);
                ((Button) btn).setTextSize(textSize);
            }
            btn.setClickable(true);
            btn.setPadding(dip2px(context, pl), dip2px(context, pt), dip2px(context, pr), dip2px(context, pb));
            MarginLayoutParams params = new MarginLayoutParams(MarginLayoutParams.WRAP_CONTENT, MarginLayoutParams.WRAP_CONTENT);
            params.setMargins(ml, mt, mr, mb);
            btn.setLayoutParams (params);
            final int finalI = i;
            //Add click event to each view
            btn.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    markClickListener.clickMark(finalI);
                }
            });
            this.addView(btn);
        }
    }

    /**
     * Convert from dp unit to px (pixel) according to the resolution of the phone
     */
    private int dip2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }

    public void setData(String[] data, Context context, int textSize,
                        int paddingLeft, int paddingTop, int paddingRight, int paddingBottom,
                        int marginLeft, int marginTop, int marginRight, int marginButton) {
        createChild(data, context, textSize,
                paddingLeft, paddingTop, paddingRight, paddingBottom,
                marginLeft, marginTop, marginRight, marginButton);
    }

    public void setData(String[] data, Context context, int textSize) {
        createChild(data, context, textSize, 8, 5, 5,
                8, 5, 5, 5, 5);
    }

    public void setData(List<String> data, Context context, int textSize,
                        int paddingLeft, int paddingTop, int paddingRight, int paddingBottom,
                        int marginLeft, int marginTop, int marginRight, int marginButton) {
        String[] mydata = null;
        if (data != null) {
            int length = data.size();
            mydata = new String[length];
            for (int i = 0; i < length; i++) {
                mydata[i] = data.get(i);
            }
        }
        createChild(mydata, context, textSize,
                paddingLeft, paddingTop, paddingRight, paddingBottom,
                marginLeft, marginTop, marginRight, marginButton);
    }

    public void setMarkClickListener(MarkClickListener markClickListener) {
        this.markClickListener = markClickListener;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        int childCount = getChildCount();
        int lineWidth = 0;
        int lineHeight = 0;
        int width = 0;//warpcontet is the width that needs to be recorded
        int height = 0;
        for (int i = 0; i < childCount; i++) {
            View child = getChildAt(i);
            // measure the width and height of each child
            measureChild(child, widthMeasureSpec, heightMeasureSpec);
            MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
            int childWidth = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
            int childHeight = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
            Log.e(TAG, "onMeasure: lineHeight = " + lineHeight + " childHeight = " + childHeight);
            if (lineWidth + childWidth > widthSize) {
                width = Math.max(lineWidth, childWidth);//This case is to exclude the case where a single label is very long
                lineWidth = childWidth;//Open a new line
                height += lineHeight;//Record the total line height
                lineHeight = childHeight;//Because a new line is opened, the height of this line should be recorded
            } else {
                lineWidth += childWidth;
// lineHeight = Math.max(lineHeight, childHeight); //Record line height
                lineHeight = Math.max(height, childHeight); //Record line height
            }
            // If it is the last one, compare the maximum width of the current record with the current lineWidth
            if (i == childCount - 1) {
                width = Math.max(width, lineWidth);  //宽度
                height += lineHeight;  //
            }
        }

        setMeasuredDimension((widthMode == MeasureSpec.EXACTLY) ? widthSize
                : width, (heightMode == MeasureSpec.EXACTLY) ? heightSize
                : height);
    }

    //OnLayout completes the specification of the position and size of all childViews
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        mAllViews.clear(); //Clear the list of child controls
        mLineHeight.clear(); //Clear the height record list
        int width = getWidth();//Get the width of the current control (it has been measured in the onmeasure method)
        int childCount = getChildCount();
        // store all childViews for each row
        List<View> lineViews = new ArrayList<View>();
        int lineWidth = 0; //line width
        int lineHeight = 0; //Total line height
        for (int i = 0; i < childCount; i++) {
            View child = getChildAt(i);
            MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();//Get property parameters
            int childWidth = child.getMeasuredWidth();
            int childHeight = child.getMeasuredHeight();
            // if a newline is already required
            if (i == 3) {
                i = 3;
            }
            if (childWidth + lp.leftMargin + lp.rightMargin + lineWidth > width) // greater than the width of the parent layout
            {
                // Record all Views in this row and the maximum height
                mLineHeight.add(lineHeight);
                // Save the childView of the current row, then open a new ArrayList to save the childView of the next row
                mAllViews.add(lineViews);
                lineWidth = 0; // reset the line width
                lineViews = new ArrayList<View>();
            }
            /**
             * Accumulate if no newline is required
             */
            lineWidth += childWidth + lp.leftMargin + lp.rightMargin;
            lineHeight = Math.max(lineHeight, childHeight + lp.topMargin
                    + lp.bottomMargin);
            lineViews.add(child);
        }
        // record the last line (because the last line is definitely larger than the width of the parent layout, so adding the last line is necessary)
        mLineHeight.add(lineHeight);
        mAllViews.add(lineViews);
        int left = 0;
        int top = 0;
        int lineNums = mAllViews.size();
        for (int i = 0; i < lineNums; i++) {
            // all views for each row
            lineViews = mAllViews.get(i);
            // The maximum height of the current row is the same for each row, so use (i+1) to set the height
            lineHeight = (i + 1) * mLineHeight.get(i);
            for (int j = 0; j < lineViews.size(); j++) {
                View lineChild = lineViews.get(j);
                if (lineChild.getVisibility() == View.GONE) {
                    continue;
                }
                MarginLayoutParams lp = (MarginLayoutParams) lineChild.getLayoutParams();
                //Start drawing labels. The distance between the left and the top is determined according to the accumulated number.
                int lc = left + lp.leftMargin;
                int tc = top + lp.topMargin;
                int rc = lc + lineChild.getMeasuredWidth();
                int bc = tc + lineChild.getMeasuredHeight();
                lineChild.layout(lc, tc, rc, bc);
                left += lineChild.getMeasuredWidth() + lp.rightMargin + lp.leftMargin;
            }
            left = 0; // reset left to zero
            top = lineHeight;
        }
    }

    @Override
    public LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new MarginLayoutParams(getContext(), attrs);
    }

    public void setStyle(int style) {
        this.style = style;
    }


    public interface MarkClickListener {
        void clickMark(int position);
    }
}

Here is the layout of the textview:

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/tv_bg"
    android:ellipsize="end"
    android:gravity="center"
    android:maxLines="1"
    android:textColor="@android:color/white" />

This is the background color of the textview:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <corners android:radius="10dp" />
    <solid android:color="#227652" />
</shape>

Use this in the layout:

<com.love5653520.mazhanzhu.utils.WrapLayout
            android:id="@+id/wrap"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@id/text_remen"
            android:background="@color/white"
            android:layout_marginBottom="5dp"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="10dp"
            android:layout_marginTop="5dp">
        </com.love5653520.mazhanzhu.utils.WrapLayout>
Okay, if you say too much, it's all nonsense. You can directly see the effect after copying it and running it. There are other requirements that can be changed slowly according to this. Basically, it can meet the effect of more than 80%!



Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325556814&siteId=291194637