【问题标题】:Can't access custom attributes from LayoutInflater无法从 LayoutInflater 访问自定义属性
【发布时间】:2014-02-05 14:19:52
【问题描述】:

我创建了一个子类 LinearLayout 的自定义视图 (AuditQuestionEntry),并且此自定义视图用于我的主要活动 (AuditActivityTEST)。因此,在 AuditActivityTEST 的 onCreate 方法中,setContentview 调用 AuditQuestionEntry 构造函数,我只能通过命名空间访问自定义属性。但是,除非我专门在 AuditQuestionEntry 中扩展视图,否则不会显示该自定义视图。怎么可能调用了构造函数却没有实际显示视图?

要显示视图,我发现我需要使用 AuditQuestionEntry 中的 LayoutInflater。当通过 inflater 调用构造函数时,我根本无法访问属性 - 甚至无法通过命名空间。

这是我的主要活动 - AuditActivityTEST

public class AuditActivityTEST extends BaseWorkbenchActivity {

// Collection of audit questions
AuditQuestionEntry AuditQuestion1;

@Override
public void onCreate(Bundle savedInstanceState) {
    // Set the context in the base class to be used for dialogs and other misc items
    CurrentContext = AuditActivityTEST.this;

    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_audit_test);

    // Set audit questions =====================================================
    AuditQuestion1 = (AuditQuestionEntry) findViewById(R.id.auditQuestionEntry10);
    AuditQuestion1.InitAuditQuestion();

     OnClickListener btnPhotoListener = new OnClickListener() {

        @Override
        public void onClick(final View v) {
            View viewParent = (View) v.getParent();             
            AuditQuestionEntry clickedAudit = (AuditQuestionEntry) viewParent;

            Toast.makeText(CurrentContext, "Audit Question #" + clickedAudit.AuditQuestionNumber, Toast.LENGTH_SHORT).show();
        }

     };

    // ((Button) AuditQuestion1.findViewById(R.id.btnTakeAuditPhoto)).setOnClickListener(btnPhotoListener);
}    
}

这是主要活动的相关布局文件 - activity_audit_test.xml

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:workbench="http://schemas.android.com/apk/com.example.viewtestapp"
    android:id="@+id/scrollView111"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="30dp"
    tools:context=".AuditActivityTEST" >

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical" >

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center_vertical|center_horizontal"
        android:paddingBottom="15dp"
        android:paddingTop="10dp"
        android:text="Current Closet Audit"
        android:textSize="24sp"
        android:textStyle="bold" />

    <com.example.viewtestapp.AuditQuestionEntry
        android:id="@+id/auditQuestionEntry10"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        workbench:AuditQuestionNumber="100"
        workbench:extraInformation="My extra information" >
    </com.example.viewtestapp.AuditQuestionEntry>

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="10dp"
        android:layout_marginTop="30dp"
        android:orientation="horizontal" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginRight="10dp"
            android:text="Finished Audit? Click the following button to submit..."
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:textStyle="bold" />
    </LinearLayout>
</LinearLayout>
</ScrollView>

这是自定义视图 - AuditQuestionEntry.java

public class AuditQuestionEntry extends LinearLayout {

// misc parameters removed for brevity

public AuditQuestionEntry(Context context) {
    super(context);
    // InflateView();

    throw new RuntimeException("Missing AuditQuestionNumber");
}

public AuditQuestionEntry(Context context, AttributeSet attrs) {
    super(context, attrs);

    this._ctx = context;

    initAttributes(attrs);
}

// Used to grab the AuditQuestionNumber attribute from the XML declaration
private void initAttributes(AttributeSet attrs) {
TypedArray a =getContext().obtainStyledAttributes(attrs,R.styleable.AuditQuestionEntry);

    //AuditQuestionNumber = attrs.getAttributeIntValue("http://schemas.android.com/apk/com.example.viewtestapp","AuditQuestionNumber", 0);
    AuditQuestionNumber = a.getInteger(R.styleable.AuditQuestionEntry_AuditQuestionNumber, -1);

    // Don't forget this
    a.recycle();
}

public void InitAuditQuestion() {

    InflateView();
}

public void InflateView() {
    // Setup the infalter
    LayoutInflater layoutInflater;

    layoutInflater = (LayoutInflater) getContext().getSystemService(
            Context.LAYOUT_INFLATER_SERVICE);

    // Inflate the resource in the context of this view and automatically attach
    layoutInflater.inflate(R.layout.audit_question_entry, this);
}
}

最后,这是 attrs.xml

<resources>
    <declare-styleable name="AuditQuestionEntry">
        <attr name="AuditQuestionNumber" format="integer" />
    </declare-styleable>
</resources>

总之,我的问题是:

  1. 如果 setContentView 调用 AuditQuestionEntry 构造函数,为什么自定义视图不显示,我是否需要通过 LayoutInflater 进行充气?
  2. 为什么自定义属性不能通过 gainStyledAttributes 获得,而是通过命名空间方法获得?

我知道这很多,但我想确保我解释并包含了所有内容。

【问题讨论】:

  • 您需要将自定义视图中的属性设置为变量,例如 int AuditQuestionNumber,直到您可以从布局和代码中访问它

标签: android android-layout android-custom-view


【解决方案1】:
// try this way
public class AuditQuestionEntry extends LinearLayout {
    public int AuditQuestionNumber;
    public AuditQuestionEntry(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(attrs);
    }

    public AuditQuestionEntry(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(attrs);
    }

    public AuditQuestionEntry(Context context) {
        super(context);
        init(null);
    }

    private void init(AttributeSet attrs) {
        String namespace = "http://schemas.android.com/apk/" + getContext().getPackageName();
        AuditQuestionNumber = attrs.getAttributeIntValue(namespace, "AuditQuestionNumber", -1);
        View view = LayoutInflater.from(getContext()).inflate(R.layout.audit_question_entry, null, false);
        addView(view);
    }

}

【讨论】:

  • 谢谢,Haresh,但现在我遇到了运行时错误。 InflateException:二进制 XML 文件第 26 行:膨胀类 com.example.viewtestapp.AuditQuestionEntry 时出错。此行在activity_audit_text.xml 文件中引用&lt;com.example.viewtestapp.AuditQuestionEntry - 还有什么想法吗?谢谢!
  • 看起来异常是因为循环问题。 init 方法调用构造函数,而构造函数又再次调用 init - 永无止境的循环。还有什么建议吗?谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-05-03
  • 2016-12-07
  • 1970-01-01
  • 1970-01-01
  • 2011-07-19
  • 1970-01-01
  • 2023-03-20
相关资源
最近更新 更多