77import android .content .Context ;
88import android .content .res .TypedArray ;
99import android .os .Build ;
10+ import android .support .annotation .NonNull ;
11+ import android .support .annotation .Nullable ;
1012import android .util .AttributeSet ;
1113import android .view .ViewGroup ;
1214import android .view .animation .AccelerateDecelerateInterpolator ;
1315import android .widget .TextView ;
1416
1517import java .lang .reflect .Field ;
18+ import java .util .ArrayList ;
19+ import java .util .List ;
1620
1721import at .blogc .expandabletextview .BuildConfig ;
1822import at .blogc .expandabletextview .R ;
@@ -39,7 +43,7 @@ public class ExpandableTextView extends TextView
3943 // copy off TextView.LINES
4044 private static final int MAXMODE_LINES = 1 ;
4145
42- private OnExpandListener onExpandListener ;
46+ private final List < OnExpandListener > onExpandListeners ;
4347 private TimeInterpolator expandInterpolator ;
4448 private TimeInterpolator collapseInterpolator ;
4549
@@ -54,12 +58,12 @@ public ExpandableTextView(final Context context)
5458 this (context , null );
5559 }
5660
57- public ExpandableTextView (final Context context , final AttributeSet attrs )
61+ public ExpandableTextView (final Context context , @ Nullable final AttributeSet attrs )
5862 {
5963 this (context , attrs , 0 );
6064 }
6165
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 )
6367 {
6468 super (context , attrs , defStyle );
6569
@@ -71,6 +75,9 @@ public ExpandableTextView(final Context context, final AttributeSet attrs, final
7175 // keep the original value of maxLines
7276 this .maxLines = this .getMaxLines ();
7377
78+ // create bucket for OnExpandListener instances
79+ this .onExpandListeners = new ArrayList <>();
80+
7481 // create default interpolators
7582 this .expandInterpolator = new AccelerateDecelerateInterpolator ();
7683 this .collapseInterpolator = new AccelerateDecelerateInterpolator ();
@@ -102,6 +109,9 @@ public int getMaxLines()
102109 }
103110 }
104111
112+
113+ //region public helper methods
114+
105115 /**
106116 * Toggle the expanded state of this {@link ExpandableTextView}.
107117 * @return true if toggled, false otherwise.
@@ -124,10 +134,7 @@ public boolean expand()
124134 this .animating = true ;
125135
126136 // notify listener
127- if (this .onExpandListener != null )
128- {
129- this .onExpandListener .onExpand (this );
130- }
137+ this .notifyOnExpand ();
131138
132139 // get collapsed height
133140 this .measure
@@ -205,10 +212,7 @@ public boolean collapse()
205212 this .animating = true ;
206213
207214 // notify listener
208- if (this .onExpandListener != null )
209- {
210- this .onExpandListener .onCollapse (this );
211- }
215+ this .notifyOnCollapse ();
212216
213217 // get expanded height
214218 final int expandedHeight = this .getMeasuredHeight ();
@@ -260,6 +264,10 @@ public void onAnimationEnd(final Animator animation)
260264 return false ;
261265 }
262266
267+ //endregion
268+
269+ //region public getters and setters
270+
263271 /**
264272 * Sets the duration of the expand / collapse animation.
265273 * @param animationDuration duration in milliseconds.
@@ -270,21 +278,21 @@ public void setAnimationDuration(final long animationDuration)
270278 }
271279
272280 /**
273- * Sets a listener which receives updates about this {@link ExpandableTextView}.
281+ * Adds a listener which receives updates about this {@link ExpandableTextView}.
274282 * @param onExpandListener the listener.
275283 */
276- public void setOnExpandListener (final OnExpandListener onExpandListener )
284+ public void addOnExpandListener (final OnExpandListener onExpandListener )
277285 {
278- this .onExpandListener = onExpandListener ;
286+ this .onExpandListeners . add ( onExpandListener ) ;
279287 }
280288
281289 /**
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.
284292 */
285- public OnExpandListener getOnExpandListener ( )
293+ public void removeOnExpandListener ( final OnExpandListener onExpandListener )
286294 {
287- return this .onExpandListener ;
295+ this .onExpandListeners . remove ( onExpandListener ) ;
288296 }
289297
290298 /**
@@ -342,6 +350,32 @@ public boolean isExpanded()
342350 return this .expanded ;
343351 }
344352
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+
345379 /**
346380 * Interface definition for a callback to be invoked when
347381 * a {@link ExpandableTextView} is expanded or collapsed.
@@ -352,12 +386,34 @@ public interface OnExpandListener
352386 * The {@link ExpandableTextView} is being expanded.
353387 * @param view the textview
354388 */
355- void onExpand (ExpandableTextView view );
389+ void onExpand (@ NonNull ExpandableTextView view );
356390
357391 /**
358392 * The {@link ExpandableTextView} is being collapsed.
359393 * @param view the textview
360394 */
361- void onCollapse (ExpandableTextView view );
395+ void onCollapse (@ NonNull ExpandableTextView view );
362396 }
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
363419}
0 commit comments