Android的换行小部件布局我正在尝试创建一个向用户显示一些数据的活动。数据可以分为“单词”,每个单词都是一个小部件,“单词”序列将形成数据(“句子”?),包含单词的ViewGroup小部件。由于“句子”中所有“单词”所需的空间将超过显示器上的可用水平空间,我想像正常的文本一样包装这些“句子”。以下代码:public class WrapTest extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout l = new LinearLayout(this);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
LinearLayout.LayoutParams mlp = new LinearLayout.LayoutParams(
new ViewGroup.MarginLayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT));
mlp.setMargins(0, 0, 2, 0);
for (int i = 0; i < 10; i++) {
TextView t = new TextView(this);
t.setText("Hello");
t.setBackgroundColor(Color.RED);
t.setSingleLine(true);
l.addView(t, mlp);
}
setContentView(l, lp);
}}产生类似左图的东西,但我想要一个布局呈现相同的小部件,如右图所示。是否有布局或布局和参数的组合,还是我必须为此实现自己的ViewGroup?
3 回答
![?](http://img1.sycdn.imooc.com/5333a0780001a6e702200220-100-100.jpg)
蝴蝶不菲
TA贡献1810条经验 获得超4个赞
我实现了与此类似的东西,但使用我认为处理间距和填充的更标准的方法。请让我知道你们的想法,并且可以在没有归属的情况下重复使用:
package com.asolutions.widget;import java.util.ArrayList;import java.util.Collections;import java.util.Iterator;import java.util.List;import android.content.Context;import android.content.res.TypedArray;import android.util.AttributeSet;import android.view.View;import android.view.ViewGroup;import com.asolutions.widget.R;public class RowLayout extends ViewGroup { public static final int DEFAULT_HORIZONTAL_SPACING = 5; public static final int DEFAULT_VERTICAL_SPACING = 5; private final int horizontalSpacing; private final int verticalSpacing; private List<RowMeasurement> currentRows = Collections.emptyList(); public RowLayout(Context context, AttributeSet attrs) { super(context, attrs); TypedArray styledAttributes = context.obtainStyledAttributes(attrs, R.styleable.RowLayout); horizontalSpacing = styledAttributes.getDimensionPixelSize(R.styleable.RowLayout_android_horizontalSpacing, DEFAULT_HORIZONTAL_SPACING); verticalSpacing = styledAttributes.getDimensionPixelSize(R.styleable.RowLayout_android_verticalSpacing, DEFAULT_VERTICAL_SPACING); styledAttributes.recycle(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { final int widthMode = MeasureSpec.getMode(widthMeasureSpec); final int heightMode = MeasureSpec.getMode(heightMeasureSpec); final int maxInternalWidth = MeasureSpec.getSize(widthMeasureSpec) - getHorizontalPadding(); final int maxInternalHeight = MeasureSpec.getSize(heightMeasureSpec) - getVerticalPadding(); List<RowMeasurement> rows = new ArrayList<RowMeasurement>(); RowMeasurement currentRow = new RowMeasurement(maxInternalWidth, widthMode); rows.add(currentRow); for (View child : getLayoutChildren()) { LayoutParams childLayoutParams = child.getLayoutParams(); int childWidthSpec = createChildMeasureSpec(childLayoutParams.width, maxInternalWidth, widthMode); int childHeightSpec = createChildMeasureSpec(childLayoutParams.height, maxInternalHeight, heightMode); child.measure(childWidthSpec, childHeightSpec); int childWidth = child.getMeasuredWidth(); int childHeight = child.getMeasuredHeight(); if (currentRow.wouldExceedMax(childWidth)) { currentRow = new RowMeasurement(maxInternalWidth, widthMode); rows.add(currentRow); } currentRow.addChildDimensions(childWidth, childHeight); } int longestRowWidth = 0; int totalRowHeight = 0; for (int index = 0; index < rows.size(); index++) { RowMeasurement row = rows.get(index); totalRowHeight += row.getHeight(); if (index < rows.size() - 1) { totalRowHeight += verticalSpacing; } longestRowWidth = Math.max(longestRowWidth, row.getWidth()); } setMeasuredDimension(widthMode == MeasureSpec.EXACTLY ? MeasureSpec.getSize(widthMeasureSpec) : longestRowWidth + getHorizontalPadding(), heightMode == MeasureSpec.EXACTLY ? MeasureSpec.getSize(heightMeasureSpec) : totalRowHeight + getVerticalPadding()); currentRows = Collections.unmodifiableList(rows); } private int createChildMeasureSpec(int childLayoutParam, int max, int parentMode) { int spec; if (childLayoutParam == LayoutParams.FILL_PARENT) { spec = MeasureSpec.makeMeasureSpec(max, MeasureSpec.EXACTLY); } else if (childLayoutParam == LayoutParams.WRAP_CONTENT) { spec = MeasureSpec.makeMeasureSpec(max, parentMode == MeasureSpec.UNSPECIFIED ? MeasureSpec.UNSPECIFIED : MeasureSpec.AT_MOST); } else { spec = MeasureSpec.makeMeasureSpec(childLayoutParam, MeasureSpec.EXACTLY); } return spec; } @Override protected void onLayout(boolean changed, int leftPosition, int topPosition, int rightPosition, int bottomPosition) { final int widthOffset = getMeasuredWidth() - getPaddingRight(); int x = getPaddingLeft(); int y = getPaddingTop(); Iterator<RowMeasurement> rowIterator = currentRows.iterator(); RowMeasurement currentRow = rowIterator.next(); for (View child : getLayoutChildren()) { final int childWidth = child.getMeasuredWidth(); final int childHeight = child.getMeasuredHeight(); if (x + childWidth > widthOffset) { x = getPaddingLeft(); y += currentRow.height + verticalSpacing; if (rowIterator.hasNext()) { currentRow = rowIterator.next(); } } child.layout(x, y, x + childWidth, y + childHeight); x += childWidth + horizontalSpacing; } } private List<View> getLayoutChildren() { List<View> children = new ArrayList<View>(); for (int index = 0; index < getChildCount(); index++) { View child = getChildAt(index); if (child.getVisibility() != View.GONE) { children.add(child); } } return children; } protected int getVerticalPadding() { return getPaddingTop() + getPaddingBottom(); } protected int getHorizontalPadding() { return getPaddingLeft() + getPaddingRight(); } private final class RowMeasurement { private final int maxWidth; private final int widthMode; private int width; private int height; public RowMeasurement(int maxWidth, int widthMode) { this.maxWidth = maxWidth; this.widthMode = widthMode; } public int getHeight() { return height; } public int getWidth() { return width; } public boolean wouldExceedMax(int childWidth) { return widthMode == MeasureSpec.UNSPECIFIED ? false : getNewWidth(childWidth) > maxWidth; } public void addChildDimensions(int childWidth, int childHeight) { width = getNewWidth(childWidth); height = Math.max(height, childHeight); } private int getNewWidth(int childWidth) { return width == 0 ? childWidth : width + horizontalSpacing + childWidth; } }}
这还需要在/res/values/attrs.xml下输入一个条目,如果它还没有,你可以创建它。
<?xml version="1.0" encoding="utf-8"?><resources> <declare-styleable name="RowLayout"> <attr name="android:verticalSpacing" /> <attr name="android:horizontalSpacing" /> </declare-styleable></resources>
xml布局中的用法如下所示:
<?xml version="1.0" encoding="utf-8"?><com.asolutions.widget.RowLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:padding="10dp" android:horizontalSpacing="10dp" android:verticalSpacing="20dp"> <FrameLayout android:layout_width="30px" android:layout_height="40px" android:background="#F00"/> <FrameLayout android:layout_width="60px" android:layout_height="40px" android:background="#F00"/> <FrameLayout android:layout_width="70px" android:layout_height="20px" android:background="#F00"/> <FrameLayout android:layout_width="20px" android:layout_height="60px" android:background="#F00"/> <FrameLayout android:layout_width="10px" android:layout_height="40px" android:background="#F00"/> <FrameLayout android:layout_width="40px" android:layout_height="40px" android:background="#F00"/> <FrameLayout android:layout_width="40px" android:layout_height="40px" android:background="#F00"/> <FrameLayout android:layout_width="40px" android:layout_height="40px" android:background="#F00"/></com.asolutions.widget.RowLayout>
- 3 回答
- 0 关注
- 592 浏览
添加回答
举报
0/150
提交
取消