2016-01-21 60 views
0

我想创建一个具有两行视图的自定义RelativeLayout:一个在屏幕左侧(android:layout_alignParentStart =“true”),另一个在右侧(android:layout_alignParentEnd =“true”)。右侧的视图将朝向左侧视图增长,直到占据两个视图之间的所有空间。然后它将移动到左侧视图下的新行。是否可以使用RelativeLayout属性实现FlowLayout?

我已经实现了一个扩展了RelativeLayout的Romain Guy的FlowLayout的稍微修改版本。然而,这个类似乎忽略了RelativeLayout的align属性,只是将视图紧挨着放在一起。有没有一种方法可以实现这样一种布局,可以将视图固定在左侧和右侧?

的FlowLayout类:

public class FlowLayout extends RelativeLayout { 

private int mHorizontalSpacing; 
private int mVerticalSpacing; 

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

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

    TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.FlowLayout); 
    mHorizontalSpacing = attributes.getDimensionPixelSize(R.styleable 
      .FlowLayout_horizontalSpacing, 0); 
    mVerticalSpacing = attributes.getDimensionPixelSize(R.styleable 
      .FlowLayout_verticalSpacing, 0); 
    attributes.recycle(); 
} 

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

    int width = 0; 
    int height = getPaddingTop(); 

    int currentWidth = getPaddingStart(); 
    int currentHeight = 0; 

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

     if (currentWidth + child.getMeasuredWidth() > widthSize) { 
      height += currentHeight + mVerticalSpacing; 
      currentHeight = 0; 
      width = Math.max(width, currentWidth); 
      currentWidth = getPaddingEnd(); 
     } 

     int spacing = mHorizontalSpacing; 
     if (lp.spacing > -1) { 
      spacing = lp.spacing; 
     } 

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

     currentWidth += child.getMeasuredWidth(); 
     currentHeight = Math.max(currentHeight, child.getMeasuredHeight()); 
    } 

    width += getPaddingEnd(); 
    height += getPaddingBottom(); 

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

} 

@Override 
protected void onLayout(boolean changed, int l, int t, int r, int b) { 
    final int count = getChildCount(); 
    for (int i = 0; i < count; i++) { 
     View child = getChildAt(i); 
     LayoutParams lp = (LayoutParams) child.getLayoutParams(); 
     child.layout(lp.x, lp.y, lp.x + child.getMeasuredWidth(), lp.y + child 
       .getMeasuredHeight()); 
    } 
} 

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

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

@Override 
protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { 
    return new LayoutParams(p.width, p.height); 
} 

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

public static class LayoutParams extends RelativeLayout.LayoutParams { 

    public int spacing; 

    public int x; 
    public int y; 

    public LayoutParams(Context context, AttributeSet attrs) { 
     super(context, attrs); 

     TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable 
       .FlowLayout_LayoutParams); 
     spacing = attributes.getDimensionPixelSize(R.styleable 
       .FlowLayout_LayoutParams_layoutSpacing, -1); 
     attributes.recycle(); 
    } 

    public LayoutParams(int width, int height) { 
     super(width, height); 
    } 
} 

} 

回答

0

事实证明,而不是你自己计算右视图的新位置,你可以改变它的LayoutParams并有OS把手定位你。我创建了一个扩展了RelativeLayout并覆盖onMeasure()方法的自定义布局。这将相应地调整LayoutParams。

更具体地说: 调用super方法,然后在onMeasure()中查找两个视图及其父项的宽度。使用这些来确定右侧视图是否与左侧视图重叠。如果是这样,请将右侧视图的layout_alignParentEnd="true"属性更改为layout_alignParentStart="true",并为其指定layout_below="@id/left_view"属性。当没有重叠时做相反的事情。再次调用超级方法让操作系统重新为您查看视图。

布局类:

public class WrappingLayout extends RelativeLayout { 

    private TextView leftView; 
    private EditText rightView; 
    //Use this to prevent unnecessarily adjusting the LayoutParams 
    //when the right view is already in the correct position 
    private boolean isMultiline = false; 

    public WrappingLayout(Context context) { 
     super(context); 
     LayoutInflater inflater = LayoutInflater.from(context); 
     inflater.inflate(R.layout.wrapping_layout, this); 

     leftView = (TextView) findViewById(R.id.left_view); 
     rightView = (EditText) findViewById(R.id.right_view); 
    } 

    public WrappingLayout(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     LayoutInflater inflater = LayoutInflater.from(context); 
     inflater.inflate(R.layout.wrapping_layout, this); 

     leftView = (TextView) findViewById(R.id.left_view); 
     rightView = (EditText) findViewById(R.id.right_view); 
    } 

    @Override 
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
     //Call first to make sure the views' initial widths have been set 
     super.onMeasure(widthMeasureSpec, heightMeasureSpec); 
     int screenWidth = getMeasuredWidth(); 
     int leftViewWidth = getPaddingStart() + leftView.getMeasuredWidth() + leftView.getPaddingEnd(); 
     int rightViewWidth = getPaddingEnd() + rightView.getMeasuredWidth() + rightView.getPaddingStart(); 

     LayoutParams rightViewParams = (LayoutParams) rightView.getLayoutParams(); 
     if (!isMultiline && rightViewWidth + leftViewWidth > screenWidth) { 
      isMultiline = true; 
      rightViewParams.addRule(BELOW, R.id.left_view); 
      rightViewParams.removeRule(ALIGN_PARENT_END); 
      rightViewParams.addRule(ALIGN_PARENT_START); 
      //Call again here to adjust dimensions for new params 
      super.onMeasure(widthMeasureSpec, heightMeasureSpec); 
     } else if (isMultiline && rightViewWidth + leftViewWidth < screenWidth) { 
      isMultiline = false; 
      rightViewParams.removeRule(BELOW); 
      rightViewParams.addRule(ALIGN_PARENT_END); 
      rightViewParams.removeRule(ALIGN_PARENT_START); 
      //Call again here to adjust dimensions for new params 
      super.onMeasure(widthMeasureSpec, heightMeasureSpec); 
     } 
    } 

} 

布局XML:

<?xml version="1.0" encoding="utf-8"?> 
<merge 
    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"> 

    <TextView 
     android:id="@id/left_view" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_alignParentStart="true" 
     android:layout_centerVertical="true"/> 

    <EditText 
     android:id="@id/right_view" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_alignParentEnd="true" 
     android:gravity="center" 
     android:text="@string/hello"/> 

</merge> 
相关问题