12

我不确定在这种特定场景中使用哪种类型的布局。

我基本上想要一个可以添加视图的水平线性布局。在这种情况下按钮(在应用程序中显示标签)但是每个视图都会根据它所显示的标签名称有不同的宽度,所以我想添加 10 个标签,我需要一个适合尽可能多的布局可以放在第一行,如果放不下,自动溢出到下一行。

基本上,文本视图如何与文本一起工作,如果文本长于它到下一行的宽度,除非我想用不可点击的按钮来做到这一点。

我想到了一个网格布局,但是当你可以在第一行有 2 个带有长名称的标签和在第二行有 7 个带有短名称的标签时,每行上的“标签”数量都会相同。

看起来有点像这样的东西: 在此处输入图像描述

我基本上想看看下面的堆栈溢出是如何发生的。

4

2 回答 2

5

答:你自己的习惯Layout:)

我知道这是对这个问题的迟到答案。但这肯定会对 OP 或某人有所帮助。

您可以扩展ViewGroup以创建像下面这样的自定义布局。这样做的好处是您可以保持视图层次结构平坦

Android Studio 非常智能地呈现自定义布局,就像任何其他布局一样!

我的流布局

public class MyFlowLayout extends ViewGroup {

    public MyFlowLayout(Context context) {
        super(context);
    }

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

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

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int realWidth = MeasureSpec.getSize(widthMeasureSpec);

        int currentHeight = 0;
        int currentWidth = 0;

        int currentChildHookPointx = 0;
        int currentChildHookPointy = 0;

        int childCount = this.getChildCount();

        for(int i = 0; i < childCount; i++) {
            View child = getChildAt(i);
            this.measureChild(child, widthMeasureSpec, heightMeasureSpec);
            int childWidth = child.getMeasuredWidth();
            int childHeight = child.getMeasuredHeight();

            //check if child can be placed in the current row, else go to next line
            if(currentChildHookPointx + childWidth > realWidth) {
                //new line
                currentWidth = Math.max(currentWidth, currentChildHookPointx);

                //reset for new line
                currentChildHookPointx = 0;

                currentChildHookPointy += childHeight;
            }

            int nextChildHookPointx;
            int nextChildHookPointy;

            nextChildHookPointx = currentChildHookPointx + childWidth;
            nextChildHookPointy = currentChildHookPointy;

            currentHeight = Math.max(currentHeight, currentChildHookPointy + childHeight);

            LayoutParams lp = (LayoutParams) child.getLayoutParams();
            lp.x = currentChildHookPointx;
            lp.y = currentChildHookPointy;

            currentChildHookPointx = nextChildHookPointx;
            currentChildHookPointy = nextChildHookPointy;
        }

        currentWidth = Math.max(currentChildHookPointx, currentWidth);

        setMeasuredDimension(resolveSize(currentWidth, widthMeasureSpec),
                resolveSize(currentHeight, heightMeasureSpec));
    }

    @Override
    protected void onLayout(boolean b, int left, int top, int right, int bottom) {
        //call layout on children
        int childCount = this.getChildCount();
        for(int i = 0; i < childCount; i++) {
            View child = this.getChildAt(i);
            LayoutParams lp = (LayoutParams) child.getLayoutParams();
            child.layout(lp.x, lp.y, lp.x + child.getMeasuredWidth(), lp.y + child.getMeasuredHeight());
        }

    }

    @Override
    public LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new MyFlowLayout.LayoutParams(getContext(), attrs);
    }

    @Override
    protected LayoutParams generateDefaultLayoutParams() {
        return new MyFlowLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
    }

    @Override
    protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
        return new MyFlowLayout.LayoutParams(p);
    }

    @Override
    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
        return p instanceof MyFlowLayout.LayoutParams;
    }

    public static class LayoutParams extends ViewGroup.MarginLayoutParams {

        int spacing = -1;
        int x = 0;
        int y = 0;

        LayoutParams(Context c, AttributeSet attrs) {
            super(c, attrs);
            TypedArray t = c.obtainStyledAttributes(attrs, R.styleable.FlowLayout_Layout);
            spacing = t.getDimensionPixelSize(R.styleable.FlowLayout_Layout_layout_space, 0);
            t.recycle();
        }

        LayoutParams(int width, int height) {
            super(width, height);
            spacing = 0;
        }

        public LayoutParams(MarginLayoutParams source) {
            super(source);
        }

        LayoutParams(ViewGroup.LayoutParams source) {
            super(source);
        }
    }
}

layout.xml 文件中的用法

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:cl="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.merryapps.customlayout.MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!" />

    <com.merryapps.customlayout.MyFlowLayout
        android:id="@+id/flw1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#FF0000">
        <Button
            android:id="@+id/b1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/hello"
            cl:layout_space="20dp"/>
        <Button
            android:id="@+id/b2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/world"/>

        <Button
            android:id="@+id/b4"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/world"/>

        <Button
            android:id="@+id/b5"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/world"/>

        <Button
            android:id="@+id/b6"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/world"/>
    </com.merryapps.customlayout.MyFlowLayout>

    <Button
        android:id="@+id/b3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/world"
        android:textAllCaps="false"/>
</LinearLayout>
于 2016-12-17T05:19:08.533 回答
2

对于显示类型的视图,必须使用流布局:- Git 上有许多可用的库以下是 blazsolar/FlowLayout的示例

在 app.gradle 中添加这一行

compile "com.wefika:flowlayout:<version>"

用法:-

<com.wefika.flowlayout.FlowLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="start|top">

    <View
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Lorem ipsum" />

</com.wefika.flowlayout.FlowLayout>

有关详细实施,请遵循以下链接-

https://github.com/blazsolar/FlowLayout

你也可以试试这个链接:- https://github.com/xiaofeng-han/AndroidLibs/tree/master/flowlayoutmanager(试试这个) https://github.com/ApmeM/android-flowlayout https://gist。 github.com/hzqtc/7940858

于 2016-12-17T06:07:46.223 回答