Skip to content

Instantly share code, notes, and snippets.

@piruin
Last active May 3, 2023 13:09
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save piruin/6f095b73de09c71341cfc9d96b1408c7 to your computer and use it in GitHub Desktop.
Save piruin/6f095b73de09c71341cfc9d96b1408c7 to your computer and use it in GitHub Desktop.
Kotlin Extension for set/get compound Drawable to TextView/EditText/Button as property
/*
* Copyright 2017 Piruin Panichphol
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
@file:Suppress("NOTHING_TO_INLINE")
import android.app.Fragment
import android.content.Context
import android.graphics.PorterDuff
import android.graphics.drawable.Drawable
import android.os.Build
import android.support.annotation.DrawableRes
import android.view.View
import android.widget.TextView
import org.jetbrains.anko.AnkoContext
fun Context.drawable(@DrawableRes id: Int): Drawable {
return if (Build.VERSION.SDK_INT >= 21) {
resources.getDrawable(id, null)
} else {
@Suppress("DEPRECATION")
resources.getDrawable(id)
}
}
inline fun AnkoContext<*>.drawable(@DrawableRes id: Int) = ctx.drawable(id)
inline fun Fragment.drawable(@DrawableRes id: Int) = activity.drawable(id)
inline fun View.drawable(@DrawableRes id: Int) = context.drawable(id)
fun Drawable.tint(color: Int, mode: PorterDuff.Mode = PorterDuff.Mode.SRC_IN) {
mutate().setColorFilter(color, mode)
}
var TextView.drawableStart: Drawable?
get() = drawables[0]
set(value) = setDrawables(value, drawableTop, drawableEnd, drawableBottom)
var TextView.drawableTop: Drawable?
get() = drawables[1]
set(value) = setDrawables(drawableStart, value, drawableEnd, drawableBottom)
var TextView.drawableEnd: Drawable?
get() = drawables[2]
set(value) = setDrawables(drawableStart, drawableTop, value, drawableBottom)
var TextView.drawableBottom: Drawable?
get() = drawables[3]
set(value) = setDrawables(drawableStart, drawableTop, drawableEnd, value)
@Deprecated("Consider replace with drawableStart to better support right-to-left Layout", ReplaceWith("drawableStart"))
var TextView.drawableLeft: Drawable?
get() = compoundDrawables[0]
set(value) = setCompoundDrawablesWithIntrinsicBounds(value, drawableTop, drawableRight, drawableBottom)
@Deprecated("Consider replace with drawableEnd to better support right-to-left Layout", ReplaceWith("drawableEnd"))
var TextView.drawableRight: Drawable?
get() = compoundDrawables[2]
set(value) = setCompoundDrawablesWithIntrinsicBounds(drawableLeft, drawableTop, value, drawableBottom)
private val TextView.drawables: Array<Drawable?>
get() = if (Build.VERSION.SDK_INT >= 17) compoundDrawablesRelative else compoundDrawables
private fun TextView.setDrawables(start: Drawable?, top: Drawable?, end: Drawable?, buttom: Drawable?) {
if (Build.VERSION.SDK_INT >= 17)
setCompoundDrawablesRelativeWithIntrinsicBounds(start, top, end, buttom)
else
setCompoundDrawablesWithIntrinsicBounds(start, top, end, buttom)
}
class ExampleActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_example)
addButton.drawableStart = drawable(R.drawable.ic_add_white_24px)
addButton.drawableStart = drawable(R.drawable.ic_add_white_24px).apply { tint(Color.BLACK) }
}
}
@piruin
Copy link
Author

piruin commented Sep 9, 2017

Firstly, I create this extension because on Pre-Lollipop, we can't set plain vector drawables as compound drawables (drawableStart/Top/End/Bottom) at layout .xml file.

As my opinion, It better to set plain-vector-drawable programmatically than unnecessarily wrap it with drawable container such as a StateListDrawable, InsetDrawable .

Update : error on Pre-Lollipop occur by set
vectorDrawables.useSupportLibrary = true
without that line we can set vector drawable at xml directly

@amirmohammadqolami
Copy link

import org.jetbrains.anko.AnkoContext
this is unavailable in android studio 3.0.1 , so i can not use this method :
inline fun AnkoContext<*>.drawable(@DrawableRes id: Int) = ctx.drawable(id)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment