实现TextView可最多两行显示、右边控件紧跟TextView效果自定义布局

此自定义布局实现的效果是:整个布局的最大宽度给定情况下,左边TextView宽度自适应,最多两行显示;右边控件紧贴左边TextView,如果TextView显示两行,右边控件转到紧贴第二行文本后面显示。最终的效果图如下:



自定义控件代码如下:

package com.rzc.widget;

import android.content.Context;
import android.support.annotation.Nullable;
import android.text.Layout;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

/**
 * Created by rzc on 17/10/23.
 */

public class MaxTwoLineTextLabelLayout extends ViewGroup {
    private static final int MAX_LINE = 2;//如果要改成TextView最大其他行数,这里跟xml文件同时修改,保持值一致(目前支持2行,其他行还有bug,需要下面代码调整下
    private static final int CHILD_COUNT = 2;//目前支持包含两个子控件,左边必须是TextView,右边是任意的View或ViewGroup

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

    public MaxTwoLineTextLabelLayout(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

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

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        if (getChildCount() == CHILD_COUNT && getChildAt(0) instanceof TextView) {
            int width = r - l;

            TextView child0 = (TextView) getChildAt(0);
            int child0Width = child0.getMeasuredWidth();
            int child0Height = child0.getMeasuredHeight();

            View child1 = getChildAt(1);
            int child1Width = child1.getMeasuredWidth();
            MarginLayoutParams lp = (MarginLayoutParams) child1.getLayoutParams();
            int child1Height = child1.getMeasuredHeight();

            int destWidth = child0Width + child1Width + lp.leftMargin;
            if (destWidth > width) {//一行显示不下
                if (child0.getLineCount() == 1) {//文本只有一行
                    child0.layout(0, 0, child0Width, child0Height);
                    int top = child0Height + lp.topMargin;
                    child1.layout(0, top, child1Width, top + child1Height);
                } else {
                    child0.layout(0, 0, child0Width, child0Height);
                    int lineWidth = getLineWidth(child0, MAX_LINE - 1);
                    if (lineWidth + lp.leftMargin + child1Width < width) {
                        int left = lineWidth + lp.leftMargin;
                        int top = (child0Height + child0Height / 2 - child1Height) / 2;
                        child1.layout(left, top, left + child1Width, top + child1Height);
                    }
                }
            } else {
                child0.layout(0, 0, child0Width, child0Height);
                int left = child0Width + lp.leftMargin;
                int top = (child0Height - child1Height) / 2;
                child1.layout(left, top, left + child1Width, top + child1Height);
            }
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int maxWidth = MeasureSpec.getSize(widthMeasureSpec);
        int maxHeight = MeasureSpec.getSize(heightMeasureSpec);

        if (getChildCount() == 2 && getChildAt(0) instanceof TextView) {
            TextView child0 = (TextView) getChildAt(0);
            measureChild(child0, widthMeasureSpec, heightMeasureSpec);
            int child0Width = child0.getMeasuredWidth();
            int child0Height = child0.getMeasuredHeight();

            View child1 = getChildAt(1);
            measureChild(child1, widthMeasureSpec, heightMeasureSpec);
            int child1Width = child1.getMeasuredWidth();
            MarginLayoutParams lp = (MarginLayoutParams) child1.getLayoutParams();
            int child1Height = child1.getMeasuredHeight();

            int destWidth = child0Width + child1Width + lp.leftMargin;
            int destHeight = 0;
            if (destWidth > maxWidth) {//一行显示不下
                if (child0.getLineCount() == 1) {//文本只有一行
                    destWidth = child0Width;
                    destHeight = lp.topMargin + child0Height + child1Height;//+ line extraspace
                } else {
                    destWidth = Math.max(child0Width, maxWidth);
                    destHeight = child0Height;
                }
            } else {
                destHeight = child0Height;
            }
            setMeasuredDimension(destWidth, destHeight);
        } else {
            setMeasuredDimension(maxWidth, maxHeight);
        }
    }


    private int getLineWidth(TextView textView, int lineNum) {
        Layout layout = textView.getLayout();
        int lineCount = textView.getLineCount();
        if (layout != null && lineNum >= 0 && lineNum < lineCount) {
            return (int) (layout.getLineWidth(lineNum) + 0.5);
        }

        return 0;
    }
}

上面demo图片的xml布局代码如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="20dp">

    <com.rzc.widget.MaxTwoLineTextLabelLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginRight="50dp" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:ellipsize="end"
            android:maxLines="2"
            android:text="文本只显示了一行,图片接着文本显示"
            android:textSize="15dp" />

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="3dp"
            android:layout_marginTop="2dp"
            android:gravity="center_vertical"
            android:orientation="horizontal">

            <ImageView
                android:layout_width="12dp"
                android:layout_height="12dp"
                android:src="@mipmap/ic_launcher" />
        </LinearLayout>
    </com.rzc.widget.MaxTwoLineTextLabelLayout>

    <com.rzc.widget.MaxTwoLineTextLabelLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginRight="50dp"
        android:layout_marginTop="30dp" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:ellipsize="end"
            android:maxLines="2"
            android:text="文本显示了一行,图片显示在第二行的情况"
            android:textSize="15dp" />

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="3dp"
            android:layout_marginTop="2dp"
            android:gravity="center_vertical"
            android:orientation="horizontal">

            <ImageView
                android:layout_width="12dp"
                android:layout_height="12dp"
                android:src="@mipmap/ic_launcher" />
        </LinearLayout>
    </com.rzc.widget.MaxTwoLineTextLabelLayout>

    <com.rzc.widget.MaxTwoLineTextLabelLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginRight="50dp"
        android:layout_marginTop="30dp" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:ellipsize="end"
            android:maxLines="2"
            android:text="文本显示了两行,图片跟着文本显示在第二行文字后面"
            android:textSize="15dp" />

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="3dp"
            android:layout_marginTop="2dp"
            android:gravity="center_vertical"
            android:orientation="horizontal">

            <ImageView
                android:layout_width="12dp"
                android:layout_height="12dp"
                android:src="@mipmap/ic_launcher" />
        </LinearLayout>
    </com.rzc.widget.MaxTwoLineTextLabelLayout>
</LinearLayout>


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章