實現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>


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