FindViewByID возвращает null

Прежде всего: да, я прочитал все другие темы по этой теме. И не только из этого сайта … (видите ли, я немного расстроен)

Большинство из них приходят с советами по использованию android:id вместо простого id в XML-файле. Я сделал.

Из других я узнал, что View.findViewById работает не так, как Activity.findViewById . Я тоже это обработал.

В моем location_layout.xml я использую:

 <FrameLayout .... > <some.package.MyCustomView ... /> <LinearLayout ... > <TextView ... android:id="@+id/txtLat" /> ... </LinearLayout> </FrameLayout> 

В моей деятельности я делаю:

 ... setContentView( R.layout.location_layout ); 

И в моем классе пользовательских представлений:

 ... TextView tv = (TextView) findViewById( R.id.txtLat ); 

null возвращает null . Выполняя это, моя деятельность работает нормально. Возможно, это View.findViewById различиями Activity.findViewById и View.findViewById . Поэтому я сохранил контекст, переданный конструктору вида таможни локально, и попытался:

 ... TextView tv = (TextView) ((Activity) context).findViewById( R.id.txtLat ); 

Который также возвратил null .

Затем я изменил свой пользовательский вид, чтобы расширить ViewGroup вместо этого View и изменил location_layout.xml чтобы TextView был прямым дочерним элементом моего пользовательского представления, так что View.findViewById должен работать так, как предполагалось. Suprise: он ничего не решал.

Так что, черт возьми, я поступаю неправильно?

Буду признателен за любые комментарии.

Solutions Collecting From Web of "FindViewByID возвращает null"

Который возвращает null

Возможно потому, что вы называете это слишком рано. Подождите, пока onFinishInflate() . Вот пример проекта, демонстрирующий пользовательский View доступ к его содержимому.

Возможно, вы вызываете findViewById перед вызовом setContentView ? Если это так, попробуйте вызвать findViewById ПОСЛЕ вызова setContentView

Убедитесь, что у вас нет нескольких версий макета для разных плотностей экрана. Однажды я столкнулся с этой проблемой при добавлении нового идентификатора в существующий макет, но забыл обновить версию hdpi. Если вы забудете обновить все версии файла макета, он будет работать для некоторых плотностей экрана, но не для других.

В моем случае у меня было 2 активности в моем проекте, main.xml и main2.xml . С самого начала main2 был копией main , и все работало хорошо, пока я не добавил новый TextView к main2 , поэтому R.id.textview1 стал доступен для остальных приложений. Затем я попытался получить его по стандартным вызовам:

 TextView tv = (TextView) findViewById( R.id.textview1 ); 

И это всегда было нулевым. Оказалось, что в конструкторе onCreate я main2 экземпляр не main2 , а другой. Я имел:

 setContentView(R.layout.main); 

вместо

 setContentView(R.layout.main2); 

Я заметил это после того, как приехал сюда, на сайт.

Наряду с классическими причинами, упомянутыми в другом месте:

  • Убедитесь, что вы вызвали setContentView() перед findViewById()
  • Убедитесь, что id вы хотите, находится в представлении или макете, который вы setContentView() для setContentView()
  • Убедитесь, что id не случайно дублируется в разных макетах

Есть один, который я нашел для пользовательских представлений в стандартных макетах, что противоречит документации:

Теоретически вы можете создать собственное представление и добавить его в макет ( см. Здесь ). Однако я обнаружил, что в таких ситуациях атрибут id работает для всех представлений в макете, кроме пользовательских. Решение, которое я использую:

  1. Замените каждое настраиваемое представление на FrameLayout с теми же свойствами макета, что и пользовательский вид. Дайте ему соответствующий id , скажем frame_for_custom_view .
  2. В onCreate :

     setContentView(R.layout.my_layout); FrameView fv = findViewById(R.id.frame_for_custom_layout); MyCustomView cv = new MyCustomView(context); fv.addView(cv); 

    Который помещает пользовательский вид в фрейм.

  @Override protected void onStart() { // use findViewById() here instead of in onCreate() } 

FindViewById может быть нулевым, если вы вызываете неправильный суперконструктор в пользовательском представлении. Тег ID является частью attrs, поэтому, если вы игнорируете attrs, вы удаляете ID.

Это было бы неправильно

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

Это верно

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

Ответ для тех, кто использует ExpandableListView, и запускать этот вопрос на основе его названия.

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

В реализациях методов getChildView () и getGroupView () вы можете использовать что-то вроде следующего.

  if (convertView == null) { LayoutInflater inflater = (LayoutInflater) myContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = inflater.inflate(R.layout.child_layout, null); } 

Я нашел это здесь .

Я довольно новичок в Android / Eclipse, по ошибке я добавил материал пользовательского интерфейса в activity_main.xml вместо fragment_main.xml . Мне потребовалось несколько часов, чтобы понять это …

В моем конкретном случае я пытался добавить нижний колонтитул в ListView. Следующий вызов onCreate () возвращал значение null.

 TextView footerView = (TextView) placesListView.findViewById(R.id.footer); 

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

 View footerView = ((LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.footer_view, null, false); 

FWIW, я не вижу, чтобы кто-то решил это так же, как мне было нужно. Никаких жалоб во время компиляции, но я получал нулевое представление во время выполнения и вызывал вещи в правильном порядке. То есть findViewById () после setContentView (). Проблема в том, что мое представление определено в content_main.xml, но в моем activity_main.xml мне не хватало этого одного утверждения:

 <include layout="@layout/content_main" /> 

Когда я добавил это к activity_main.xml, больше нет NullPointer.

В моем случае я использовал ExpandableListView, и я установил android:transcriptMode="normal" . Это привело к тому, что несколько детей в расширяемой группе исчезли, и я использовал исключение NULL, когда я использовал прокрутку списка.

Для меня у меня было два xml-макета для одной и той же активности – один в портретном режиме и один в ландшафте. Конечно, я изменил идентификатор объекта в ландшафте xml, но забыл сделать то же изменение в портретной версии. Убедитесь, что если вы изменили одно, вы сделаете то же самое с другим xml или вы не получите сообщение об ошибке, пока не запустите / отлаживаете его, и он не сможет найти идентификатор, который вы не изменили. О, глупые ошибки, почему ты так меня наказываешь?

Задайте содержимое активности из ресурса макета. Т.е. setContentView(R.layout.basicXml) ;

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

Наконец я понял, что происходит. Eclipse все еще использовал XML-файл раскладки библиотеки для каждой ячейки в GridView, хотя он не дал никаких указаний на это. В моем пользовательском адаптере он указал, что он использует ресурс xml из моего собственного проекта, хотя во время выполнения он не был.

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

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

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

 public class MiniPlayerControllBar extends LinearLayout { //code } 

Вы не можете получить представление в конструкторе. Вы должны вызвать findViewById после того, как просмотр завышен. Их метод, который вы можете переопределить onFinishInflate

В моем случае я раздул макет, но взгляды на ребенка возвращали нуль. Первоначально у меня было это:

 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_history); footerView = ((LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.listview_footer, null, false); pbSpinner = (ProgressBar) findViewById(R.id.pbListviewFooter); tvText = (TextView) findViewById(R.id.tvListviewFooter); ... } 

Однако, когда я изменил его на следующее, он работал:

 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_history); footerView = ((LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.listview_footer, null, false); pbSpinner = (ProgressBar) footerView.findViewById(R.id.pbListviewFooter); tvText = (TextView) footerView.findViewById(R.id.tvListviewFooter); ... } 

Ключ должен был специально ссылаться на уже завышенный макет, чтобы получить вид ребенка. То есть, чтобы добавить footerView :

  • FooterView .findViewById …

По моему опыту, похоже, что это также может произойти, когда ваш код вызывается после OnDestroyView (когда фрагмент находится в фоновом стеке.) Если вы обновляете пользовательский интерфейс на входе от BroadCastReceiver, вы должны проверить, действительно ли это так ,

В дополнение к вышеуказанным решениям вы убедитесь, что
tools:context=".TakeMultipleImages" в макете такое же значение в файле mainfest.xml:
android:name=".TakeMultipleImages" для одного и того же элемента активности. Это происходит при использовании копирования и вставки для создания новой активности

ОГРАНИЧИВАЙТЕ СРОК! (Который содержит идентификатор)

В моем случае findViewById () возвратил null, потому что макет, в котором был написан элемент, не был завышен …

Например. fragment_layout.xml

 <ListView android:id="@+id/listview"> 

FindViewById (R.id.listview) возвратил null, потому что я не делал inflater.inflate (R.layout.fragment_layout, …, …); перед этим.

Надеюсь, этот ответ поможет некоторым вам.

Мое решение состояло в том, чтобы просто очистить проект.

Просто хотел бросить здесь свой конкретный случай. Может помочь кому-то спуститься по линии.

Я использовал эту директиву в своем Android-интерфейсе Android следующим образом:

Родительский взгляд:

 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:tag="home_phone" android:background="@color/colorPrimary"> ... <include layout="@layout/retry_button" android:visibility="gone" /> 

Детский вид (retry_button):

 <com.foo.RetryButton xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/retry" android:layout_gravity="center" android:orientation="vertical" android:layout_width="100dp" android:layout_height="140dp"> 

.findViewById (R.id.retry) всегда возвращает null. Но, если я переместил идентификатор из дочернего представления в тег include, он начал работать.

Фиксированный родитель:

 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:tag="home_phone" android:background="@color/colorPrimary"> ... <include layout="@layout/retry_button" android:id="@+id/retry" android:visibility="gone" /> 

Исправлено:

 <com.foo.RetryButton xmlns:android="http://schemas.android.com/apk/res/android" android:layout_gravity="center" android:orientation="vertical" android:layout_width="100dp" android:layout_height="140dp"> 

FindViewById также может возвращать значение null, если вы находитесь внутри фрагмента. Как описано здесь: findViewById in Fragment

Вы должны вызвать getView () для возврата верхнего уровня в фрагмент. Затем вы можете найти элементы макета (кнопки, текстовые изображения и т. Д.),