【问题标题】:How do you define custom attributes for the LayoutParams class of a custom RecyclerView.LayoutManager implementation?如何为自定义 RecyclerView.LayoutManager 实现的 LayoutParams 类定义自定义属性?
【发布时间】:2017-10-13 20:19:02
【问题描述】:

我知道如何为特定类创建自定义属性。您只需在 Styleable 中使用名称的类名定义它们,就像这样。

<declare-styleable name="MyCustomView">
    <attr name="customAttr1" format="integer" />
    <attr name="customAttr2" format="boolean" />
</declare-styleable>

然后,当我在布局中使用 MyCustomView 的实例时,可以设置 customAttr1customAttr2。很简单。

我现在要做的是在我的自定义RecyclerView 的子级上使用LayoutParams 的自定义属性,或者更准确地说,在提供各个RecyclerView.ViewHolder 子类的布局文件的根视图中我正在使用。但是,我无法获得传递给我的属性,我不知道为什么。

这是我的 attrs.xml 文件...

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="ScrollableGridLayoutManager.LayoutParams">
        <attr name="cellLayoutMode">
            <enum name="scrollable"                 value="0" />
            <enum name="fixedHorizontal"            value="1" />
            <enum name="fixedVertical"              value="2" />
            <enum name="fixedHorizontalAndVertical" value="3" />
        </attr>
    </declare-styleable>

</resources>

这是我的自定义 LayoutParams 类中读取属性的代码...

public LayoutParams(Context context, AttributeSet attrs){

    super(context, attrs);

    TypedArray styledAttrs = context.obtainStyledAttributes(R.styleable.ScrollableGridLayoutManager_LayoutParams);

    if(styledAttrs.hasValue(R.styleable.ScrollableGridLayoutManager_LayoutParams_cellLayoutMode)){
        int layoutModeOrdinal = styledAttrs.getInt(R.styleable.ScrollableGridLayoutManager_LayoutParams_cellLayoutMode, layoutMode.ordinal());
        layoutMode = LayoutMode.values()[layoutModeOrdinal];
    }

    styledAttrs.recycle();
}

这是我在布局中为我的一个 ViewHolders 设置它的地方...

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android = "http://schemas.android.com/apk/res/android"
    xmlns:app     = "http://schemas.android.com/apk/res-auto"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:gravity="start|center_vertical"
    android:background="#0000FF"
    app:cellLayoutMode="fixedVertical">

    <TextView
        android:id="@+id/mainTextView"
        android:textColor="#000000"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#FFFF00"
        android:layout_marginStart="20dp" />

</LinearLayout>

但是,我尝试的任何东西似乎都没有进入“hasValue”调用。它总是像未设置一样返回。

注意:我在定义属性时也尝试了所有这些...

<declare-styleable name="LayoutParams">

<declare-styleable name="ScrollableGridLayoutManager_LayoutParams">

<declare-styleable name="ScrollableGridAdapter_LayoutParams">

...但似乎没有一个工作。

那么我做错了什么?您如何定义特定于您的自定义 LayoutParams 类的属性?

【问题讨论】:

  • 几乎完全相同。 LayoutParams 子类应该有一个构造函数,它接受 ContextAttributeSet,因此您可以像在 View 子类中一样检索这些值。确保在自定义 RecyclerView 中覆盖 generateLayoutParams(AttributeSet) 以返回您的 LayoutParams 子类。另外,虽然你可以使用任何你喜欢的东西,我相信惯例是将_Layout附加到自定义ViewGroupname,用于LayoutParams'&lt;declare-styleable&gt;;例如,name="MyCustomView_Layout".
  • 我刚刚添加了我的代码,正是这样做的。问题是我不确定如何定义属性,因为无论我在布局文件中做什么,我设置的属性反映在传递给的属性中自定义 LayoutParams 构造函数。他们总是报告为未设置。这就是我要克服的问题。 (我感觉我在您回答时发布了该代码,所以您可能没有看到它。)
  • 嗯,我只是用RecyclerView 进行了一个快速而肮脏的测试,以确保我没有忽略任何东西,并且它按预期工作。你究竟是如何夸大项目布局的?您是否在 inflate() 调用中传递父自定义 RecyclerView
  • 哦,等等,我现在看到了。您使用了错误的obtainStyledAttributes() 重载。也就是说,您忘记将AttributeSet 传递给它。应该是context.obtainStyledAttributes(attrs, R.styleable.ScrollableGridLayoutManager_LayoutParams);
  • 呃!!! [捂脸]我觉得自己像个白痴!我怎么没看到?问题虽然......这应该是declare-styleable标签中name属性的正确值......或者它是否重要(即没有错误的答案,它只是一个约定?)

标签: android android-layout android-recyclerview custom-attributes android-custom-attributes


【解决方案1】:

在自定义的LayoutParams 构造函数中,obtainStyledAttributes() 调用必须包含传入的AttributeSet。否则,它只会从Context 的主题中提取值,而那些在布局 XML 中指定的属性值将获胜'不包含在返回的TypedArray中。

例如:

TypedArray styledAttrs =
    context.obtainStyledAttributes(attrs, R.styleable.ScrollableGridLayoutManager_LayoutParams);

【讨论】:

    猜你喜欢
    • 2012-05-05
    • 1970-01-01
    • 2011-11-28
    • 2011-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多