findViewById(int)为自定义视图返回null,但不为Android内置函数返回

时间:2011-10-18 17:30:53

标签: android android-layout android-widget

情况:我的布局中有一些自定义组件。我有一个公共布局框架,我在我的Activity基类的onCreate()中加载,然后使用inflater在我的实现中加载我的内容布局,将根设置为主布局的内容列。

问题:当我获取对视图的引用时,为了实际提取用户的输入,Activity.findViewById()返回null。这可能是一个线索,我在布局中的CheckBox和Button不会返回null;我得到了对小部件的有效引用。

我尝试过的事情:我知道我正在正确加载和扩充布局xml,因为一切都显示出来了,ID可以找到相同布局的标准视图。我可以与我的视图进行交互,并将内容放入它们和所有内容中,但我无法在代码中获得对它们的引用。

我多次尝试清理项目。 R.id是新鲜的,是最新的。

我检查了控制台和错误日志,并且没有报告UI / XML错误。

我尝试获取为此活动加载的内容的根布局的句柄,并调用View.findViewById()来获取我的引用,并返回null。如果我在调试器中检查布局,我可以向下钻取并在mChildren中找到我的视图。

也许是另一条线索:

public VideoChooser(Context pCtxt, AttributeSet pAttrs)
{
    super(pCtxt, pAttrs);
    Log.d("VideoChooser", "Expected ID: " + R.id.vchShareVids + " | actual: " + getId());
}

将产生以下输出:

DEBUG/VideoChooser(10372): Expected ID: 2131296271 | actual: 268435456

分配给视图的ID与R.id中的ID不匹配!那为什么会这样?我知道它正在加载android:id属性,否则它将为-1(View.NO_ID)。

公共布局框架:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:foo="http://schemas.android.com/apk/res/com.foo"
    android:id="@+id/common_frame" android:orientation="vertical"
    android:layout_width="match_parent" android:layout_height="match_parent">

    <!-- top banner -->
    <LinearLayout android:id="@+id/frame_header" android:orientation="horizontal"
        android:layout_height="wrap_content" android:layout_width="match_parent"
        android:layout_marginBottom="16dp">

        <ImageView android:src="@drawable/banner"
            android:layout_width="wrap_content" android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal" android:layout_weight="1" />

    </LinearLayout>

    <!-- content column -->
    <LinearLayout android:id="@+id/frame_content" android:orientation="vertical"
        android:layout_width="match_parent" android:layout_height="wrap_content"
        android:layout_marginLeft="32dp" android:layout_marginRight="32dp" />

</LinearLayout>

内容布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:foo="http://schemas.android.com/apk/res/com.foo"
    android:id="@+id/content_panel" android:orientation="vertical"
    android:layout_width="match_parent" android:layout_height="match_parent">

    <com.foo.view.VideoChooser android:id="@+id/vchShareVids"
        foo:prompt_text="@string/prompt_share_vid" foo:prompt_size="16dp"
        foo:preview_height="80dp"
        android:layout_width="match_parent" android:layout_height="wrap_content"
        android:layout_marginBottom="12dp" android:hapticFeedbackEnabled="true" />
    <com.foo.view.ContactChooser android:id="@+id/cchRecipients"
        foo:prompt_text="@string/prompt_share_email" foo:prompt_size="16dp"
        foo:preview_lines="3" foo:dialog_title="Pretend you are picking contacts"
        android:layout_width="match_parent" android:layout_height="wrap_content"
        android:layout_marginBottom="12dp" android:hapticFeedbackEnabled="true" />
    <com.foo.view.TextChooser android:id="@+id/tchDescription"
        foo:prompt_text="@string/prompt_share_description" foo:prompt_size="16dp"
        foo:preview_lines="1" foo:dialog_title="@string/title_msg_chooser_dlg"
        android:layout_width="match_parent" android:layout_height="wrap_content"
        android:layout_marginBottom="12dp" android:hapticFeedbackEnabled="true" />

    <CheckBox android:id="@+id/chkReshare" android:text="@string/prompt_reshare"
        android:layout_width="wrap_content" android:layout_height="wrap_content"
        android:checked="true" android:hapticFeedbackEnabled="true" />
    <Button android:id="@+id/btnSend" android:text="@string/btn_send"
        android:layout_width="@dimen/btn_width" android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal" android:hapticFeedbackEnabled="true" />

</LinearLayout>

活动基类onCreate():

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.common_frame);
}

活动实施onCreate():

@Override
protected void onCreate(Bundle pState)
{
    super.onCreate(pState);
    load_content_view(R.layout.content_layout);

    ViewGroup tLayout = (ViewGroup)findViewById(R.id.content_panel);

    // These all return null
    mCchVideo = (ContentChooser)tLayout.findViewById(R.id.vchShareVids);
    mCchContact = (ContentChooser)tLayout.findViewById(R.id.cchRecipients);
    mCchDescription = (ContentChooser)tLayout.findViewById(R.id.tchDescription);

    // These return valid references
    mChkReshare = (CheckBox)findViewById(R.id.chkReshare);
    mBtnSend = (Button)findViewById(R.id.btnSend);

    // ...
}

protected void load_content_view(int pResId)
{
    LinearLayout tColumn = (LinearLayout)findViewById(R.id.frame_content);
    getLayoutInflater().inflate(pResId, tColumn);
}

3 个答案:

答案 0 :(得分:13)

我遇到了类似的问题,我的解决方案是确保自定义窗口小部件的构造函数调用

super(context, attrs); 

我的构造函数没有将attrs传递给super,因此视图id被搞砸了,findviewbyId返回null。

答案 1 :(得分:1)

如果没有实际来源,很难找到问题。我已根据您的帖子创建了示例项目,并且已完全正常运行。 我相信有一个非常简单的错误,你会发现它。 如果您愿意,可以try it

答案 2 :(得分:1)

是的......我是个白痴。 View当然是设置正确的ID,然后我的一个init方法返回并破坏了它。

捂脸