XML资源中的变量 - 将值从父级传递到子级

14

我正在尝试重复使用基本形状,并使用这些声明性的XML元素来组成我的用户界面。

如何创建可变的Android属性?

但我不想为每个属性值及其排列组合创建单独的XML文件,并在此过程中重复大部分工作。

例如,我希望该形状的使用者能够定义android:radius值?

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <gradient
            android:startColor="#449def"
            android:endColor="#2f6699"
            android:angle="270"/>
    <stroke
            android:width="1dp"
            android:color="#2f6699"/>
    <corners
            android:radius="3dp"/>
</shape>

如何从XML父元素设置属性?

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" android:drawable="@drawable/shape_box_round_blue_uniform" />
    <!-- How to set the corner radius here? -->
    <item android:drawable="@drawable/shape_box_round_blue" />
</selector>

有什么解决方案吗?

  • 尽可能地不使用任何Java代码 / 避免创建自定义控件/类。
  • 使用维度资源可能是一个有成效的途径?

1
据我所知,在xml父元素中设置属性是不可行的。尺寸资源可能会很方便,例如radius="@dimen/radius_round_blue",并在values/dimensions.xml中定义这个radius_round_blue。如果此属性根据某些值标识符(如语言环境或屏幕大小)而变化,则这可能特别有用。但是,为了完全自由,您应该创建Java类,但这又将增加额外的编码工作(以设置这些可绘制对象和bla)。 - Sherif elKhatib
@SherifelKhatib 我对基于代码的解决方案很感兴趣。例如,一个自定义形状类依赖于项目特定的静态主题类,该类可能定义了非默认属性值,如果存在,则应该由形状类使用?或者是否可以从代码中更改维度资源值? - Cel
3
看起来你正在从"按照安卓方式"做事情中进行任意限制。通过使用一个自定义类并使用attr.xml文件传递参数,这是最简单的方法。这里有一个非常好的例子:https://dev59.com/pm855IYBdhLWcg3wKxDc如果你遵循"安卓方式",你将会在这个环境下拥有更愉悦的编程体验。对我来说,最终理解这一点是很困难的。 - HalR
@HalR 谢谢!这是很棒的东西,您能否确认在这种情况下是否可以创建自定义选择器,并传递自定义属性给选择器,然后通过代码修改其项目?如果选择器无法被定位,那么您是说我应该创建自定义形状并从代码中实例化它们,然后以编程方式使它们成为选择器的一部分吗?我不确定自定义形状自定义属性如何帮助我在这里不重复XML文件.. 无论如何,请将您的评论设置为答案,您可能会获得赏金 :) - Cel
1
似乎这已经接近于使用XAML而不是Android XML的方法了。实际上并没有Expression Blend来创建自定义对象以操纵它们以供Android使用。最接近的解决方案是HaIR提供的,非常酷。Android使用ShapeDrawable从XML文件创建可绘制对象。当形状被定义为矩形时,corners属性才适用。无论如何,都需要一些Java代码。这不是WPF,请查看此处以获取更多信息:http://developer.android.com/guide/topics/resources/drawable-resource.html#Shape。 - Sean
@SherifelKhatib,请将您的评论作为答案发布。 - s.maks
1个回答

4
你可以创建
样式属性
,我认为这就是你要找的。它们基本上是可变属性。例如,你可以在你的themes.xml中使用它们。
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!-- You can define attributes here -->
    <attr name="button_radius" format="reference" />
</resources>

定义了一个名为button_radius的变量引用,可以在样式文件或布局xml文件中使用:

<!-- You can use them like so: -->
<style name="MyApp.Theme1" parent="android:Theme.Holo.Light">
    <item name="button_radius">12</item>
</style>

<style name="MyApp.Theme2" parent="android:Theme.Holo.Light">
    <item name="button_radius">36</item>
</style>

通过更改主题,您可以使用不同的半径值。以下是如何更改形状可绘制对象的未经测试的示例:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <gradient
        android:startColor="#449def"
        android:endColor="#2f6699"
        android:angle="270"/>
    <stroke
        android:width="1dp"
        android:color="#2f6699"/>
    <corners
        android:radius="?button_radius"/> <!-- NOTE the ?button_radius-->
</shape>

用户可以通过应用不同的样式来使用不同的属性。我不知道这个例子是否完全回答了您的问题,但是您可以通过在主题中声明属性来实现很多功能。这些属性是动态引用。有关更多信息和可能性,请参阅此文章


虽然引用属性方法并没有准确回答我的问题——我是想从父选择器中设置变量,而不同的选择器会在同一个项目中设置不同的本地值——但你的方法允许项目特定的全局变量,这已经达到了一半的效果! - Cel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接