我已经使用这个站点实现了自定义搜索栏首选项 - seekbar preference它工作得很好。现在我想从 string.xml
向搜索栏的自定义属性添加值文件而不是硬编码它们:
而不是写 customseekbar:unitsRight="Seconds"
我想要一个像 <string name="units">Seconds</string>
这样的字符串资源并像这样使用它:customseekbar:unitsRight="@string/units"
.我试图实现这个 guide .我的相关代码是:
属性.xml
<resources>
<declare-styleable name="CustomSeekBarPreference">
<attr name="unitsRight" format="reference|string"/>
</declare-styleable>
和构造函数-
CustomSeekBarPreference.java
public class CustomSeekBarPreference extends Preference implements SeekBar.OnSeekBarChangeListener {
private static final String APPLICATIONNS="http://CustomSeekBarPreference.com";
public CustomSeekBarPreference(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(
attrs, R.styleable.CustomSeekBarPreference, 0 ,0);
mUnitsRight = a.getString(R.styleable.CustomSeekBarPreference_unitsRight);
a.recycle();
}
和布局 -
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:customseekbar="http://CustomSeekBarPreference.com" >
<com.x.sharedpreferencestestapp.CustomSeekBarPreference
android:key="1"
android:defaultValue="30"
android:max="100"
customseekbar:min="0"
android:title="Default step"
customseekbar:unitsRight="@string/units"/>
</PreferenceScreen>
但如您所见,我得到的是“null”而不是正确的值:
即使我将值更改为固定字符串而不是字符串资源,如 customseekbar:unitsRight="Seconds"
我仍然得到相同的结果。只是为了说清楚 - 如果我坚持搜索栏首选项的原始代码:mUnitsRight = getAttributeStringValue(attrs, APPLICATIONNS, "unitsRight", "defaultValue")
它有效,但不适用于字符串资源。
最佳答案
由于您在布局 XML 中为其声明的命名空间,您将获得该属性值的 null - http://CustomSeekBarPreference.com
。
据我所知,obtainStyledAttributes()
方法只能提取标准 Android 资源命名空间中的属性 – http://schemas.android.com/apk/res/android
– 或您应用的资源命名空间,即 http://schemas.android.com/apk/res/
加上应用的包名称。任何其他命名空间中的属性都将被忽略,并且不会出现在返回的 TypedArray
中,这就是为什么无论值是硬编码字符串还是资源引用都会得到 null 的原因。
在您所关注的示例中,他们使用了类似的非标准命名空间,但他们直接从 AttributeSet
中提取值,并在 getAttributeValue 中指定该命名空间()
调用。我不能说我见过这种经常以这种方式使用的特定方法,我能看到的唯一好处是它使您不必定义自己的自定义属性,这是一项相当微不足道的任务。
有几种方法可以解决这个问题。
将这些布局属性移动到您应用的命名空间中,并为每个属性定义一个
attr
资源。这是您链接的开发人员页面中演示的方法,可能是实现自定义
View
属性的最常见和最熟悉的方法。首先将布局中的命名空间声明改为:
xmlns:customseekbar="http://schemas.android.com/apk/res-auto"
(如前所述,
res-auto
段很方便,可以使实际命名空间名称与当前包名称适本地构造。)使用您发布的设置,这将导致
customseekbar:min
出错,因为您没有将min
定义为属性资源 (attr
) 在你的应用程序中。您可以简单地定义attr
,然后像处理unitsRight
一样处理它;即,从obtainStyledAttributes()
返回的TypedArray
中检索它的值。您可以对可能需要的任何其他自定义属性执行相同的操作。
修改
CustomSeekBarPreference
示例中的getAttributeStringValue()
方法以处理资源引用。就修改给定示例而言,这可能是更简单的选项,但直接访问
AttributeSet
值会阻止这些值针对您可能希望应用的任何主题或样式进行调整。如果这不是问题,那么必要的更改就相当简单。在修改后的方法中,我们只需要首先使用
AttributeSet#getAttributeResourceValue()
检查属性值是否为资源值。如果该方法返回有效标识符,我们将使用Resources#getString()
检索实际值。如果不是,我们将属性值视为纯字符串。private String getAttributeStringValue(AttributeSet attrs, String namespace, String name, String defaultValue) { String value = null; int resId = attrs.getAttributeResourceValue(namespace, name, 0); if (resId == 0) { value = attrs.getAttributeValue(namespace, name); if (value == null) value = defaultValue; } else { value = getContext().getResources().getString(resId); } return value; }
使用此方法,您无需定义自定义属性,并且布局命名空间可以保留在发布的代码段中。
关于java - Android:如何在自定义首选项的属性中使用 xml 文件中的字符串资源?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46689210/