java - Android:如何在自定义首选项的属性中使用 xml 文件中的字符串资源?

标签 java android android-preferences

我已经使用这个站点实现了自定义搜索栏首选项 - 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”而不是正确的值:screenshot 即使我将值更改为固定字符串而不是字符串资源,如 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/

相关文章:

android - getDefaultSharedPreferences() 和 getPreferences() 有什么区别?

android - PreferenceActivity 未显示(黑屏)

javascript - HtmlUnit - 无法调用未定义的方法 "replace"

java - Android:如何删除数字选择器中的分隔线

java - Webrtc 部分仅在发布版本上崩溃在调试版本上工作正常

java - Android - 保存动态生成的 TextView

android - 无法通过 ?attr 设置标题首选项图标

java - 如何在ZK中的TreeNode结构中选择树节点?

Java 滚动面板

java - 为什么 javac 在系统重新启动时速度最慢?