diff --git a/README.md b/README.md index 5b4a0a5..0ec8d60 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,8 @@ # FlowLayout Android流式布局,支持单选、多选等,适合用于产品标签等。 +## 特色 -##特色 * 以setAdapter形式注入数据 * 直接设置selector为background即可完成标签选则的切换,类似CheckBox * 支持控制选择的Tag数量,比如:单选、多选 @@ -13,12 +13,16 @@ Android流式布局,支持单选、多选等,适合用于产品标签等。 * 支持adapter.notifyDataChanged * Activity重建(或者旋转)后,选择的状态自动保存 -##效果图 +## 效果图 + + + + ## 用法 ```java @@ -30,26 +34,34 @@ dependencies { ### 声明 布局文件中声明: -```java - - +``` + + ``` 支持属性: -`max_select`:-1为不限制选择数量,>=1的数字为控制选择tag的数量 +| 属性 | 单位 | 说明 | +| ------------------ | ------- | ------------------------------------------------------------ | +| max_select | integer | -1为不限制选择数量,>=1的数字为控制选择tag的数量 | +| horizontal_padding | dp | 标签之间水平padding | +| vertical_padding | dp | 标签之间垂直padding | +| auto_stretch | boolean | 标签两端对齐,中间间隙均分 | 支持通过state=checked来控制选中和取消,也可以自己在Adapter 的onSelected和unSelected中分别处理显示。 -###设置数据 +### 设置数据 -```java +``` mFlowLayout.setAdapter(new TagAdapter(mVals) { @Override @@ -68,7 +80,7 @@ getView中回调,类似ListView等用法。 ### 对于选中状态 -```java +``` mLineWidth = new ArrayList(); private int mGravity; private List lineViews = new ArrayList<>(); + private int mTagVerticalPadding, mTagHorizontalPadding; + private boolean mAutoStretch; public FlowLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.TagFlowLayout); mGravity = ta.getInt(R.styleable.TagFlowLayout_tag_gravity, LEFT); + mTagVerticalPadding = ta.getDimensionPixelSize(R.styleable.TagFlowLayout_vertical_padding, 0); + mTagHorizontalPadding = ta.getDimensionPixelSize(R.styleable.TagFlowLayout_horizontal_padding, 0); + mAutoStretch = ta.getBoolean(R.styleable.TagFlowLayout_auto_stretch, false); int layoutDirection = TextUtilsCompat.getLayoutDirectionFromLocale(Locale.getDefault()); if (layoutDirection == LayoutDirection.RTL) { if (mGravity == LEFT) { @@ -63,13 +68,13 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int lineHeight = 0; int cCount = getChildCount(); - for (int i = 0; i < cCount; i++) { View child = getChildAt(i); if (child.getVisibility() == View.GONE) { if (i == cCount - 1) { + lineWidth -= mTagHorizontalPadding; width = Math.max(lineWidth, width); - height += lineHeight; + height += lineHeight - mTagVerticalPadding; } continue; } @@ -80,20 +85,22 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int childWidth = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin; int childHeight = child.getMeasuredHeight() + lp.topMargin - + lp.bottomMargin; + + lp.bottomMargin + mTagVerticalPadding; if (lineWidth + childWidth > sizeWidth - getPaddingLeft() - getPaddingRight()) { + lineWidth -= mTagHorizontalPadding; width = Math.max(width, lineWidth); lineWidth = childWidth; height += lineHeight; lineHeight = childHeight; } else { - lineWidth += childWidth; + lineWidth += childWidth + mTagHorizontalPadding; lineHeight = Math.max(lineHeight, childHeight); } if (i == cCount - 1) { + lineWidth -= mTagHorizontalPadding; width = Math.max(lineWidth, width); - height += lineHeight; + height += lineHeight - mTagVerticalPadding; } } setMeasuredDimension( @@ -125,29 +132,30 @@ protected void onLayout(boolean changed, int l, int t, int r, int b) { MarginLayoutParams lp = (MarginLayoutParams) child .getLayoutParams(); - int childWidth = child.getMeasuredWidth(); - int childHeight = child.getMeasuredHeight(); + int childWidth = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin; + int childHeight = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin + mTagVerticalPadding; - if (childWidth + lineWidth + lp.leftMargin + lp.rightMargin > width - getPaddingLeft() - getPaddingRight()) { + if (childWidth + lineWidth > width - getPaddingLeft() - getPaddingRight()) { + lineWidth -= mTagHorizontalPadding; mLineHeight.add(lineHeight); mAllViews.add(lineViews); mLineWidth.add(lineWidth); lineWidth = 0; - lineHeight = childHeight + lp.topMargin + lp.bottomMargin; + lineHeight = childHeight; lineViews = new ArrayList(); } - lineWidth += childWidth + lp.leftMargin + lp.rightMargin; - lineHeight = Math.max(lineHeight, childHeight + lp.topMargin - + lp.bottomMargin); + lineWidth += childWidth + mTagHorizontalPadding; + lineHeight = Math.max(lineHeight, childHeight); lineViews.add(child); } + lineWidth -= mTagHorizontalPadding; + lineHeight -= mTagVerticalPadding; mLineHeight.add(lineHeight); mLineWidth.add(lineWidth); mAllViews.add(lineViews); - int left = getPaddingLeft(); int top = getPaddingTop(); @@ -173,8 +181,12 @@ protected void onLayout(boolean changed, int l, int t, int r, int b) { Collections.reverse(lineViews); break; } - - for (int j = 0; j < lineViews.size(); j++) { + int lineChildCount = lineViews.size(); + int gap = 0; + if (lineChildCount > 1) { + gap = (width - currentLineWidth) / (lineChildCount - 1); + } + for (int j = 0; j < lineChildCount; j++) { View child = lineViews.get(j); if (child.getVisibility() == View.GONE) { continue; @@ -191,11 +203,11 @@ protected void onLayout(boolean changed, int l, int t, int r, int b) { child.layout(lc, tc, rc, bc); left += child.getMeasuredWidth() + lp.leftMargin - + lp.rightMargin; + + lp.rightMargin + mTagHorizontalPadding; + if (mAutoStretch) left += gap; } top += lineHeight; } - } @Override diff --git a/flowlayout-lib/src/main/res/values/attrs.xml b/flowlayout-lib/src/main/res/values/attrs.xml index d1454ed..8c31386 100644 --- a/flowlayout-lib/src/main/res/values/attrs.xml +++ b/flowlayout-lib/src/main/res/values/attrs.xml @@ -7,5 +7,8 @@ + + + \ No newline at end of file diff --git a/horizontal_padding_and_vertical_padding_sample.png b/horizontal_padding_and_vertical_padding_sample.png new file mode 100644 index 0000000..be75a1f Binary files /dev/null and b/horizontal_padding_and_vertical_padding_sample.png differ