7
7
import android .content .Context ;
8
8
import android .content .res .TypedArray ;
9
9
import android .os .Build ;
10
+ import android .support .annotation .NonNull ;
11
+ import android .support .annotation .Nullable ;
10
12
import android .util .AttributeSet ;
11
13
import android .view .ViewGroup ;
12
14
import android .view .animation .AccelerateDecelerateInterpolator ;
13
15
import android .widget .TextView ;
14
16
15
17
import java .lang .reflect .Field ;
18
+ import java .util .ArrayList ;
19
+ import java .util .List ;
16
20
17
21
import at .blogc .expandabletextview .BuildConfig ;
18
22
import at .blogc .expandabletextview .R ;
@@ -39,7 +43,7 @@ public class ExpandableTextView extends TextView
39
43
// copy off TextView.LINES
40
44
private static final int MAXMODE_LINES = 1 ;
41
45
42
- private OnExpandListener onExpandListener ;
46
+ private final List < OnExpandListener > onExpandListeners ;
43
47
private TimeInterpolator expandInterpolator ;
44
48
private TimeInterpolator collapseInterpolator ;
45
49
@@ -54,12 +58,12 @@ public ExpandableTextView(final Context context)
54
58
this (context , null );
55
59
}
56
60
57
- public ExpandableTextView (final Context context , final AttributeSet attrs )
61
+ public ExpandableTextView (final Context context , @ Nullable final AttributeSet attrs )
58
62
{
59
63
this (context , attrs , 0 );
60
64
}
61
65
62
- public ExpandableTextView (final Context context , final AttributeSet attrs , final int defStyle )
66
+ public ExpandableTextView (final Context context , @ Nullable final AttributeSet attrs , final int defStyle )
63
67
{
64
68
super (context , attrs , defStyle );
65
69
@@ -71,6 +75,9 @@ public ExpandableTextView(final Context context, final AttributeSet attrs, final
71
75
// keep the original value of maxLines
72
76
this .maxLines = this .getMaxLines ();
73
77
78
+ // create bucket for OnExpandListener instances
79
+ this .onExpandListeners = new ArrayList <>();
80
+
74
81
// create default interpolators
75
82
this .expandInterpolator = new AccelerateDecelerateInterpolator ();
76
83
this .collapseInterpolator = new AccelerateDecelerateInterpolator ();
@@ -102,6 +109,9 @@ public int getMaxLines()
102
109
}
103
110
}
104
111
112
+
113
+ //region public helper methods
114
+
105
115
/**
106
116
* Toggle the expanded state of this {@link ExpandableTextView}.
107
117
* @return true if toggled, false otherwise.
@@ -124,10 +134,7 @@ public boolean expand()
124
134
this .animating = true ;
125
135
126
136
// notify listener
127
- if (this .onExpandListener != null )
128
- {
129
- this .onExpandListener .onExpand (this );
130
- }
137
+ this .notifyOnExpand ();
131
138
132
139
// get collapsed height
133
140
this .measure
@@ -205,10 +212,7 @@ public boolean collapse()
205
212
this .animating = true ;
206
213
207
214
// notify listener
208
- if (this .onExpandListener != null )
209
- {
210
- this .onExpandListener .onCollapse (this );
211
- }
215
+ this .notifyOnCollapse ();
212
216
213
217
// get expanded height
214
218
final int expandedHeight = this .getMeasuredHeight ();
@@ -260,6 +264,10 @@ public void onAnimationEnd(final Animator animation)
260
264
return false ;
261
265
}
262
266
267
+ //endregion
268
+
269
+ //region public getters and setters
270
+
263
271
/**
264
272
* Sets the duration of the expand / collapse animation.
265
273
* @param animationDuration duration in milliseconds.
@@ -270,21 +278,21 @@ public void setAnimationDuration(final long animationDuration)
270
278
}
271
279
272
280
/**
273
- * Sets a listener which receives updates about this {@link ExpandableTextView}.
281
+ * Adds a listener which receives updates about this {@link ExpandableTextView}.
274
282
* @param onExpandListener the listener.
275
283
*/
276
- public void setOnExpandListener (final OnExpandListener onExpandListener )
284
+ public void addOnExpandListener (final OnExpandListener onExpandListener )
277
285
{
278
- this .onExpandListener = onExpandListener ;
286
+ this .onExpandListeners . add ( onExpandListener ) ;
279
287
}
280
288
281
289
/**
282
- * Returns the {@link OnExpandListener }.
283
- * @return the listener.
290
+ * Removes a listener which receives updates about this {@link ExpandableTextView }.
291
+ * @param onExpandListener the listener.
284
292
*/
285
- public OnExpandListener getOnExpandListener ( )
293
+ public void removeOnExpandListener ( final OnExpandListener onExpandListener )
286
294
{
287
- return this .onExpandListener ;
295
+ this .onExpandListeners . remove ( onExpandListener ) ;
288
296
}
289
297
290
298
/**
@@ -342,6 +350,32 @@ public boolean isExpanded()
342
350
return this .expanded ;
343
351
}
344
352
353
+ //endregion
354
+
355
+ /**
356
+ * This method will notify the listener about this view being expanded.
357
+ */
358
+ private void notifyOnCollapse ()
359
+ {
360
+ for (final OnExpandListener onExpandListener : this .onExpandListeners )
361
+ {
362
+ onExpandListener .onCollapse (this );
363
+ }
364
+ }
365
+
366
+ /**
367
+ * This method will notify the listener about this view being collapsed.
368
+ */
369
+ private void notifyOnExpand ()
370
+ {
371
+ for (final OnExpandListener onExpandListener : this .onExpandListeners )
372
+ {
373
+ onExpandListener .onExpand (this );
374
+ }
375
+ }
376
+
377
+ //region public interfaces
378
+
345
379
/**
346
380
* Interface definition for a callback to be invoked when
347
381
* a {@link ExpandableTextView} is expanded or collapsed.
@@ -352,12 +386,34 @@ public interface OnExpandListener
352
386
* The {@link ExpandableTextView} is being expanded.
353
387
* @param view the textview
354
388
*/
355
- void onExpand (ExpandableTextView view );
389
+ void onExpand (@ NonNull ExpandableTextView view );
356
390
357
391
/**
358
392
* The {@link ExpandableTextView} is being collapsed.
359
393
* @param view the textview
360
394
*/
361
- void onCollapse (ExpandableTextView view );
395
+ void onCollapse (@ NonNull ExpandableTextView view );
362
396
}
397
+
398
+ /**
399
+ * Simple implementation of the {@link OnExpandListener} interface with stub
400
+ * implementations of each method. Extend this if you do not intend to override
401
+ * every method of {@link OnExpandListener}.
402
+ */
403
+ public static class SimpleOnExpandListener implements OnExpandListener
404
+ {
405
+ @ Override
406
+ public void onExpand (@ NonNull final ExpandableTextView view )
407
+ {
408
+ // empty implementation
409
+ }
410
+
411
+ @ Override
412
+ public void onCollapse (@ NonNull final ExpandableTextView view )
413
+ {
414
+ // empty implementation
415
+ }
416
+ }
417
+
418
+ //endregion
363
419
}
0 commit comments