findViewById (int) возвращает null для пользовательских представлений, но не для встроенных модулей Android - PullRequest
4 голосов
/ 18 октября 2011

Ситуация: У меня есть несколько пользовательских компонентов в моем макете. У меня есть общий фрейм макета, который я загружаю в onCreate() моего базового класса Activity, а затем загружаю макеты содержимого в моих реализациях с помощью инфлатера, устанавливая корень для столбца содержимого основного макета.

Проблема: Когда я беру ссылку на представления, чтобы фактически извлечь ввод пользователя, Activity.findViewById() возвращает null. Возможно, это подсказка, что CheckBox и Button, которые есть в макете, НЕ возвращают null; Я получаю действительную ссылку на виджет.

Вещи, которые я пробовал: Я знаю, что я правильно загружаю и раздуваю макет xml, потому что все отображается, и стандартные представления в том же макете можно найти по идентификатору. Я могу взаимодействовать со своими представлениями и помещать в них содержимое и все, но я не могу получить ссылку на них в своем коде.

Я пытался очистить проект несколько раз. R.id свежо и актуально.

Я проверил консоль и журнал ошибок, и нет сообщений об ошибках интерфейса / 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

Идентификатор, присвоенный представлению, не совпадает с идентификатором в R.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 ]

13 голосов
/ 15 августа 2012

У меня была похожая проблема, и моим решением было убедиться, что конструктор пользовательского виджета вызывает

super(context, attrs); 

Мой конструктор не передал атрибуты super, поэтому идентификатор представления был испорчен, а findviewbyId возвратил ноль.

1 голос
/ 20 октября 2011

Да ... Я идиот.Конечно, в представлении был задан правильный идентификатор, а затем один из моих методов инициализации вернулся и забил его.

1 голос
/ 19 октября 2011

Очень трудно найти проблему без реальных источников.Я создал пример проекта на основе ваших постов и он полностью работает.Я считаю, что есть очень простая ошибка, и вы ее найдете.Если хотите, можете попробовать

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...