在Android中使用wrap向左浮动

在Android中使用wrap向左浮动,android,Android,我很有兴趣获得与cssfloat:left样式中相同的效果。我现在使用的是RelativeLayout和android:layout\u-toRightOf,但需要在视图不合适时转到下一行。如何在android布局中实现这一点 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" and

我很有兴趣获得与css
float:left
样式中相同的效果。我现在使用的是
RelativeLayout
android:layout\u-toRightOf
,但需要在视图不合适时转到下一行。如何在android布局中实现这一点

<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">

    <Button
        android:id="@+id/a"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:width="300dp" />

    <Button
        android:id="@+id/b"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@+id/a"
        android:width="300dp" />

    <Button
        android:id="@+id/c"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@+id/b"
        android:width="300dp" />

</RelativeLayout>

我需要这样的东西

在较宽的屏幕上,我需要获得例如,一行中有3个按钮,但在较小的屏幕上,一行中有2个按钮,第二行中有第三个按钮。如下图所示

小型设备

宽设备


对于单行,使用具有水平方向的
线性布局,而不是相对线布局

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="horizontal">

<!-- add your views here -->

</LinearLayout>

对于多行,您希望自动将元素“流动”到新行。您可以查看或尝试根据

/**扩展{@link RelativeLayout}的自定义视图
*将其子对象水平放置,
*当线条超出宽度时,流向一条新的线条*/
公共类水平流布局
扩展相对长度
{
/**从代码创建视图时要使用的构造函数*/
公共水平流布局(上下文)
{
超级(上下文);
}
/**从XML扩展视图时调用的构造函数*/
公共水平流布局(上下文、属性集属性)
{
超级(上下文,attrs);
}
/**从XML执行膨胀并应用特定于类的基本样式*/
公共水平流布局(上下文上下文、属性集属性、int-defStyle)
{
超级(上下文、属性、定义样式);
}
@凌驾
测量时的保护空隙(内部宽度测量等级、内部高度测量等级)
{
//需要调用super.onMeasure(…),否则会出现一些有趣的行为
超级测量(宽度测量、高度测量);
最终int width=MeasureSpec.getSize(widthmasurespec);
int height=MeasureSpec.getSize(heightMeasureSpec);
//当我们通过一条直线时,增加x位置
int xpos=getPaddingLeft();
//当我们通过这些线时,增加y位置
int ypos=getPaddingTop();
//当前行的高度
int line_高度=0;
//检查儿童
//计算此视图所需的高度的步骤
//我想不需要打电话来测量孩子的大小?!
//没有它,获取孩子的测量高度/宽度似乎可以正常工作
//测量儿童(宽度测量,高度测量);
看孩子;
marginlayoutparms childmarginlayoutparms;
int childWidth、childHeight、childMarginLeft、childMarginRight、childMarginTop、childMarginBottom;
对于(int i=0;iwidth)
{
//这个孩子需要换一条新线路
xpos=getPaddingLeft();
ypos+=线路高度;
线条高度=childMarginTop+childHeight+childMarginBottom;
}
其他的
//当前行上有足够的空间容纳此子项
线条高度=数学最大值(
线条高度,
childMarginTop+childHeight+childMarginBottom);
xpos+=childMarginLeft+childWidth+childMarginRight;
}
}
ypos+=行_高度+getPaddingBottom();
if(测量等级getMode(高度测量等级)=未指定的测量等级)
//设置测量的高度,因为没有高度限制
高度=ypos;
else if(MeasureSpec.getMode(heightMeasureSpec)=MeasureSpec.AT_
&&ypos<高度)
//设置测量的高度,因为它小于允许的最大值
高度=ypos;
设置测量尺寸(宽度、高度);
}
@凌驾
仅受保护的void布局(布尔值已更改、int l、int t、int r、int b)
{
//当我们通过一条直线时,增加x位置
int xpos=getPaddingLeft();
//当我们通过这些线时,增加y位置
int ypos=getPaddingTop();
//当前行的高度
int line_高度=0;
看孩子;
marginlayoutparms childmarginlayoutparms;
int childWidth、childHeight、childMarginLeft、childMarginRight、childMarginTop、childMarginBottom;
对于(int i=0;i/** Custom view which extends {@link RelativeLayout}
 * and which places its children horizontally,
 * flowing over to a new line whenever it runs out of width.*/
public class HorizontalFlowLayout
  extends RelativeLayout
{
  /** Constructor to use when creating View from code.*/
  public HorizontalFlowLayout(Context context)
  {
    super(context);
  }

  /** Constructor that is called when inflating View from XML.*/
  public HorizontalFlowLayout(Context context, AttributeSet attrs)
  {
    super(context, attrs);
  }

  /** Perform inflation from XML and apply a class-specific base style.*/
  public HorizontalFlowLayout(Context context, AttributeSet attrs, int defStyle)
  {
    super(context, attrs, defStyle);
  }

  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
  {
    // need to call super.onMeasure(...) otherwise get some funny behaviour
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    final int width = MeasureSpec.getSize(widthMeasureSpec);
    int height = MeasureSpec.getSize(heightMeasureSpec);

    // increment the x position as we progress through a line
    int xpos = getPaddingLeft();
    // increment the y position as we progress through the lines
    int ypos = getPaddingTop();
    // the height of the current line
    int line_height = 0;

    // go through children
    // to work out the height required for this view

    // call to measure size of children not needed I think?!
    // getting child's measured height/width seems to work okay without it
    //measureChildren(widthMeasureSpec, heightMeasureSpec);

    View child;
    MarginLayoutParams childMarginLayoutParams;
    int childWidth, childHeight, childMarginLeft, childMarginRight, childMarginTop, childMarginBottom;

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

      if (child.getVisibility() != GONE)
      {
        childWidth = child.getMeasuredWidth();
        childHeight = child.getMeasuredHeight();

        if (child.getLayoutParams() != null
            && child.getLayoutParams() instanceof MarginLayoutParams)
        {
          childMarginLayoutParams = (MarginLayoutParams)child.getLayoutParams();

          childMarginLeft = childMarginLayoutParams.leftMargin;
          childMarginRight = childMarginLayoutParams.rightMargin;
          childMarginTop = childMarginLayoutParams.topMargin;
          childMarginBottom = childMarginLayoutParams.bottomMargin;
        }
        else
        {
          childMarginLeft = 0;
          childMarginRight = 0;
          childMarginTop = 0;
          childMarginBottom = 0;
        }

        if (xpos + childMarginLeft + childWidth + childMarginRight + getPaddingRight() > width)
        {
          // this child will need to go on a new line

          xpos = getPaddingLeft();
          ypos += line_height;

          line_height = childMarginTop + childHeight + childMarginBottom;
        }
        else
          // enough space for this child on the current line
          line_height = Math.max(
              line_height,
              childMarginTop + childHeight + childMarginBottom);

        xpos += childMarginLeft + childWidth + childMarginRight;
      }
    }

    ypos += line_height + getPaddingBottom();

    if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.UNSPECIFIED)
      // set height as measured since there's no height restrictions
      height = ypos;
    else if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST
        && ypos < height)
      // set height as measured since it's less than the maximum allowed
      height = ypos;

    setMeasuredDimension(width, height);
  }

  @Override
  protected void onLayout(boolean changed, int l, int t, int r, int b)
  {
    // increment the x position as we progress through a line
    int xpos = getPaddingLeft();
    // increment the y position as we progress through the lines
    int ypos = getPaddingTop();
    // the height of the current line
    int line_height = 0;

    View child;
    MarginLayoutParams childMarginLayoutParams;
    int childWidth, childHeight, childMarginLeft, childMarginRight, childMarginTop, childMarginBottom;

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

      if (child.getVisibility() != GONE)
      {
        childWidth = child.getMeasuredWidth();
        childHeight = child.getMeasuredHeight();

        if (child.getLayoutParams() != null
            && child.getLayoutParams() instanceof MarginLayoutParams)
        {
          childMarginLayoutParams = (MarginLayoutParams)child.getLayoutParams();

          childMarginLeft = childMarginLayoutParams.leftMargin;
          childMarginRight = childMarginLayoutParams.rightMargin;
          childMarginTop = childMarginLayoutParams.topMargin;
          childMarginBottom = childMarginLayoutParams.bottomMargin;
        }
        else
        {
          childMarginLeft = 0;
          childMarginRight = 0;
          childMarginTop = 0;
          childMarginBottom = 0;
        }

        if (xpos + childMarginLeft + childWidth + childMarginRight + getPaddingRight() > r - l)
        {
          // this child will need to go on a new line

          xpos = getPaddingLeft();
          ypos += line_height;

          line_height = childHeight + childMarginTop + childMarginBottom;
        }
        else
          // enough space for this child on the current line
          line_height = Math.max(
              line_height,
              childMarginTop + childHeight + childMarginBottom);

        child.layout(
            xpos + childMarginLeft,
            ypos + childMarginTop,
            xpos + childMarginLeft + childWidth,
            ypos + childMarginTop + childHeight);

        xpos += childMarginLeft + childWidth + childMarginRight;
      }
    }
  }
}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal"
    android:weightSum="3" >

    <Button 
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="wrap_content"/>
    <Button 
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="wrap_content"/>
    <Button 
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="wrap_content"/>
</LinearLayout>