With the new android support update, vector drawables get backward compatibility. I have a vector image with various paths. I want the color of the paths to change on click
You can achieve this without a library, and combine Data Binding with Kotlin.
ButtonBinding.kt
@SuppressLint("PrivateResource")
@BindingAdapter("drawable:start", "drawable:color", "button:isClicked", requireAll = false)
@JvmStatic
fun Button.setDrawableStartColor(@DrawableRes start: Int, @ColorRes color: Int, isClicked: Boolean) {
this.apply btn@{
context.apply ctx@{
val drawable = ContextCompat
.getDrawable(this, start)
?.apply {
if (isClicked) {
setColorFilter(
ContextCompat.getColor(this@ctx, color),
PorterDuff.Mode.SRC_ATOP)
}
}
setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null)
}
}
}
You can directly use setCompoundDrawablesWithIntrinsicBounds or setCompoundDrawables( but you have to define the current intrinsic bound, check out this article here
my_fragment.xml
For setup click listener, you can do this following as well:
YourFragment.kt
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
mViewBinding = AccountFragmentV2Binding
.inflate(inflater, container, false)
.apply {
viewModel = mViewModel // also, assign the correct view model to your xml
actionListener = this@AccountFragment
setLifecycleOwner(this@AccountFragment) // don't forget this
}
return mViewBinding.root
}
override fun onProfileClicked(v: View) {
mViewBinding.apply {
mViewModel.let {
// change and store the state, but don't forget to reset to default
it.clickState[R.drawable.v2_ic_person_blue] = v.isPressed
}
executePendingBindings() // update ui directly, without delays
}
}
ViewModel.kt
val clickState = ObservableArrayMap()
init {
clickState[R.drawable.ic_aktivitas_blue] = false
clickState[R.drawable.ic_person_blue] = false
clickState[R.drawable.ic_bookmark_blue] = false
}
Define the binding adapter with integer resource instead of using @color/ or @drawable. If you prefer using @ annotation (e.g: drawable:start="@{@drawable/id}") on the XML.
Change the data binding like this
fun Button.setDrawable(start: Drawable, color: Color) {
// do the conversion to int id, it will be a mess. that's why I stick to receive int id from resource instead
}
Also, don't forget to set up this from @aminography
Important Point in Using Android Vector Drawable When you are using an android vector drawable and want to have backward compatibility for API below 21, add the following codes to
In app level build.gradle:
android {
defaultConfig {
vectorDrawables.useSupportLibrary = true
}
}
In Application class:
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
}
}
Thanks to this answer here, @Varun here explained any other alternative, the original answer for my case here