Вопрос по android – findViewById не работает для включения?

38

У меня есть, как включить:

<include
    android:id="@+id/placeHolder"
    layout="@layout/test" />

Макет включения выглядит следующим образом (test.xml):

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

<FrameLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/outer"
    ... >

    <ImageView
        android:id="@+id/inner"
        ... />
</FrameLayout>

Кажется, я не могу найти внутренний ImageView с id = & quot; внутренним & quot; во время выполнения:

ImageView iv = (ImageView)findViewById(R.id.inner);
if (iv == null) {
    Log.e(TAG, "Not found!");
}

Должен ли я быть в состоянии найти это? Похоже, что поскольку он использует «include», обычный метод findViewById не работает.

---------- Обновить ----------------

Так что я могу найти идентификатор, назначенный для включения:

View view = findViewById(R.id.placeHolder); // ok

но я не могу найти ни одного из его детей по id, например:

view.findViewById(R.id.outer); // nope
view.findViewById(R.id.inner); // nope

так же, как оригинал, если я пытаюсь искать их напрямую, как:

findViewById(R.id.outer); // nope
findViewById(R.id.inner); // nope

Идентификаторы просто удаляются из элементов во время выполнения, может быть?

Спасибо

любая ошибка, если да, то пост logcat Samir Mangroliya
Была такая же проблема. В конце я неправильно ссылался на свои взгляды внутри включенного макета. Я включил один из ресурсов макета, который поставляется с SDK и поэтому должен был использоватьandorid.R.id. в отличие отR.id. в моемfindViewById(), Решение dymmeh работало нормально, как только я это исправил. jhavatar
Извините, "test.xml", опечатка, спасибо. user291701

Ваш Ответ

6   ответов
0

У меня такая же проблема. Я обнаружил, что использовал неправильную функцию с тем же именем и двумя параметрами:

public void onCreate(@Nullable Bundle savedInstanceState, @Nullable PersistableBundle persistentState) {
    super.onCreate(savedInstanceState, persisten,tState);
    setContentView(R.layout.activity_ble_connecting);
    //findViewByid() => wrong
} 

correct функция только с одним параметром:

    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_ble_connecting);
        //findViewByid() => correct
    }
0

Можете ли вы попытаться найти внешнего родителя (давайте назовем его «op»), а затем попробовать op.findViewById ()?

Эй, да, тоже не работает, обновил вопрос с ним. user291701
0

Будущие исследователи:https://stackoverflow.com/a/1760010/2790016 когда вы добавляете в него идентификатор, он перезаписывает идентификатор из внешнего тега из «реального макета»;

Учитывая, что большинству макетов ограничений нужен идентификатор для позиционирования элементов, удаление идентификатора из include не является идеальным ответом.

0

Если вы дали идентификаторinclude элемент, и у вас есть только один вид во включенном макете (не в любомViewGroup), в моем случаеAdViewзатем используйте идентификаторinclude элемент вместо включенного представления.

<?xml version="1.0" encoding="utf-8"?>
<!--adview.xml-->
<com.google.android.gms.ads.AdView
        xmlns:ads="http://schemas.android.com/apk/res-auto"
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/adView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_alignParentBottom="true"
        ads:adSize="BANNER"
        ads:adUnitId="@string/admob_banner_id">
</com.google.android.gms.ads.AdView>

activity_main.xml

<include
        layout="@layout/adview"
        android:id="@+id/adsLayout"
  />

В деятельности

AdView nullAdView=findViewById(R.id.adView); //this will give null
AdView adView = findViewById(R.id.adsLayout);  //this will be AdView

Если вы не дадитеid вinclude элемент тогда можно использовать видid, Также если вашview внутри любогоViewGroup лайкFrameLayout тогда можно использовать видid.

63

Попробуйте получить<include /> а затем искать в этом

Убедитесь, что ваш корень имеет тот же идентификатор, что и корневой элемент во включенном XML-файле.

<include
    android:id="@+id/outer"
    layout="@layout/test" />

Затем извлеките свой & quot; внутренний & quot; использование контента:

FrameLayout outer = (FrameLayout)findViewById(R.id.outer);

ImageView iv = (ImageView)outer.findViewById(R.id.inner);
if (iv == null) {
    Log.e(TAG, "Not found!");
}
Попробуйте мой обновленный ответ. Убедитесь, что ваш идентификатор для включения совпадает с корневым элементом во включенном XML-файле.
Я просто хочу указать на важность того, чтобы убедиться, что идентификатор включения совпадает с идентификатором корневого элемента во включенном XML-файле. Точно так же, как @dymmeh сказал. Когда я впервые прочитал ответ, я полностью пропустил предложение, и ДЕЙСТВИТЕЛЬНО важно принять его во внимание. Большое спасибо за помощь!
Бум спасибо, что работает! user291701
Эй, да, тоже не работает, обновил вопрос с ним. user291701
Если идентификатор включения совпадает с внутренним корневым элементом, то нет смысла переопределять его, он будет раздуваться как есть. Согласно источнику LayoutInflater, он не будет переопределять идентификатор корневого элемента слияния, что делает его бесполезным для повторного использования макетов, которые могут совместно использовать идентификаторы и позволять им переопределяться при включении.
11

Я просто хотел добавить к этому для будущих Googlers, у меня была своего рода противоположная проблема, когда корневой макет включенного xml (в данном случае external) был нулевым при вызове findViewById (), но дочерние элементы external не были нулевыми.

Проблема была решена для меня путем удаления свойства id изinclude & APOS; вид & APOS; (в этом случае placeHolder). Когда этого не было, я мог найти внешнее, но это идентификатор :)

Если вам нужен идентификатор, присвоенныйinclude элемент, я думаю, лучше обернуть его в другую группу просмотра.

Для других googlers вы можете попробовать позвонитьfindViewById вonViewCreated, если вы используете фрагмент :)
Это сработало для меня - спасибо. Я немного покопался и (по крайней мере, в своем не фрагментном коде) обнаружил следующее: если у вас есть включение с идентификатором и вы хотите получить доступ к верхнему уровню включенной структуры, тогда идентификатор включения должен совпадать с идентификатор структуры верхнего уровня включенного элемента. Это кажется неправильным в том смысле, что это, кажется, дублирующееся имя - но это работает. Другой альтернативой, которая также работает, является ваше решение - то есть пропустить название на включаемом.
Для будущих читателей<include/> id переопределит идентификатор дочернего макета, он все равно будет работать, если выfindViewById с этим<include/> id вместо идентификатора дочернего макета, иначе будет null. Альтернативный способ - это то, что предложил этот ответ, то есть удалить<include/> id и остается только дочерним макетом id. И не забудьте изменить другие вещи, такие какlayout_above которые относятся к этому<include> ID, если вы добавили.

Похожие вопросы