如何在Android drawable中传递参数

问题描述

如何在android drawable中传递参数。

如何实现下面提到的代码

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape android:shape="rectangle">
            <solid android:color="{colorcode}" />
            <stroke android:width="1sp" android:color="{colorcode}" />
            <corners android:radius="15dp" />
        </shape>
    </item>
</selector>

,然后从XML文件中获取此可绘制的参数传递值。像

<TextView
    android:layout_width="wrap_content"
    android:layout_height="50dp"
    android:layout_marginRight="5dp"
    android:layout_weight="1"
    android:background="@drawable/rounded,{colorCode}"
    android:gravity="center"/>

解决方法

您可以使用data binding和BindingAdapter来完成。我将展示一个使用Kotlin的示例。

  1. 要启用数据绑定,请添加到您的Gradle:
apply plugin: 'kotlin-kapt' // only need when You use Kotlin

...
android {  
    ...
    buildFeatures {
        dataBinding = true
    }
    ...
}
  1. Crete BindingAdapter(我将其添加到MainActivity.kt中以简化代码):
import android.graphics.drawable.GradientDrawable
import android.os.Bundle
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.databinding.BindingAdapter
import androidx.databinding.DataBindingUtil
import com.myniprojects.teststackjava.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity()
{
    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?)
    {
        super.onCreate(savedInstanceState)

        binding = DataBindingUtil.setContentView(
                this,R.layout.activity_main)
    }
}

// Here is binding adapter. It takes 2 colors,background and stroke. If You want more customization add more parameters 
@BindingAdapter(value = ["colorStoke","colorBack"],requireAll = true)
fun setBackground(textView: TextView,@ColorRes colorStoke: Int,@ColorRes colorBack: Int)
{
    val stroke = ContextCompat.getColor(textView.context,colorStoke)
    val back = ContextCompat.getColor(textView.context,colorBack)

    val gd = GradientDrawable()

    // setting background
    gd.colors = intArrayOf(
            back,back
    )

    // here change parameters as You want
    gd.gradientType = GradientDrawable.LINEAR_GRADIENT

    gd.shape = GradientDrawable.RECTANGLE
    gd.cornerRadius = 15f;
    
    // setting stroke width and color 
    gd.setStroke(5,stroke)

    textView.background = gd
}

要自定义GradeintDrawable检查this docs

  1. 在您的MainActivity.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:tools="http://schemas.android.com/tools">

    <data>

        <import type="com.myniprojects.teststackjava.R" />
    </data>

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

        <TextView
            android:id="@+id/txtVTest"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_margin="20dp"
            android:gravity="center"
            android:text="TextView Text"
            android:textSize="40sp"
            app:colorBack="@{R.color.color_back}"
            app:colorStoke="@{R.color.color_stroke}"/>

    </FrameLayout>
</layout>

我正在导入R,以便能够传递资源。 (也许还有另一种不导入的方法,但是我无法像@{@color/name}那样传递颜色,所以我只导入了它)。在您的TextView中,您必须使用要设置为笔划和后退的颜色调用app:colorBackapp:colorStoke

  1. 当然是res / values / colors:
<color name="color_stroke">#B71C1C</color>
<color name="color_back">#33691E</color>
  1. 最终效果表明一切正常:

enter image description here


要生成ActivityMainBinding,首先必须创建一个数据绑定布局。如果您正确添加了依赖性以快速将布局转换为数据绑定布局,请使用:Alt + EnterConvert to data binding layout *

enter image description here

所以您的布局应如下所示:

<?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:tools="http://schemas.android.com/tools">

    <data>

    </data>

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

    </FrameLayout>
</layout>

现在,在重建项目之后,您应该获得ActivityMainBinding类。

,

ShapeDrawableGradientDrawableColorDrawableDrawable的直接子类。您可以将可绘制对象显式转换为上述任何子类,以调用方法/属性访问,例如setColor(int).paint,如下所示:

val drawable: Drawable = (yourDrawable as StateListDrawable).getStateDrawable(0)
when (drawable) {
    is ShapeDrawable -> {
        (drawable as ShapeDrawable).paint.color = ContextCompat.getColor(mContext,R.color.colorToSet)
    }
    is GradientDrawable -> {
        (drawable as GradientDrawable).setColor(ContextCompat.getColor(mContext,R.color.colorToSet))
        (drawable as GradientDrawable).cornerRadius = 2.0F
    }
    is ColorDrawable -> {
        (drawable as ColorDrawable).color = ContextCompat.getColor(mContext,R.color.colorToSet)
    }
}

需要注意的地方:

您可以在此drawable上使用mutate(),因为它返回具有复制的常量drawable状态的同一drawable实例。 mutate()方法不会与其他任何可绘制对象共享其状态,因此如果要保持可绘制对象原样然后在许多地方将其与不同状态一起使用,这将非常有用。 Here's是如何在可绘制和保存状态下使用mutate的绝佳答案。

此外,如您在注释中所述,也要更改可绘制半径,请使用cornerRadii,它根据给定嵌入链接中的文档,返回4个角中每个角的半径。对于每个角,数组包含2个值[X_radius,Y_radius]。角的顺序为top-lefttop-rightbottom-rightbottom-left

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...