TagLayout自定義流式佈局 End

效果圖:

實現思路:

這是一個繼承ViewGourp來實現的自定義佈局。他的核心只有一個,即當子View的寬度超出自身最大寬度時,自動換行。那麼,我們先來看核心代碼:

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

        measureChildren(widthMeasureSpec, heightMeasureSpec);

        final int count = getChildCount(); // tag的數量
        int left = 0; // 當前的左邊距離
        int top = 0; // 當前的上邊距離
        int totalHeight = 0; // WRAP_CONTENT時控件總高度
        int totalWidth = 0; // WRAP_CONTENT時控件總寬度

        for (int i = 0; i < count; i++) {
            View child = getChildAt(i);

            LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) child.getLayoutParams();

            if (i == 0) { // 第一行的高度
                totalHeight = params.topMargin + child.getMeasuredHeight() + params.bottomMargin;
            }

            if (left + params.leftMargin + child.getMeasuredWidth() + params.rightMargin > getMeasuredWidth()) { // 換行
                left = 0;
                top += params.topMargin + child.getMeasuredHeight() + params.bottomMargin; // 每個TextView的高度都一樣,隨便取一個都行
                totalHeight += params.topMargin + child.getMeasuredHeight() + params.bottomMargin;
            }

            children.add(new int[]{left + params.leftMargin, top + params.topMargin, left + params.leftMargin + child.getMeasuredWidth(), top + params.topMargin + child.getMeasuredHeight()});

            left += params.leftMargin + child.getMeasuredWidth() + params.rightMargin;

            if (left > totalWidth) { // 當寬度爲WRAP_CONTENT時,取寬度最大的一行
                totalWidth = left;
            }
        }

        int height = 0;
        if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY) {
            height = MeasureSpec.getSize(heightMeasureSpec);
        } else {
            height = totalHeight;
        }

        int width = 0;
        if (MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY) {
            width = MeasureSpec.getSize(widthMeasureSpec);
        } else {
            width = totalWidth;
        }

        setMeasuredDimension(width, height);
    }

毫無疑問,onMeasure是這個自定義佈局的核心,筆者不僅在改方法中實現了測量,同時還會記錄子控件的左上右下四個座標位置信息,存在一個ArrayList<int []> 中。以便在onLayout中直接賦值。

簡單的解析一下代碼,在子View的循環中,我們首先獲取一次子View的高度,而每次換行時,再疊加高度,最終用於Warp-Content時,高度的測量。而寬度則取最寬的一行的值。
設置一個當前的左上點座標。確定每一個子View的左上點座標後,通過子View的寬高確定右下點座標。即完成了對一個子View的測量。

如何使用:

 for (index in list.indices){
            val layout=LayoutInflater.from(context).inflate(R.layout.item_text_card,null)
            val tv=layout.findViewById<TextView>(R.id.tv)
            val params = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)
            params.setMargins(20, 20, 0, 0)
            tv.text=list[index].text
            layout.setOnClickListener {
                if(listener!=null) listener!!.onItemClick(list[index],index)
                dismiss()
            }
            tags.addView(layout,params)
        }
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:background="#F0EFEF"
    android:layout_height="450dp">
    <ImageView
        android:id="@+id/ivCancel"
        android:layout_gravity="right"
        android:padding="15dp"
        android:src="@mipmap/icon_schedule_close"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <com.hjl.artisan.app.TagLayout
            android:id="@+id/tags"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>

    </ScrollView>

</LinearLayout>

源碼:

wusyLibrary://wusylibrary/src/main/java/com/wusy/wusylibrary/view/TagLayout.java
掃描文章末尾的二維碼,關注筆者的公衆號:飲水思源|wusy,回覆Android源碼獲取。感謝你的支持。

End

筆者的Github Blog,希望各位大大提意見,點個star,謝謝
傳送門:WusyBlog

求互粉互贊,互贊所有文章可以私聊我。哈哈,希望我們的原創文章能讓更多朋友看到,一起變強。

筆者新開通了微信公衆號——飲水思源|wusy 計劃持續運營,每日爲您分享Android乾貨、原創文章。微信掃描下方的二維碼關注我,開發學習路上不迷路。謝謝各位


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