Android:水平列表与trello类似标签的新换行符

时间:2018-05-23 03:11:31

标签: android xml android-linearlayout layout-inflater

我想在android中创建一个包含Trello标签的视图。 card with labels

我面临的问题是,当标签持有者达到最大宽度容量时,如何创建新的换行符。我希望实现这样的目标。

card with labels that surpass the view's width capacity card with labels that surpass the view's width capacity twice

还必须考虑标签可以有不同的宽度。

我想到在宽度总和超过最大容量的任何时候膨胀一个新的水平视图,但我不知道是否存在其他方法或更有效的方法来解决这个问题。

possible solution diagram

感谢您的帮助。

2 个答案:

答案 0 :(得分:3)

在这种情况下,我认为您应该使用this并替换RecyclerView

答案 1 :(得分:2)

通过覆盖onLayout和onMeasure方法来自定义ViewGroup:

String[] dataList;

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
    int childCount = getChildCount();
    int curItemWidth, curItemHeight, curLeft, curTop, maxHeight;

    //get the available size of child view
    int viewLeft = this.getPaddingLeft();
    int viewTop = this.getPaddingTop();
    int viewRight = this.getMeasuredWidth() - this.getPaddingRight();
    int viewBottom = this.getMeasuredHeight() - this.getPaddingBottom();
    int viewWidth = viewRight - viewLeft;
    int viewHeight = viewBottom - viewTop;

    maxHeight = 0;
    curLeft = viewLeft + getCurLeft(0, viewWidth, viewHeight, viewRight);
    curTop = viewTop;

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

        if (child.getVisibility() == GONE)
            continue;

        //Get the maximum size of the child
        child.measure(MeasureSpec.makeMeasureSpec(viewWidth, MeasureSpec.AT_MOST),
                MeasureSpec.makeMeasureSpec(viewHeight, MeasureSpec.AT_MOST));

        curItemWidth = child.getMeasuredWidth();
        curItemHeight = child.getMeasuredHeight();
        //wrap is reach to the end
        if (curLeft + curItemWidth >= viewRight) { //new row
            curLeft = viewLeft + getCurLeft(i, viewWidth, viewHeight, viewRight);
            curTop += maxHeight;
            maxHeight = 0;
        }
        //do the layout
        child.layout(curLeft, curTop, curLeft + curItemWidth, curTop + curItemHeight);

        //store the max height
        maxHeight = Math.max(maxHeight, curItemHeight);
        curLeft += curItemWidth;
    }
}

private int getCurLeft(int currentPosition, int viewWidth, int viewHeight, int viewRight) {
    int childCount = getChildCount();
    int currentMaxWidth = 0;
    for (int i = currentPosition; i < childCount; i++) {
        View child = getChildAt(i);
        if (child.getVisibility() == GONE)
            continue;

        child.measure(MeasureSpec.makeMeasureSpec(viewWidth, MeasureSpec.AT_MOST),
                MeasureSpec.makeMeasureSpec(viewHeight, MeasureSpec.AT_MOST));

        currentMaxWidth += child.getMeasuredWidth();
        //wrap is reach to the end
        if (currentMaxWidth >= viewRight) { //new row
            return 0;
        }
    }
    return (viewWidth - currentMaxWidth) / 2;
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    // Measurement will ultimately be computing these values.
    int childCount = getChildCount();
    int maxHeight = 0;
    int maxWidth = 0;
    int childState = 0;
    int currentRowWidth = 0;
    int parentWidth = resolveSizeAndState(maxWidth, widthMeasureSpec, childState);
    // Iterate through all children, measuring them and computing our dimensions
    // from their size.

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

        if (child.getVisibility() == GONE)
            continue;

        // Measure the child.
        measureChild(child, widthMeasureSpec, heightMeasureSpec);
        maxWidth = Math.max(maxWidth, child.getMeasuredWidth());
        maxHeight = Math.max(maxHeight, child.getMeasuredHeight());

        currentRowWidth += child.getMeasuredWidth();
        if (currentRowWidth >= parentWidth) { //create new row.
            maxHeight += child.getMeasuredHeight();
            currentRowWidth = 0;
        }
        childState = combineMeasuredStates(childState, child.getMeasuredState());
    }

    // Check against our minimum height and width
    maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight());
    maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth());

    // Report our final dimensions.
    setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, childState),
            resolveSizeAndState(maxHeight, heightMeasureSpec, childState << MEASURED_HEIGHT_STATE_SHIFT));
}

public void setData(String[] dataList) {
    this.dataList = dataList;

    for (int i = 0; i < dataList.length; i++) {
        View tagView = layoutInflater.inflate(R.layout.item_tag_layout, null, false);

        TextView tagTextView = tagView.findViewById(R.id.label);
        tagTextView.setText(dataList[i]);
        tagTextView.setTag(i);
        tagTextView.setOnClickListener(onClickListener);

        if (dataList[i].equalsIgnoreCase(defaultItem)) {
            selectedItemView = tagTextView;
            tagTextView.setTextColor(ContextCompat.getColor(getContext(), R.color.tag_layout_text_selected));
        } else {
            tagTextView.setTextColor(ContextCompat.getColor(getContext(), R.color.tag_layout_text_default));
        }

        if (i == dataList.length - 1) {
            View indicator = tagView.findViewById(R.id.indicator);
            indicator.setVisibility(GONE);
        }
        this.addView(tagView);
    }

}