一、效果
二、实现
1.自定义View
public class FeatureGroupView extends ViewGroup{ //itemSpaceVertical为列与列之间的间距 private int itemSpaceVertical, itemSpaceHorizontal, maxLineNum; private int paddingTop, paddingBottom, paddingLeft, paddingRight; private int moreTextColor, moreTextSize; private TextView moreTextView; public FeatureGroupView(Context context) { super(context); } public FeatureGroupView(Context context, AttributeSet attrs) { super(context, attrs); TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.FixedWidthViewGroup);//自定义样式,名字为FixedWidthViewGroup itemSpaceVertical = (int) typedArray.getDimension(R.styleable.FixedWidthViewGroup_itemSpaceVertical, 0); itemSpaceHorizontal = (int) typedArray.getDimension(R.styleable.FixedWidthViewGroup_itemSpaceHorizontal, 0); maxLineNum = typedArray.getInt(R.styleable.FixedWidthViewGroup_maxLineNum, Integer.MAX_VALUE); moreTextColor = typedArray.getColor(R.styleable.FixedWidthViewGroup_moreTextColor, -1); moreTextSize = typedArray.getInt(R.styleable.FixedWidthViewGroup_moreTextSize, -1); paddingTop = getPaddingTop(); paddingBottom = getPaddingBottom(); paddingLeft = getPaddingLeft(); paddingRight = getPaddingRight(); typedArray.recycle(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){ final int count = getChildCount(); int parentWidth = MeasureSpec.getSize(widthMeasureSpec) - paddingRight; if(maxLineNum != Integer.MAX_VALUE){ moreTextView = createMore(); moreTextView.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED); parentWidth = parentWidth - (itemSpaceVertical + moreTextView.getMeasuredWidth()); } int lengthY = paddingTop; int lengthX = paddingLeft; int lineNum = 0; for(int i = 0; i < count; i++){ final View child = getChildAt(i); if(child.getVisibility() == GONE){ continue; } child.measure(MeasureSpec.UNSPECIFIED,MeasureSpec.UNSPECIFIED); int width = child.getMeasuredWidth(); int height = child.getMeasuredHeight(); if(lengthY <= paddingTop){ lengthY += height; } if(i == 0){ lengthX += width; }else{ lengthX += width + itemSpaceVertical; } if(lengthX > parentWidth){ lineNum++; if(lineNum >= maxLineNum){ //如果超过规定的最大行数 标记上一行最后一个为结束项 if(i - 1 >= 0){ LayoutData layoutData = (LayoutData) getChildAt(i - 1).getTag(); if (layoutData != null) { layoutData.isEnd = true; } } break; } lengthX = paddingLeft + width; lengthY = lengthY + height + itemSpaceHorizontal; } child.setTag(new LayoutData(lengthX, lengthY)); } setMeasuredDimension(widthMeasureSpec, MeasureSpec.makeMeasureSpec( lengthY + paddingBottom, MeasureSpec.UNSPECIFIED)); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { for (int i = 0; i < getChildCount(); i++) { final View child = this.getChildAt(i); if (child.getVisibility() == GONE) { continue; } if(child.getTag() == null){ break; } LayoutData layoutData = (LayoutData) child.getTag(); if (layoutData != null) { int left = layoutData.x - child.getMeasuredWidth(); int top = layoutData.y - child.getMeasuredHeight(); child.layout(left, top, layoutData.x,layoutData.y); if(layoutData.isEnd && moreTextView!= null){ addView(moreTextView); moreTextView.layout(child.getRight() + itemSpaceVertical , child.getBottom() - moreTextView.getMeasuredHeight() , child.getRight()+ itemSpaceVertical + moreTextView.getMeasuredWidth(), child.getBottom()); } } } } //简单起见,这里用了TextView,并设置内容为"..." private TextView createMore(){ TextView more = new TextView(getContext()); more.setText("..."); more.setGravity(Gravity.CENTER); if(moreTextColor != -1){ more.setTextColor(moreTextColor); } if(moreTextSize != -1){ more.setTextSize(moreTextSize); } return more; } private class LayoutData{ int x; int y; boolean isEnd; public LayoutData(int x, int y) { this.x = x; this.y = y; } } }
2.自定义R.styleable.FixedWidthViewGroup样式
res/values/attrs.xml文件的<resources>标签下增加内容:
<?xml version="1.0" encoding="utf-8"?> <resources> ... ... <declare-styleable name="FixedWidthViewGroup"> <attr name="itemSpaceVertical" format="dimension" /> <attr name="itemSpaceHorizontal" format="dimension" /> <attr name="maxLineNum" format="integer" /> <attr name="moreTextColor" format="color" /> <attr name="moreTextSize" format="integer" /> </declare-styleable> </resources>
3.每个item的布局,
item_feature.xml:
<?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginRight="3dp" android:gravity="center" android:paddingBottom="1dp" android:paddingLeft="3dp" android:paddingRight="3dp" android:paddingTop="1dp" android:singleLine="true" android:textColor="#80b2bf" android:textSize="11sp" android:background="@drawable/feature_item_bg"/>
4.res/drawable/feature_item_bg.xml
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item> <shape android:shape="rectangle"> <stroke android:width="1dp" android:color="#80b2bf" /> <solid android:color="@android:color/transparent" /> <corners android:radius="2dp" /> </shape> </item> </selector>
5.Activity的布局文件
activity_freture_group.xml:
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_height="match_parent" android:layout_width="match_parent" android:background="#FFEEDD"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:showDividers="middle" android:dividerPadding="20dp"> <view.FeatureGroupView android:id="@+id/features1" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:padding="10dp" android:orientation="horizontal" android:background="#d0d0d0" app:itemSpaceVertical="10dp" app:maxLineNum="1" app:moreTextColor="#80b2bf" app:moreTextSize="12" /> <view.FeatureGroupView android:id="@+id/features2" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:background="#d0d0d0" android:orientation="horizontal" app:itemSpaceVertical="4dp" app:itemSpaceHorizontal="4dp" app:maxLineNum="2" app:moreTextColor="#80b2bf" app:moreTextSize="12" /> <view.FeatureGroupView android:id="@+id/features3" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:orientation="horizontal" android:paddingLeft="10dp" android:background="#d0d0d0" app:itemSpaceVertical="4dp" app:moreTextColor="#80b2bf" app:moreTextSize="12" /> <view.FeatureGroupView android:id="@+id/features4" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:orientation="horizontal" android:background="#d0d0d0" android:padding="10dp" app:itemSpaceVertical="4dp" app:itemSpaceHorizontal="2dp" app:maxLineNum="2" app:moreTextColor="#80b2bf" app:moreTextSize="12" /> </LinearLayout> </ScrollView>
说明:
xmlns:app="http://schemas.android.com/apk/res-auto" , 加上这一句便可以使用<declare-styleable>中自定义的样式,app为命名空间,可以写成其他名字。
app:itemSpaceVertical="10dp" , 使用自定义样式中的属性,"app"为"xmlns:app=..."中的"app"
6.Activity代码
public class FeatureGroupActivity extends Activity { private FeatureGroupView featureGroupView1; private FeatureGroupView featureGroupView2; private FeatureGroupView featureGroupView3; private FeatureGroupView featureGroupView4; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_freture_group); featureGroupView1 = (FeatureGroupView)findViewById(R.id.features1); featureGroupView2 = (FeatureGroupView)findViewById(R.id.features2); featureGroupView3 = (FeatureGroupView)findViewById(R.id.features3); featureGroupView4 = (FeatureGroupView)findViewById(R.id.features4); addFeatures(featureGroupView1); addFeatures(featureGroupView2); addFeatures(featureGroupView3); addFeatures(featureGroupView4); } private void addFeatures(ViewGroup viewGroup){ for(String str: getFeatures()){ TextView feature = (TextView) getLayoutInflater().inflate(R.layout.item_feature, null); feature.setText(str); viewGroup.addView(feature); } } private List<String> getFeatures(){ List<String> list = new ArrayList<>(); list.add("北京"); list.add("上海"); list.add("广东"); list.add("四川"); list.add("威海"); list.add("大连"); list.add("青岛"); list.add("浙江"); list.add("海口"); list.add("西安"); list.add("山东"); list.add("济南"); list.add("河北"); list.add("石家庄"); list.add("香港"); list.add("西藏"); list.add("新疆"); list.add("重庆"); list.add("秦皇岛"); list.add("保定"); list.add("太原"); list.add("天津"); list.add("黑龙江"); list.add("哈尔滨"); return list; } }
时间: 2024-10-24 07:36:20