Android View自動(dòng)換行簡單實(shí)現(xiàn)

原創(chuàng)博客,如有轉(zhuǎn)載,請注明出處,非常感謝。

img1.png

如上圖,view的自動(dòng)換行,貌似現(xiàn)在很多app都很流行這個(gè)設(shè)計(jì)。
下面介紹兩種實(shí)現(xiàn)方式:

一. 自定義控件WordWrapView

1. 在attrs.xml中定義控件需要的屬性
<declare-styleable name="WordWrapView">
        <attr name="spacing_vertical" format="dimension" />
        <attr name="spacing_horizontal" format="dimension" />
</declare-styleable>
2.繼承ViewGroup開始自定義控件。(邏輯非常簡單,直接貼代碼,不解釋了...)
/**
 * 自動(dòng)換行view
 * Created by ys on 2016/2/3.
 */
public class WordWrapView extends ViewGroup {

    private float spacingVertical = 20;

    private float spacingHorizontal = 20;

    public WordWrapView(Context context) {
        this(context, null);
    }

    public WordWrapView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public WordWrapView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.WordWrapView);

        spacingHorizontal = a.getDimension(R.styleable.WordWrapView_spacing_horizontal, spacingHorizontal);
        spacingVertical = a.getDimension(R.styleable.WordWrapView_spacing_vertical, spacingVertical);

        a.recycle();
    }


    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int childCount = getChildCount();
        int autualWidth = r - l - getPaddingRight();
        int x = getPaddingLeft();// 橫坐標(biāo)開始
        int y = 0;//縱坐標(biāo)開始
        int rows = 1;
        for (int i = 0; i < childCount; i++) {
            View view = getChildAt(i);
            int width = view.getMeasuredWidth();
            int height = view.getMeasuredHeight();
            x += width;
            if (x > autualWidth) {
                x = width + getPaddingLeft();
                rows++;
            }
            y = rows * height + (rows - 1) * (int) spacingVertical + getPaddingTop();

            view.layout(x - width, y - height, x, y);

            x += spacingHorizontal;
        }
    }

    ;

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int x = 0;//橫坐標(biāo)
        int y = 0;//縱坐標(biāo)
        int rows = 1;//總行數(shù)
        int specWidth = MeasureSpec.getSize(widthMeasureSpec);
        int actualWidth = specWidth - getPaddingLeft() - getPaddingRight();//實(shí)際寬度
        int childCount = getChildCount();
        for (int index = 0; index < childCount; index++) {
            View child = getChildAt(index);
            child.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
            int width = child.getMeasuredWidth();
            int height = child.getMeasuredHeight();
            x += width;
            if (x > actualWidth) {//換行
                x = width;
                rows++;
            }
            x += spacingHorizontal;

            y = rows * height + (rows - 1) * (int) spacingVertical + getPaddingTop() + getPaddingBottom();
        }
        setMeasuredDimension(specWidth, y);
    }

}

3. 使用

直接一個(gè)布局搞定。當(dāng)然,如果里面的子item如果是動(dòng)態(tài)的,可以使用viewGroup的addView()方法實(shí)現(xiàn)。

img2.png
img3.png

二. FlexboxLayout實(shí)現(xiàn)

FlexboxLayout是谷歌的一個(gè)開源項(xiàng)目,可以實(shí)現(xiàn)各種復(fù)雜布局。
FlexboxLayout開源地址:

https://github.com/google/flexbox-layout
1. 添加依賴
dependencies {
    compile 'com.google.android:flexbox:0.3.0'
}
2. 使用

FlexboxLayout有一個(gè)屬性flexWrap,代表是否支持換行排列,有三個(gè)值:
nowrap :不換行
wrap:按正常方向換行
wrap-reverse:按反方向換行
我們用第二個(gè)“wrap”就行,接下來繼續(xù)上代碼。

img4.png
img6.png
img5.png
3. 最后

效果和自定義控件一模一樣,實(shí)現(xiàn)更簡單。
如果想了解更多FlexboxLayout使用方法,可以參考:

http://www.oschina.net/news/73442/google-flexbox-layout
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容