@@ -2,83 +2,88 @@ package og.android.lib.toggleiconview
22
33import android.content.Context
44import android.util.AttributeSet
5+ import androidx.annotation.DrawableRes
56import androidx.appcompat.widget.AppCompatImageView
67import androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat
78
89abstract class ToggleIconView @JvmOverloads constructor(
910 context : Context , attrs : AttributeSet ? = null , defStyleAttr : Int = 0 ,
10- checkedDrawableRes : Int ,
11- uncheckedDrawableRes : Int ,
11+ @DrawableRes checkedDrawableResId : Int ,
12+ @DrawableRes uncheckedDrawableResId : Int ,
1213) : AppCompatImageView(context, attrs, defStyleAttr) {
13- private var onCheckedChangeListener : ((toggleIconView : ToggleIconView , isChecked : Boolean ) -> Unit ) ? =
14- null
14+ private lateinit var checkedDrawable : AnimatedVectorDrawableCompat
15+ private lateinit var uncheckedDrawable : AnimatedVectorDrawableCompat
1516
16- private var checkedDrawable: AnimatedVectorDrawableCompat ? = null
17- private var uncheckedDrawable: AnimatedVectorDrawableCompat ? = null
18- private var isChecked = false
17+ private var isChecked: Boolean = false
18+ private var onCheckedChangeListener: ((toggleIconView: ToggleIconView , isChecked: Boolean ) -> Unit )? = null
1919
2020 init {
21- setCheckedDrawable(checkedDrawableRes )
22- setUncheckedDrawable(uncheckedDrawableRes )
21+ setCheckedDrawable(checkedDrawableResId )
22+ setUncheckedDrawable(uncheckedDrawableResId )
2323 handleAttributes(attrs, defStyleAttr)
2424 }
2525
26- fun toggle ( ) {
27- setChecked( ! isChecked)
26+ private fun setCheckedDrawable (@DrawableRes drawableResId : Int ) {
27+ checkedDrawable = AnimatedVectorDrawableCompat .create(context, drawableResId) !!
2828 }
2929
30- fun isChecked (): Boolean {
31- return isChecked
30+ private fun setUncheckedDrawable (@DrawableRes drawableResId : Int ) {
31+ uncheckedDrawable = AnimatedVectorDrawableCompat .create(context, drawableResId) !!
3232 }
3333
34- fun setChecked (checked : Boolean ) {
35- handleCheckState(checked)
36- isChecked = checked
37-
38- onCheckedChangeListener?.invoke(this , checked)
39- }
40-
41- interface OnCheckedChangeListener {
42- fun onCheckedChanged (toggleIconView : ToggleIconView , isChecked : Boolean )
43- }
44-
45- private fun handleCheckedState () {
34+ private fun setAndAnimateCheckedDrawable () {
4635 setImageDrawable(checkedDrawable)
47- checkedDrawable!! .start()
36+ checkedDrawable.start()
4837 }
4938
50- private fun handleUncheckedState () {
39+ private fun setAndAnimateUncheckedDrawable () {
5140 setImageDrawable(uncheckedDrawable)
52- uncheckedDrawable!! .start()
41+ uncheckedDrawable.start()
5342 }
5443
55- private fun handleCheckState (checked : Boolean ) {
44+ private fun setAndAnimateDrawableByCheckState (checked : Boolean ) {
5645 if (checked) {
57- handleCheckedState ()
46+ setAndAnimateCheckedDrawable ()
5847 } else {
59- handleUncheckedState ()
48+ setAndAnimateUncheckedDrawable ()
6049 }
6150 }
6251
52+ private fun handleCheckState (checked : Boolean ) {
53+ setAndAnimateDrawableByCheckState(checked)
54+ isChecked = checked
55+ }
56+
6357 private fun handleAttributes (attrs : AttributeSet ? = null, defStyleAttr : Int = 0) {
64- val typedArray =
65- context.theme.obtainStyledAttributes(attrs, R .styleable.ToggleIconView , defStyleAttr, 0 )
58+ val typedArray = context.theme.obtainStyledAttributes(attrs, R .styleable.ToggleIconView , defStyleAttr, 0 )
6659
6760 try {
6861 // app:checked
6962 val checked = typedArray.getBoolean(R .styleable.ToggleIconView_checked , isChecked)
70- setChecked(checked)
63+
64+ handleCheckState(checked)
7165 } finally {
7266 typedArray.recycle()
7367 }
7468 }
7569
76- private fun setCheckedDrawable ( checkedDrawableRes : Int ) {
77- checkedDrawable = AnimatedVectorDrawableCompat .create(context, checkedDrawableRes )
70+ fun toggle ( ) {
71+ setChecked( ! isChecked )
7872 }
7973
80- private fun setUncheckedDrawable (uncheckedDrawableRes : Int ) {
81- uncheckedDrawable = AnimatedVectorDrawableCompat .create(context, uncheckedDrawableRes)
74+ fun isChecked (): Boolean {
75+ return isChecked
76+ }
77+
78+ fun setChecked (checked : Boolean ) {
79+ // We won't update the status if the status is the same as the current status
80+ // This is to prevent the animation from restarting when the state is set again
81+ if (checked == isChecked) {
82+ return
83+ }
84+
85+ handleCheckState(checked)
86+ onCheckedChangeListener?.invoke(this , checked)
8287 }
8388
8489 open fun setOnCheckedChangeListener (listener : (toggleIconView: ToggleIconView , isChecked: Boolean ) -> Unit ) {
0 commit comments