2020
2121import android .content .Context ;
2222import android .content .res .TypedArray ;
23+ import android .graphics .Canvas ;
24+ import android .graphics .ColorFilter ;
25+ import android .graphics .PixelFormat ;
2326import android .graphics .drawable .Drawable ;
2427import android .os .Build .VERSION ;
2528import android .os .Build .VERSION_CODES ;
29+ import android .os .Parcel ;
2630import android .support .annotation .BoolRes ;
2731import android .support .annotation .DimenRes ;
2832import android .support .annotation .Dimension ;
2933import android .support .annotation .IdRes ;
34+ import android .support .annotation .NonNull ;
3035import android .support .annotation .Nullable ;
31- import com .google .android .material .internal .FlowLayout ;
36+ import com .google .android .material .internal .FlexWrap ;
37+ import com .google .android .material .internal .FlexboxLayout ;
3238import com .google .android .material .internal .ThemeEnforcement ;
3339import android .util .AttributeSet ;
3440import android .view .View ;
4652 * group unchecks any previously checked chip within the same group. The behavior mirrors that of
4753 * {@link android.widget.RadioGroup}.
4854 */
49- public class ChipGroup extends FlowLayout {
55+ public class ChipGroup extends FlexboxLayout {
5056
5157 /**
5258 * Interface definition for a callback to be invoked when the checked chip changed in this group.
@@ -62,8 +68,39 @@ public interface OnCheckedChangeListener {
6268 public void onCheckedChanged (ChipGroup group , @ IdRes int checkedId );
6369 }
6470
71+ /**
72+ * {@link FlexboxLayout.LayoutParams for {@link ChipGroup}.
73+ */
74+ public static class LayoutParams extends FlexboxLayout .LayoutParams {
75+ public LayoutParams (Context context , AttributeSet attrs ) {
76+ super (context , attrs );
77+ }
78+
79+ public LayoutParams (FlexboxLayout .LayoutParams source ) {
80+ super (source );
81+ }
82+
83+ public LayoutParams (ViewGroup .LayoutParams source ) {
84+ super (source );
85+ }
86+
87+ public LayoutParams (int width , int height ) {
88+ super (width , height );
89+ }
90+
91+ public LayoutParams (MarginLayoutParams source ) {
92+ super (source );
93+ }
94+
95+ protected LayoutParams (Parcel in ) {
96+ super (in );
97+ }
98+ }
99+
100+ private final SpacingDrawable spacingDrawable = new SpacingDrawable ();
65101 @ Dimension private int chipSpacingHorizontal ;
66102 @ Dimension private int chipSpacingVertical ;
103+ private boolean singleLine ;
67104 private boolean singleSelection ;
68105
69106 @ Nullable private OnCheckedChangeListener onCheckedChangeListener ;
@@ -107,9 +144,35 @@ public ChipGroup(Context context, AttributeSet attrs, int defStyleAttr) {
107144 }
108145
109146 a .recycle ();
147+
148+ setDividerDrawable (spacingDrawable );
149+ setShowDivider (SHOW_DIVIDER_MIDDLE );
150+ // Superclass uses presence of dividers to determine whether it needs to draw.
151+ setWillNotDraw (true );
152+
110153 super .setOnHierarchyChangeListener (passThroughListener );
111154 }
112155
156+ @ Override
157+ public FlexboxLayout .LayoutParams generateLayoutParams (AttributeSet attrs ) {
158+ return new ChipGroup .LayoutParams (getContext (), attrs );
159+ }
160+
161+ @ Override
162+ protected ViewGroup .LayoutParams generateLayoutParams (ViewGroup .LayoutParams lp ) {
163+ return new ChipGroup .LayoutParams (lp );
164+ }
165+
166+ @ Override
167+ protected ViewGroup .LayoutParams generateDefaultLayoutParams () {
168+ return new ChipGroup .LayoutParams (LayoutParams .WRAP_CONTENT , LayoutParams .WRAP_CONTENT );
169+ }
170+
171+ @ Override
172+ protected boolean checkLayoutParams (ViewGroup .LayoutParams p ) {
173+ return super .checkLayoutParams (p ) && (p instanceof ChipGroup .LayoutParams );
174+ }
175+
113176 @ Override
114177 public void setOnHierarchyChangeListener (OnHierarchyChangeListener listener ) {
115178 // the user listener is delegated to our pass-through listener
@@ -142,38 +205,43 @@ public void addView(View child, int index, ViewGroup.LayoutParams params) {
142205 super .addView (child , index , params );
143206 }
144207
145- /** Deprecated. Use {@link ChipGroup#setChipSpacingHorizontal(int)} instead. */
146- @ Deprecated
208+ @ Override
147209 public void setDividerDrawableHorizontal (Drawable divider ) {
148- throw new UnsupportedOperationException (
149- "Changing divider drawables have no effect. ChipGroup do not use divider drawables as "
150- + "spacing." );
210+ if (divider != spacingDrawable ) {
211+ throw new UnsupportedOperationException (
212+ "Changing divider drawables not allowed. ChipGroup uses divider drawables as spacing." );
213+ }
214+ super .setDividerDrawableHorizontal (divider );
151215 }
152216
153- /** Deprecated. Use {@link ChipGroup#setChipSpacingVertical(int)} instead. */
154- @ Deprecated
217+ @ Override
155218 public void setDividerDrawableVertical (@ Nullable Drawable divider ) {
156- throw new UnsupportedOperationException (
157- "Changing divider drawables have no effect. ChipGroup do not use divider drawables as "
158- + "spacing." );
219+ if (divider != spacingDrawable ) {
220+ throw new UnsupportedOperationException (
221+ "Changing divider drawables not allowed. ChipGroup uses divider drawables as spacing." );
222+ }
223+ super .setDividerDrawableVertical (divider );
159224 }
160225
161- /** Deprecated. Use {@link ChipGroup#setChipSpacingHorizontal(int)} instead. */
162- @ Deprecated
226+ @ Override
163227 public void setShowDividerHorizontal (int dividerMode ) {
164- throw new UnsupportedOperationException (
165- "Changing divider modes has no effect. ChipGroup do not use divider drawables as spacing." );
228+ if (dividerMode != SHOW_DIVIDER_MIDDLE ) {
229+ throw new UnsupportedOperationException (
230+ "Changing divider modes not allowed. ChipGroup uses divider drawables as spacing." );
231+ }
232+ super .setShowDividerHorizontal (dividerMode );
166233 }
167234
168- /** Deprecated. Use {@link ChipGroup#setChipSpacingVertical(int)} instead. */
169- @ Deprecated
235+ @ Override
170236 public void setShowDividerVertical (int dividerMode ) {
171- throw new UnsupportedOperationException (
172- "Changing divider modes has no effect. ChipGroup do not use divider drawables as spacing." );
237+ if (dividerMode != SHOW_DIVIDER_MIDDLE ) {
238+ throw new UnsupportedOperationException (
239+ "Changing divider modes not allowed. ChipGroup uses divider drawables as spacing." );
240+ }
241+ super .setShowDividerVertical (dividerMode );
173242 }
174243
175- /** Deprecated Use {@link ChipGroup#setSingleLine(int)} instead. */
176- @ Deprecated
244+ @ Override
177245 public void setFlexWrap (int flexWrap ) {
178246 throw new UnsupportedOperationException (
179247 "Changing flex wrap not allowed. ChipGroup exposes a singleLine attribute instead." );
@@ -287,7 +355,6 @@ public int getChipSpacingHorizontal() {
287355 public void setChipSpacingHorizontal (@ Dimension int chipSpacingHorizontal ) {
288356 if (this .chipSpacingHorizontal != chipSpacingHorizontal ) {
289357 this .chipSpacingHorizontal = chipSpacingHorizontal ;
290- setItemSpacing (chipSpacingHorizontal );
291358 requestLayout ();
292359 }
293360 }
@@ -307,7 +374,6 @@ public int getChipSpacingVertical() {
307374 public void setChipSpacingVertical (@ Dimension int chipSpacingVertical ) {
308375 if (this .chipSpacingVertical != chipSpacingVertical ) {
309376 this .chipSpacingVertical = chipSpacingVertical ;
310- setLineSpacing (chipSpacingVertical );
311377 requestLayout ();
312378 }
313379 }
@@ -317,6 +383,17 @@ public void setChipSpacingVerticalResource(@DimenRes int id) {
317383 setChipSpacingVertical (getResources ().getDimensionPixelOffset (id ));
318384 }
319385
386+ /** Returns whether this chip group is single line, or reflowed multiline. */
387+ public boolean isSingleLine () {
388+ return singleLine ;
389+ }
390+
391+ /** Sets whether this chip group is single line, or reflowed multiline. */
392+ public void setSingleLine (boolean singleLine ) {
393+ this .singleLine = singleLine ;
394+ super .setFlexWrap (singleLine ? FlexWrap .NOWRAP : FlexWrap .WRAP );
395+ }
396+
320397 /** Sets whether this chip group is single line, or reflowed multiline. */
321398 public void setSingleLine (@ BoolRes int id ) {
322399 setSingleLine (getResources ().getBoolean (id ));
@@ -349,6 +426,43 @@ public void setSingleSelection(@BoolRes int id) {
349426 setSingleSelection (getResources ().getBoolean (id ));
350427 }
351428
429+ /**
430+ * Drawable that only has intrinsic width/height and nothing else. Intended to be used as spacing
431+ * for {@link ChipGroup#setDividerDrawable(Drawable)}.
432+ */
433+ private class SpacingDrawable extends Drawable {
434+
435+ @ Override
436+ public int getIntrinsicWidth () {
437+ return chipSpacingHorizontal ;
438+ }
439+
440+ @ Override
441+ public int getIntrinsicHeight () {
442+ return chipSpacingVertical ;
443+ }
444+
445+ @ Override
446+ public void draw (@ NonNull Canvas canvas ) {
447+ // No-op.
448+ }
449+
450+ @ Override
451+ public void setAlpha (int alpha ) {
452+ // No-op.
453+ }
454+
455+ @ Override
456+ public void setColorFilter (@ Nullable ColorFilter colorFilter ) {
457+ // No-op.
458+ }
459+
460+ @ Override
461+ public int getOpacity () {
462+ return PixelFormat .TRANSPARENT ;
463+ }
464+ }
465+
352466 private class CheckedStateTracker implements CompoundButton .OnCheckedChangeListener {
353467 @ Override
354468 public void onCheckedChanged (CompoundButton buttonView , boolean isChecked ) {
0 commit comments