AndroidでFlowLayoutのようなことをするにはどうすればよいですか?


96

どうすればFlowLayoutAndroidのようなことができますか?


@arsentの回答を参照してください。
フランクR.

回答:


91

私がDevoxx大学の日(parleys.comで利用可能)で行った講演を見ると、自分でそれを行う方法を学ぶことができます。講演中、FlowLayoutステージ上でライブ実装を書いて、カスタムレイアウトを書くのがいかに簡単かを示しました。

実装はここでホストされます


18
romainの男に感謝します。解決策を与えるだけではどうですか?またはリンク?...あなたの答えが受け入れられた方法がわかりません。
Johann Hilbold、2012

4
@JohannHilbold:リンクを追加しました
Macarse 2012年

7
読者はリンク上のコードにいくつかの深刻な問題があり、ドロップインソリューションとはほど遠いことに注意してください。この小さなコードベースには、すでに2つの大きな問題がありました。修正は、私の特定のニーズに対応するダクトテープソリューションであるため、掲載しません...
Nemanja Kovacevic

6
私はそれが完璧だとは決して主張しなかった:)
Romain Guy

19
@RomainGuy要点は、結局のところ、それほど単純ではないかもしれません。
Jeffrey Blattman、2013年

69

属性FlexboxLayoutとともに使用する必要がありflexWrap="wrap"ます。

<com.google.android.flexbox.FlexboxLayout 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     app:flexWrap="wrap">

<!-- contents go here -->

</com.google.android.flexbox.FlexboxLayout>

ビルド手順については、githubリポジトリを参照してください

FlexboxLayoutの視覚的表現 これについての詳細-https://android-developers.googleblog.com/2017/02/build-flexible-layouts-with.html


7
これは最新の、これまでのところ最高のソリューションです。
Touhid

3
これは解決策としてマークする必要があります!これまでのところ、この問題に対する最良の回答
x10sion 2017

1
あなたはRecyclerViewでこの効果を持つようにしたい場合は、この答えに追加するには、そのlibにもするLayoutManagerを持っている
アリ

1
ビンゴ、バンゴ、ボンゴ。AndroidでFlexboxを使用するための素晴らしいライブラリ。良いですね。
Joshua Pinter

23

Romain Guyの回答にコメントを投稿するのに十分な評判はありませんが、そこにこの回答があります(編集内容を共有するためだけにアカウントを作成しました)。

とにかく、私は彼のかなりクールなFlowLayoutソリューションにいくつかの問題があることを他の人々が知っているのを目にします。私は自分自身を見つけることができました、そして、他の人として、何人かの子供が切り取られているのを見ました。アルゴリズムを詳しく見ると、高さの計算は非常に単純な間違いのようです。最後の子が新しい行に配置される子である場合、高さは適切に計算されませんでした。計算を少し整理しました( "height"とcurrentHeightの奇妙な使い方がありました)。

次の変更により、「新しい行にある場合、最後の子が切り取られる」という問題が修正されます。

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
    int widthLimit = MeasureSpec.getSize(widthMeasureSpec) - getPaddingRight();
    int widthMode = MeasureSpec.getMode(widthMeasureSpec);

    boolean growHeight = widthMode != MeasureSpec.UNSPECIFIED;

    int width = 0;

    int currentWidth = getPaddingLeft();
    int currentHeight = getPaddingTop();

    int maxChildHeight = 0;

    boolean breakLine = false;
    boolean newLine = false;
    int spacing = 0;

    final int count = getChildCount();
    for (int i = 0; i < count; i++)
    {
        View child = getChildAt(i);
        measureChild(child, widthMeasureSpec, heightMeasureSpec);

        LayoutParams lp = (LayoutParams) child.getLayoutParams();
        spacing = mHorizontalSpacing;

        if (lp.horizontalSpacing >= 0)
        {
            spacing = lp.horizontalSpacing;
        }

        if (growHeight && (breakLine || ((currentWidth + child.getMeasuredWidth()) > widthLimit)))
        {               
            newLine = true;
            currentHeight += maxChildHeight + mVerticalSpacing;

            width = Math.max(width, currentWidth - spacing);

            currentWidth = getPaddingLeft();
            maxChildHeight = 0;
        }
        else
        {
            newLine = false;
        }

        maxChildHeight = Math.max(maxChildHeight, child.getMeasuredHeight());

        lp.x = currentWidth;
        lp.y = currentHeight;

        currentWidth += child.getMeasuredWidth() + spacing;

        breakLine = lp.breakLine;
    }

    if (newLine == false)
    {
        width = Math.max(width, currentWidth - spacing);
    }

    width += getPaddingRight();
    int height = currentHeight + maxChildHeight + getPaddingBottom();

    setMeasuredDimension(resolveSize(width, widthMeasureSpec),
            resolveSize(height, heightMeasureSpec));
}

9

「flexbox-layout」と呼ばれるGoogleのライブラリがあります。ぜひチェックしてみてください。

RecyclerViewで使用するには、次のようなものを使用できます。

val layoutManager = FlexboxLayoutManager(activity)
layoutManager.flexDirection = FlexDirection.ROW
layoutManager.flexWrap = FlexWrap.WRAP
layoutManager.justifyContent = JustifyContent.FLEX_START
layoutManager.alignItems = AlignItems.FLEX_START 
recyclerView.layoutManager=layoutManager

6

以前の答えの1つと同様に、私はここでソリューションから始めました:http : //hzqtc.github.io/2013/12/android-custom-layout-flowlayout.html

子供の身長の変化に対応するために、以下のように拡張しました。

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;

// Custom layout that wraps child views to a new line
public class FlowLayout extends ViewGroup {

    private int marginHorizontal;
    private int marginVertical;

    public FlowLayout(Context context) {
        super(context);
        init();
    }

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

    public FlowLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    private void init() { // Specify the margins for the children
        marginHorizontal = getResources().getDimensionPixelSize(R.dimen.activity_half_horizontal_margin);
        marginVertical = getResources().getDimensionPixelSize(R.dimen.activity_half_vertical_margin);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int childLeft = getPaddingLeft();
        int childTop = getPaddingTop();
        int lowestBottom = 0;
        int lineHeight = 0;
        int myWidth = resolveSize(100, widthMeasureSpec);
        int wantedHeight = 0;

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

            child.measure(getChildMeasureSpec(widthMeasureSpec, 0, child.getLayoutParams().width),
                    getChildMeasureSpec(heightMeasureSpec, 0, child.getLayoutParams().height));
            int childWidth = child.getMeasuredWidth();
            int childHeight = child.getMeasuredHeight();
            lineHeight = Math.max(childHeight, lineHeight);

            if (childWidth + childLeft + getPaddingRight() > myWidth) { // Wrap this line
                childLeft = getPaddingLeft();
                childTop = marginVertical + lowestBottom; // Spaced below the previous lowest point
                lineHeight = childHeight;
            }
            childLeft += childWidth + marginHorizontal;

            if (childHeight + childTop > lowestBottom) { // New lowest point
                lowestBottom = childHeight + childTop;
            }
        }

        wantedHeight += childTop + lineHeight + getPaddingBottom();
        setMeasuredDimension(myWidth, resolveSize(wantedHeight, heightMeasureSpec));
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        int childLeft = getPaddingLeft();
        int childTop = getPaddingTop();
        int lowestBottom = 0;
        int myWidth = right - left;
        for (int i = 0; i < getChildCount(); i++) {
            final View child = getChildAt(i);
            if (child.getVisibility() == View.GONE) {
                continue;
            }
            int childWidth = child.getMeasuredWidth();
            int childHeight = child.getMeasuredHeight();

            if (childWidth + childLeft + getPaddingRight() > myWidth) { // Wrap this line
                childLeft = getPaddingLeft();
                childTop = marginVertical + lowestBottom; // Spaced below the previous lowest point
            }
            child.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);
            childLeft += childWidth + marginHorizontal;

            if (childHeight + childTop > lowestBottom) { // New lowest point
                lowestBottom = childHeight + childTop;
            }
        }
    }
}

これを複数行のTextEditをラップするためのソリューションとして使用しました。それが役に立てば幸い!


特定の場合に非常に役立ちます。 以下は、MarginLayoutParamsをサポートするリビジョンです。
jk7

素敵な解決策!marginはinitメソッド内で設定した後にのみ機能し、layoutからは機能しません。
Pratik Saluja 2017

6

以下は、動的ビュー(別名FlowLayout)を追加して、次のようなレイアウトを実現できるカスタムクラスです。

ここに画像の説明を入力してください

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;

/*
Created By Dhavalkumar Solanki
* */
public class FlowLayout extends ViewGroup {

    private int line_height_space;

    public static class LayoutParams extends ViewGroup.LayoutParams {

        public int horizontal_spacing;
        public int vertical_spacing;

        /**
         * @param horizontal_spacing Pixels between items, horizontally
         * @param vertical_spacing   Pixels between items, vertically
         */
        public LayoutParams(int horizontal_spacing, int vertical_spacing) {
            super(0, 0);
            this.horizontal_spacing = horizontal_spacing;
            this.vertical_spacing = vertical_spacing;
        }
    }

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

    public FlowLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        assert (MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.UNSPECIFIED);

        final int width = MeasureSpec.getSize(widthMeasureSpec) - getPaddingLeft() - getPaddingRight();
        int height = MeasureSpec.getSize(heightMeasureSpec) - getPaddingTop() - getPaddingBottom();
        final int count = getChildCount();
        int line_height_space = 0;

        int xpos = getPaddingLeft();
        int ypos = getPaddingTop();

        int childHeightMeasureSpec;
        if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST) {
            childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST);
        } else {
            childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
        }


        for (int i = 0; i < count; i++) {
            final View child = getChildAt(i);
            if (child.getVisibility() != GONE) {
                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
                child.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST), childHeightMeasureSpec);
                final int childw = child.getMeasuredWidth();
                line_height_space = Math.max(line_height_space, child.getMeasuredHeight() + lp.vertical_spacing);

                if (xpos + childw > width) {
                    xpos = getPaddingLeft();
                    ypos += line_height_space;
                }

                xpos += childw + lp.horizontal_spacing;
            }
        }
        this.line_height_space = line_height_space;

        if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.UNSPECIFIED) {
            height = ypos + line_height_space;

        } else if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST) {
            if (ypos + line_height_space < height) {
                height = ypos + line_height_space;
            }
        }
        setMeasuredDimension(width, height);
    }

    @Override
    protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
        return new LayoutParams(1, 1); // default of 1px spacing
    }

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

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        final int count = getChildCount();
        final int width = r - l;
        int xpos = getPaddingLeft();
        int ypos = getPaddingTop();

        for (int i = 0; i < count; i++) {
            final View child = getChildAt(i);
            if (child.getVisibility() != GONE) {
                final int childw = child.getMeasuredWidth();
                final int childh = child.getMeasuredHeight();
                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
                if (xpos + childw > width) {
                    xpos = getPaddingLeft();
                    ypos += line_height_space;
                }
                child.layout(xpos, ypos, xpos + childw, ypos + childh);
                xpos += childw + lp.horizontal_spacing;
            }
        }
    }
}

例:

text_view.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tool="http://schemas.android.com/tools"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="5dp">

    <TextView
        android:id="@+id/tvText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="19sp"
        android:background="@drawable/unselected_tag"
        android:textColor="@color/colorPrimary"
        tool:text="Temp" />
</RelativeLayout>

activity_flow_layou_demo.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"

    >
    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical">

                <TextView
                    android:id="@+id/tvTitleBusiness"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="Business Interest "
                    android:textColor="@color/colorPrimary"
                    android:textSize="25sp" />

                <com.example.tristateandroid2.radardemo.FlowLayout
                    android:id="@+id/flowBusiness"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content">

                </com.example.tristateandroid2.radardemo.FlowLayout>
            </LinearLayout>

            <LinearLayout
                android:layout_marginTop="@dimen/activity_horizontal_margin"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical">

                <TextView
                    android:id="@+id/tvTitlePrivate"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="Private Interest "
                    android:textColor="@color/colorPrimary"
                    android:textSize="25sp" />

                <com.example.tristateandroid2.radardemo.FlowLayout
                    android:id="@+id/flowPrivate"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content">

                </com.example.tristateandroid2.radardemo.FlowLayout>
            </LinearLayout>
        </LinearLayout>
    </ScrollView>
</RelativeLayout>

FlowLayouDemo.java

import android.graphics.Color;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;

import java.util.ArrayList;

public class FlowLayouDemo extends AppCompatActivity {
    private TextView tvTitleBusiness;
    private FlowLayout flowBusiness;
    private TextView tvTitlePrivate;
    private FlowLayout flowPrivate;
    private ArrayList<TagModel> arrayList;

    private void findViews() {
        tvTitleBusiness = (TextView) findViewById(R.id.tvTitleBusiness);
        flowBusiness = (FlowLayout) findViewById(R.id.flowBusiness);
        tvTitlePrivate = (TextView) findViewById(R.id.tvTitlePrivate);
        flowPrivate = (FlowLayout) findViewById(R.id.flowPrivate);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_flow_layou_demo);
        findViews();
        addLayouts();
    }

    private void addLayouts() {
        if (arrayList == null) {
            arrayList = new ArrayList<>();
        }
        flowBusiness.removeAllViews();
        flowPrivate.removeAllViews();
        for (int i = 0; i < 75; i++) {

            final boolean[] selected = {false};
            View view = this.getLayoutInflater().inflate(R.layout.text_view, null);
            final TextView textView = (TextView) view.findViewById(R.id.tvText);
            if (i % 5 == 0) {
                arrayList.add(new TagModel(i, false, "Business VIEW : " + i));
                textView.setText("Busi VIEW To  IS : " + i);
            } else {
                arrayList.add(new TagModel(i, false, "TEXT IS : " + i));
                textView.setText("Busi IS : " + i);
            }
            textView.setBackgroundResource(R.drawable.unselected_tag);
            textView.setTextColor(Color.parseColor("#3F51B5"));
            textView.setTag(i);
            if(i<=50){
                flowBusiness.addView(view);
            }else {
                textView.setText("Priv View : "+i);
                flowPrivate.addView(view);
            }

            textView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    if (selected[0]) {
                        selected[0] = false;
                        textView.setBackgroundResource(R.drawable.unselected_tag);
                        textView.setTextColor(Color.parseColor("#3F51B5"));
                    } else {
                        selected[0] = true;
                        textView.setBackgroundResource(R.drawable.selected_tag);
                        textView.setTextColor(Color.parseColor("#FFFFFF"));
                    }
                }
            });

        }
    }
}

1
素晴らしいクラスですが、右から左へのレイアウト方向をサポートするためにいくつかの作業が必要です。
Ted Hopp、2016

センターでアイテムを作る方法。
Abhishek c

java.lang.ClassCastException:android.widget.LinearLayout $ LayoutParamsをcom.nuveda.fillintheblank.FlowLayout $ LayoutParamsにキャストできない
Naveen Kumar M

私はあなたがあなたのレイアウトに動的パラメータを設定しようとしていると思うので、それは問題を引き起こしています、私はRelativeLayout.LayoutParamsを使うことを勧めます。
Dhaval Solanki

3

MarginLayoutParams をサポートする@MattNotEquals()FlowLayoutの改訂。

これは、MarginLayoutParmsの最小限の実装で、左、右、上、下のマージンをサポートします。

import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;

/**
 *  Original version courtesy of MattNotEquals() at http://stackoverflow.com/a/34169798/4515489 - 4/13/17.
 *  7/15/17 Revised to support MarginLayoutParams.
 */
public class FlowLayout extends ViewGroup {
    // Custom layout that wraps child views to a new line.

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

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

    public FlowLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int childLeft = getPaddingLeft();
        int childTop = getPaddingTop();
        int lowestBottom = 0;
        int lineHeight = 0;
        int myWidth = resolveSize(100, widthMeasureSpec);
        int wantedHeight = 0;
        for (int i = 0; i < getChildCount(); i++) {
            final View child = getChildAt(i);
            if (child.getVisibility() == View.GONE) {
                continue;
            }
            child.measure(getChildMeasureSpec(widthMeasureSpec, 0, child.getLayoutParams().width),
                          getChildMeasureSpec(heightMeasureSpec, 0, child.getLayoutParams().height));
            int childWidth = child.getMeasuredWidth();
            int childHeight = child.getMeasuredHeight();
            lineHeight = Math.max(childHeight, lineHeight);

            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
            childLeft += lp.leftMargin;
            childTop += lp.topMargin;
            if (childLeft + childWidth + lp.rightMargin + getPaddingRight() > myWidth) { // Wrap this line
                childLeft = getPaddingLeft() + lp.leftMargin;
                childTop = lowestBottom + lp.topMargin; // Spaced below the previous lowest point
                lineHeight = childHeight;
            }
            childLeft += childWidth + lp.rightMargin;

            if (childTop + childHeight + lp.bottomMargin > lowestBottom) { // New lowest point
                lowestBottom = childTop + childHeight + lp.bottomMargin;
            }
        }
        wantedHeight += lowestBottom + getPaddingBottom(); // childTop + lineHeight + getPaddingBottom();
        setMeasuredDimension(myWidth, resolveSize(wantedHeight, heightMeasureSpec));
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        int childLeft = getPaddingLeft();
        int childTop = getPaddingTop();
        int lowestBottom = 0;
        int myWidth = right - left;
        for (int i = 0; i < getChildCount(); i++) {
            final View child = getChildAt(i);
            if (child.getVisibility() == View.GONE) {
                continue;
            }
            int childWidth = child.getMeasuredWidth();
            int childHeight = child.getMeasuredHeight();

            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
            childLeft += lp.leftMargin;
            childTop += lp.topMargin;
            if (childLeft + childWidth + lp.rightMargin + getPaddingRight() > myWidth) { // Wrap this line
                childLeft = getPaddingLeft() + lp.leftMargin;
                childTop = lowestBottom + lp.topMargin; // Spaced below the previous lowest point
            }
            child.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);
            childLeft += childWidth + lp.rightMargin;

            if (childTop + childHeight + lp.bottomMargin > lowestBottom) { // New lowest point
                lowestBottom = childTop + childHeight + lp.bottomMargin;
            }
        }
    }

    @Override
    public boolean shouldDelayChildPressedState() {
        return false;
    }

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

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

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

    @Override
    protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams lp) {
        if (lp instanceof LayoutParams) {
            return new LayoutParams((LayoutParams) lp);
        }
        else if (lp instanceof MarginLayoutParams) {
            return new LayoutParams((MarginLayoutParams) lp);
        }
        else
            return super.generateLayoutParams(lp);
    }

    /**
     * Per-child layout information for layouts that support margins.
     */
    public static class LayoutParams extends MarginLayoutParams {
        public LayoutParams(@NonNull Context c, @Nullable AttributeSet attrs) {
            super(c, attrs);
        }
        public LayoutParams(int width, int height) {
            super(width, height);
        }
        public LayoutParams(@NonNull ViewGroup.LayoutParams source) {
            super(source);
        }
        public LayoutParams(@NonNull ViewGroup.MarginLayoutParams source) {
            super(source);
        }
        public LayoutParams(@NonNull LayoutParams source) {
            super(source);
        }
    }
}

私は過去2時間から頭を悩ませていましたが、このコードの部分だけが私のために働きました!! RadioGroupのフローレイアウトを提供できますか?
Pratik Saluja

また、マージンの使い方を知りたいのですが?margin = 10dpはレイアウトから適切に取得されます。
Pratik Saluja

1
@Pratik、小さなRadioGroupがあり、部屋がある場合に他のビューを横に表示し、部屋がない場合に次の行にフローする場合、FlowLayoutは正常に機能します。RadioGroupがLinearLayoutを拡張しているため、最初の行が領域を超えたときにそのRadioButtonアイテムが次の行に流れる大きな水平RadioGroupには、カスタムRadioGroupタイプのクラスを記述する必要があります。このFlowLayoutクラスのアイデアを使用して、カスタムRadioGroupクラスを作成できます。これまでのところ、ラジオボタンを使用する必要はありません。通常は、スピナーまたはその他のコントロールを使用します。
jk7

@Pratikは、あなたがすべてのマージンを設定することができandroid:layout_margin="10dp"、レイアウトファイルに、またはのような属性を持つ個々のマージンを設定しandroid:layout_marginLeft="10dp"android:layout_marginTop="4dp"、..etc。
jk7

0

ここに素敵なシンプルな自己完結型FlowLayoutコード (いくつかの簡潔なgist.githubファイル)

http://hzqtc.github.io/2013/12/android-custom-layout-flowlayout.html

しかし、そのままの状態では、カスタムレイアウトをロードするためのアクティビティが機能しませんでした。

私はこの回避策を見つけました[ この例の2-param .inflate()呼び出しを使用して ]

@Override
protected void onCreate(Bundle savedInstanceState)
{
    // ..

    setContentView(R.layout.main_res_layout_activity_main);

    ViewGroup flowContainer = getFlowLayoutView(); 

    // ..
}

ViewGroup getFlowLayoutView()
{
    LayoutInflater inflater = getLayoutInflater();

    ViewGroup flowLayout = 
        (ViewGroup)
            inflater.inflate(
                    R.layout.main_res_layout_activity_main,
                    (FlowLayout) findViewById(R.id.flow_container)
            );

    return flowLayout;
}

0

フローウィジェットを使用したConstraintLayoutの組み込みサポートが追加されました。多くのタイプのフローを実現するために使用できる多くのオプションがあります。

例:

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">

<androidx.constraintlayout.helper.widget.Flow
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    app:constraint_referenced_ids="item_1,item_2,item_3"
    app:flow_horizontalBias="0"
    app:flow_horizontalGap="10dp"
    app:flow_horizontalStyle="packed"
    app:flow_verticalGap="8dp"
    app:flow_wrapMode="aligned"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

<View
    android:id="@+id/item_1"
    android:layout_width="50dp"
    android:layout_height="50dp" />

<View
    android:id="@+id/item_2"
    android:layout_width="50dp"
    android:layout_height="50dp" />

<View
    android:id="@+id/item_3"
    android:layout_width="50dp"
    android:layout_height="50dp" />
</androidx.constraintlayout.widget.ConstraintLayout>

この投稿をご覧くださいhttps : //medium.com/@tapanrgohil/constraintlayout-flow-bye-bye-to-linerlayout-78fd7fa9b679

そしてここ:https : //www.bignerdranch.com/blog/constraintlayout-flow-simple-grid-building-without-nested-layouts/

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.