随着新的Android支持更新,矢量drawables获得向后兼容性。我有一个带有各种路径的矢量图像。我希望通过单击按钮或基于输入值以编程方式更改路径的颜色。是否可以访问矢量路径的name参数?然后改变颜色。
答案 0 :(得分:47)
可以使用setTint更改整个矢量的颜色。
您必须在布局文件中设置ImageView,如下所示:
<ImageView
android:id="@+id/myImageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:tint="@color/my_nice_color"
android:src="@drawable/ic_my_drawable"
android:scaleType="fitCenter" />
然后改变图像的颜色:
DrawableCompat.setTint(myImageView.getDrawable(), ContextCompat.getColor(context, R.color.another_nice_color));
注意:如果向量drawable设置为imageView作为背景,myImageView.getDrawable()
会给出nullpointerexception。
答案 1 :(得分:13)
Use this to change a path color in your vector drawable
VectorChildFinder vector = new VectorChildFinder(this, R.drawable.my_vector, imageView);
VectorDrawableCompat.VFullPath path1 = vector.findPathByName("path1");
path1.setFillColor(Color.RED);
Library is here: https://github.com/devsideal/VectorChildFinder
答案 2 :(得分:5)
您可以使用此方法更改较低API中的颜色以更改片段
中的矢量颜色In [36]: sign != sign.shift()
Out[36]:
0 True
1 False
2 True
3 False
4 False
5 True
6 False
Name: values, dtype: bool
In [37]: (sign != sign.shift()).cumsum()
Out[37]:
0 1
1 1
2 2
3 2
4 2
5 3
6 3
Name: values, dtype: int64
代替getActivity,你应该使用MainActivity.this来改变活动中的矢量颜色
答案 3 :(得分:2)
您可以在运行时更改单个路径的颜色,而不使用反射。
VectorMaster引入了对矢量绘图的动态控制。可以使用此库动态控制矢量drawable的每个方面(通过Java实例)。
只需在应用的build.gradle
中添加以下依赖项dependencies {
compile 'com.sdsmdg.harjot:vectormaster:1.0.9'
}
在您的情况下,您需要一个简单的颜色更改:
矢量示例:your_vector.xml
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:name="outline"
android:pathData="M20.84,4..."
android:strokeColor="#5D5D5D"
android:fillColor="#00000000"
android:strokeWidth="2"/>
<强> XML 强>:
<com.sdsmdg.harjot.vectormaster.VectorMasterView
android:id="@+id/your_vector"
android:layout_width="150dp"
android:layout_height="150dp"
app:vector_src="@drawable/your_drawable" />
<强>爪哇强>:
VectorMasterView heartVector = (VectorMasterView)
findViewById(R.id.your_drawable);
// find the correct path using name
PathModel outline = heartVector.getPathModelByName("outline");
// set the stroke color
outline.setStrokeColor(Color.parseColor("#ED4337"));
// set the fill color (if fill color is not set or is TRANSPARENT, then no fill is drawn)
outline.setFillColor(Color.parseColor("#ED4337"));
来自:https://github.com/harjot-oberai/VectorMaster,在麻省理工学院获得许可。
您现在可以完全控制矢量绘图。
答案 4 :(得分:2)
有几种方法可以做同样的事情,但这适用于 Vector Drawables 以及 SVG (本地/网络)。
imageView.setColorFilter(ContextCompat.getColor(context,
R.color.headPink), android.graphics.PorterDuff.Mode.SRC_IN);
(使用您选择的颜色更改R.color.headPink)
答案 5 :(得分:1)
在另一个问题上查看我的答案:https://stackoverflow.com/a/38418049/1335438。
如何通过使用主题和参数化路径来管理它是个好主意,以便能够动态设置它们。
答案 6 :(得分:0)
正如@Eyal在这篇文章中所述 https://stackoverflow.com/a/32007436/4969047
您无法在运行时更改单个路径的颜色。
查看VectorDrawableCompat
的源代码,通过名称公开内部元素的唯一方法是getTargetByName
,它存在于内部私有状态类VectorDrawableCompatState
中{ {1}}。
由于它是一个包私有(默认) - 你不能使用它(除非你使用reflection)。
答案 7 :(得分:0)
您可以在没有库的情况下实现此目的,并将数据绑定与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)
}
}
}
您可以直接使用 setCompoundDrawablesWithIntrinsicBounds 或 setCompoundDrawables(),但是您必须定义当前的固有边界,请查看本文here
my_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:drawable="http://schemas.android.com/apk/res-auto">
<data>
<import type="your.package.R"/>
<variable
name="actionListener"
type="your.package.mvvmV2.account.profile.ProfileActionListener"/>
<variable
name="profileResponse"
type="your.package.data.model.ProfileResponse"/>
<variable
name="viewModel"
type="your.package.mvvmV2.home.HomeViewModel"/>
</data>
<Button
drawable:color="@{R.color.white}"
drawable:start="@{R.drawable.ic_person_blue}"
android:id="@+id/buttonProfile"
</layout>
对于设置点击侦听器,您也可以执行以下操作:
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<Int, Boolean>()
init {
clickState[R.drawable.ic_aktivitas_blue] = false
clickState[R.drawable.ic_person_blue] = false
clickState[R.drawable.ic_bookmark_blue] = false
}
使用整数资源定义绑定适配器,而不使用 @ color /或@drawable 。如果您希望在XML上使用@注释(例如:drawable:start="@{@drawable/id}"
)。
像这样更改数据绑定
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
}
此外,别忘了通过@aminography设置this
使用Android Vector Drawable的重要要点 如果您使用的是可绘制的android向量,并且希望对21以下的API具有向后兼容性,请将以下代码添加到
在应用程序级别build.gradle:
android {
defaultConfig {
vectorDrawables.useSupportLibrary = true
}
}
在应用程序类中:
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
}
}
感谢answer here,@Varun here explained any other alternative这是我的案例here的原始答案
答案 8 :(得分:0)
DrawableCompat.setTint(imageView.getDrawable(),ContextCompat.getColor(getApplicationContext(),R.color.colorAccent));