【问题标题】:How can I do something like a FlowLayout in Android?如何在 Android 中执行类似 FlowLayout 的操作?
【发布时间】:2010-12-17 19:50:30
【问题描述】:

如何在 Android 中执行 FlowLayout 之类的操作?

【问题讨论】:

    标签: android


    【解决方案1】:

    您应该使用 FlexboxLayoutflexWrap="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>
    

    有关构建说明,请参阅the github repo.

    implementation 'com.google.android:flexbox:2.0.1'
    

    更多关于这个 - https://android-developers.googleblog.com/2017/02/build-flexible-layouts-with.html

    【讨论】:

      【解决方案2】:

      我没有足够的声誉来对 Romain Guy 的回答发表评论,但这应该是这个回答的地方(我创建了一个帐户只是为了分享我的编辑)。

      无论如何,我看到其他人发现他非常酷的 FlowLayout 解决方案存在一些问题。 我自己也能找到一个,和其他人一样,我看到一些孩子被剪掉了。 仔细查看算法,在计算高度时似乎是一个非常简单的错误。当最后一个孩子被放在新行上时,高度计算不正确。 我清理了一些计算(“高度”与 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));
      }
      

      【讨论】:

        【解决方案3】:

        有一个来自 Google 的库,名为 "flexbox-layout"。你应该检查一下。

        要在 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
        

        【讨论】:

          【解决方案4】:

          这是自定义类,您可以在其中通过添加动态视图(也称为 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_layo_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"));
                              }
                          }
                      });
          
                  }
              }
          }
          

          【讨论】:

          • 不错的类,但需要一些工作来支持从右到左的布局方向。
          • 如何在中心制作物品。
          • java.lang.ClassCastException: android.widget.LinearLayout$LayoutParams 无法转换为 com.nuveda.fillintheblank.FlowLayout$LayoutParams
          • 我认为您正在尝试为您的布局设置动态参数,所以它会出现问题,我建议使用 RelativeLayout.LayoutParams 。
          【解决方案5】:

          与之前的答案之一一样,我从这里的解决方案开始: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;
                      }
                  }
              }
          }
          

          我将其用作包装多行 TextEdits 的解决方案。希望对您有所帮助!

          【讨论】:

          • 在某些情况下非常有用。 Here's a revision 支持 MarginLayoutParams。
          • 不错的解决方案!边距只有在 init 方法中设置后才有效,而不是从布局中。
          【解决方案6】:

          现在使用 Flow 小部件在 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/

          【讨论】:

            【解决方案7】:

            支持 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 的流程布局?
            • 另外,我想知道如何使用保证金? margin=10dp 来自布局。
            • @Pratik,如果您有一个小型 RadioGroup,并且如果有空间,您希望在它旁边显示其他视图,如果没有空间,则流到下一行,FlowLayout 应该可以正常工作。当第一行空间不足时,导致其 RadioButton 项目流到下一行的大型水平 RadioGroup 需要编写自定义 RadioGroup 类型的类,因为 RadioGroup 扩展了 LinearLayout。您可以使用此 FlowLayout 类中的想法编写自定义 RadioGroup 类。到目前为止,我还没有需要使用单选按钮。我们通常使用 Spinners 或其他控件。
            • @Pratik,您可以在布局文件中使用android:layout_margin="10dp"设置所有边距,也可以使用android:layout_marginLeft="10dp"android:layout_marginTop="4dp"、..等属性设置单个边距。
            【解决方案8】:

            这里有很好的简单的自包含 FlowLayout 代码(只是几个简洁的 gist.github 文件)

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

            但是,开箱即用的活动对我来说无法加载自定义布局。

            我发现了这个解决方法[使用 2-param .inflate() 调用 from this example]

            @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;
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2019-08-05
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2019-10-14
              • 1970-01-01
              • 1970-01-01
              • 2014-09-26
              相关资源
              最近更新 更多