【问题标题】:How to pass parameters in Android drawable如何在Android drawable中传递参数
【发布时间】:2020-08-18 16:06:33
【问题描述】:

如何在 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"/>

【问题讨论】:

  • 据我所知,您不能像上述方式从 XML 传递值 - 期待其他任何可能/可以回答这个问题的人(如果有的话)。但是,您可以以编程方式将值/传递参数设置为 android drawable,例如按照问题中的要求更改形状内部的纯色。这会解决/帮助你想要完成的事情吗?
  • 我们如何以编程方式将参数传递给 android drawable ?我想同时实现 1. 更改半径和 2, 更改纯色。
  • 发布了答案。请检查并告诉我是否有帮助。
  • 有没有办法在样式标签的帮助下改变半径?喜欢:&lt;style name="RoundedCorner" parent="android:Theme"&gt; &lt;item name="android:shape"&gt;rectangle&lt;/item&gt; &lt;item name="android:radius"&gt;15dp&lt;/item&gt; &lt;/style&gt;
  • 请检查我的回答,如果你明确地将你的可绘制对象投射到GradientDrawable,你会得到大量的半径属性(cornerRadius、cornerRadii 等)。编辑了答案并添加了一对。

标签: android android-studio android-drawable


【解决方案1】:

您可以使用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. 最终效果表明一切正常:


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

所以你的布局应该是这样的:

<?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类。

【讨论】:

  • 如果我想在所有片段中使用我必须在每个片段中重复 2 和 3 步?
  • 不,您只需创建一个 BindingAdapter,然后您就可以在任何地方使用它。所以在第二个片段中你只需创建TextView 并添加app:colorBack="@{R.color.some_color}"app:colorStoke="@{R.color.another_color}"。就是这样
  • class databinding.ActivityMainBinding 不会自行生成我必须为此做的任何事情
  • @AnupamSomani 第一个选项 - 您没有正确添加依赖项。完成后,重建您的项目。第二 - 您的主要活动根元素不是布局。为此,只需单击 alt + enter,您将看到“转换为数据绑定布局”选项。完成后你应该看到绑定类
  • @AnupamSomani 我已经编辑了我的答案以更好地解释如何生成ActivityMainBinding
【解决方案2】:

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)
    }
}

注意事项:

您可以在此可绘制对象上使用mutate(),因为它返回具有复制的恒定可绘制状态的可绘制对象的相同实例。 mutate() 方法不与任何其他可绘制对象共享其状态,因此如果您想保持可绘制对象原样然后在许多地方以不同的状态使用它,这将非常有帮助。 Here's 是关于如何在可绘制和保存状态上使用 mutate 的一个很好的答案。

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

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-14
  • 1970-01-01
  • 2015-08-19
  • 1970-01-01
  • 2023-03-08
相关资源
最近更新 更多