Android標簽流控件的實現

jopen 9年前發布 | 168K 次閱讀 Android Android開發 移動開發

我們從服務器端獲取標簽的信息,然后將其動態的添加到布局中,并且我們能夠得到我們選擇容器的信息,并將選中的標簽重新返回至服務器。

前言

在我們的開發過程中,常常會遇到這樣的場景:

我們展示一種物品或者為某一事物添加一些標簽。比如說,我們買一件衣服,可以有以下幾種標簽:杰克瓊斯,男士,運動等等。

但我們這時候可能并不知道標簽的數量和每個標簽的文字,所以,我們在開發過程中,需要實現下面的功能:

我們從服務器端獲取標簽的信息,然后將其動態的添加到布局中,并且我們能夠得到我們選擇容器的信息,并將選中的標簽重新返回至服務器。

因此,我們必須計算出每個標簽(Button)的長度,并且將其與它的容器做比較,如果容器剩余的長度并不足以容納一個標簽的時候,那么就會另起一行,添加標簽,就這樣周而復始,直到所有的標簽添加到容器中。

實現

我們將我們自定義的控件命名為TagCloudLayout,它繼承ViewGroup 并將它作為標簽的容器。同時覆寫onMeasure()和onLayout方法

onMeasure()方法

通過覆寫onMeasure()方法,我們可以計算出容器和各標簽的長度和寬度,代碼如下:

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int wantHeight = 0;
        int wantWidth = resolveSize(0, widthMeasureSpec);

    int paddingLeft = getPaddingLeft();
    int paddingRight = getPaddingRight();
    int paddingTop = getPaddingTop();
    int paddingBottom = getPaddingBottom();

    int childLeft = paddingLeft;
    int childTop = paddingTop;
    int lineHeight = 0;

    for (int i = 0; i < getChildCount(); i++) {
        final View childView = getChildAt(i);
        if (childView.getVisibility() == View.GONE) {
            continue;
        }

        LayoutParams params = childView.getLayoutParams();
        childView.measure(
                getChildMeasureSpec(widthMeasureSpec, paddingLeft + paddingRight, params.width),
                getChildMeasureSpec(heightMeasureSpec, paddingTop + paddingBottom, params.height)
        );

        int childHeight = childView.getHeight();
        int childWidth = childView.getWidth();
        lineHeight = Math.max(childHeight, lineHeight);

        if (childLeft + childWidth + paddingRight > wantWidth) {
            childLeft = paddingLeft;
            childTop += mLineSpacing + childHeight;
            lineHeight = childHeight;
        } else {
            childLeft += childWidth + mTagSpacing;
        }


    }
    wantHeight = childTop + lineHeight + paddingBottom;
    setMeasuredDimension(wantWidth, resolveSize(wantHeight, heightMeasureSpec));

}</pre> <h3>onLayout()方法 </h3>

計算好長度和寬度之后,我們就可以進行布局了。

protected void onLayout(boolean changed, int l, int t, int r, int b) {
    int width = r - l;

int paddingLeft = getPaddingLeft();
int paddingTop = getPaddingTop();
int paddingRight = getPaddingRight();

int childLeft = paddingLeft;
int childTop = paddingTop;

int lineHeight = 0;

for (int i = 0, childCount = getChildCount(); i < childCount; ++i) {

    final View childView = getChildAt(i);

    if (childView.getVisibility() == View.GONE) {
        continue;
    }

    int childWidth = childView.getMeasuredWidth();
    int childHeight = childView.getMeasuredHeight();
    lineHeight = Math.max(childHeight, lineHeight);

    if (childLeft + childWidth + paddingRight > width) {
        childLeft = paddingLeft;
        childTop += mLineSpacing + lineHeight;
        lineHeight = childHeight;
    }

    childView.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);
    childLeft += childWidth + mTagSpacing;
}

}</pre>

在主應用程序調用

這樣的話,我們的控件的主要方法就完成了,接下來我們就可以在主應用程序中直接調用了,代碼如下:

TagCloudLayout mContainer;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Button btn = (Button) findViewById(R.id.test_btn);
    mContainer = (TagCloudLayout) findViewById(R.id.container);
    ArrayList<String> list = new ArrayList<>();
    list.add("one");
    list.add("你好");
    list.add("three");
    list.add("four");
    list.add("ninkfnsadf");
    list.add("fsadfsdgdsfasd");
    list.add("fasdgsdagfsdafdsfsadfsadf");
    list.add("adf");
    list.add("one");
    list.add("fasdfadfa");
    list.add("fads");
    list.add("中國");
    list.add("one");
    list.add("柴靜");
    list.add("three");
    list.add("four");
    mContainer.addData(list);
    mContainer.drawLayout();
    btn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
        }
    });

}</pre>

效果

最后,讓我們來看看實現效果

Android標簽流控件的實現

結束語

這個自定義控件我感覺還是挺實用的,所以我會抽出時間將它整理,便于他人調用,項目的地址是標簽云控件,歡迎大家指正。

參考資料

Johnny Huang的博客

</div> 來自:http://www.fyales.com/archives/71

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!