findViewByID возвращает null
Прежде всего: да, я прочитал все другие темы по этой теме. И не только из этого сайта … (видите ли, я немного расстроен)
Большинство из них приходят с советами по использованию android:id
вместо простого id
в XML-файле. Я сделал.
Из других я узнал, что View.findViewById
работает иначе, чем Activity.findViewById
. Я тоже это обработал.
- мы можем получить хромированную историю просмотров / закладки в нашем приложении для Android
- Класс BaseAdapter не будет устанавливать адаптер внутри Asynctask - Android
- Проверьте, присутствует ли SDCard, логическое значение всегда верно
- Получить кликнутый элемент и его позицию в RecyclerView
- Обновите приложение для Android (без Google Play)
В моем location_layout.xml
я использую:
...
В моей деятельности я делаю:
... setContentView( R.layout.location_layout );
и в моем classе пользовательских представлений:
... TextView tv = (TextView) findViewById( R.id.txtLat );
который возвращает 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: он ничего не решал.
Так что, черт возьми, я поступаю неправильно?
Буду признателен за любые комментарии.
- как блокировать виртуальную клавиатуру при нажатии на edittext в android?
- Как просмотреть файл общих настроек с помощью Android Studio?
- Дооснащение и OkHttpClient, тайм-аут соединения catch в методе сбоя
- Как проверить активность на переднем плане или на видимом фоне?
- Подавлять / Блокировать BroadcastReceiver в другом приложении
- Как рассчитать расстояние между двумя точками, используя их долготу и значение широты
- Android Studio - НЕОПРЕДЕЛЕННЫЙ ТОП-УРОВЕННЫЙ ИСКЛЮЧИТЕЛЬ:
- Вручную добавление aar с зависимым файлом pom / iml
который возвращает 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);
Я заметил это после того, как приехал сюда, на сайт.
Наряду с classическими причинами, упомянутыми в другом месте:
- Убедитесь, что вы вызвали
setContentView()
передfindViewById()
- Убедитесь, что
id
вы хотите, находится в представлении или макете, который выsetContentView()
дляsetContentView()
- Убедитесь, что
id
не случайно дублируется в разных макетах
Есть один, который я нашел для пользовательских представлений в стандартных макетах, что противоречит документации:
Теоретически вы можете создать собственное представление и добавить его в макет ( см. Здесь ). Однако я обнаружил, что в таких ситуациях атрибут id
работает для всех представлений в макете, кроме пользовательских. Решение, которое я использую:
- Замените каждое пользовательское представление на
FrameLayout
с теми же свойствами макета, что и пользовательский вид. Дайте ему соответствующийid
, скажемframe_for_custom_view
. -
В
onCreate
:setContentView(R.layout.my_layout); FrameView fv = findViewById(R.id.frame_for_custom_layout); MyCustomView cv = new MyCustomView(context); fv.addView(cv);
который помещает пользовательский вид в фрейм.
FindViewById может быть пустым, если вы вызываете неправильный супер-конструктор в пользовательском представлении. Тег ID является частью attrs, поэтому, если вы игнорируете attrs, вы удаляете ID.
Это было бы неправильно
public CameraSurfaceView(Context context, AttributeSet attrs) { super(context); }
Это верно
public CameraSurfaceView(Context context, AttributeSet attrs) { super(context,attrs); }
@Override protected void onStart() { // use findViewById() here instead of in onCreate() }
Ответ для тех, кто использует 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
. Мне потребовалось несколько часов, чтобы понять это …
FWIW, я не вижу, чтобы кто-то решил это так же, как мне было нужно. Никаких жалоб во время компиляции, но я получал нулевой вид во время выполнения и вызывал вещи в правильном порядке. То есть findViewById () после setContentView (). Проблема в том, что мое представление определено в content_main.xml, но в моем activity_main.xml мне не хватало этого одного утверждения:
Когда я добавил, что для activity_main.xml, больше нет NullPointer.
В моем конкретном случае я пытался добавить нижний колонтитул в ListView. Следующий вызов в onCreate () возвращал значение null.
TextView footerView = (TextView) placesListView.findViewById(R.id.footer);
Изменение этого, чтобы раздуть нижний колонтитул вместо того, чтобы найти его по ID, решило эту проблему.
View footerView = ((LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.footer_view, null, false);
Мое дело не похоже на выше, никаких решений не было. Я предполагаю, что мой взгляд был слишком глубоким в иерархии компоновки. Я переместил его на один уровень и больше не был нулевым.
В моем случае я использовал ExpandableListView, и я установил android:transcriptMode="normal"
. Это привело к тому, что несколько детей в расширяемой группе исчезли, и я использовал исключение NULL, когда я использовал прокрутку списка.
Для меня у меня было два xml-макета для одного и того же действия – один в портретном режиме и один в ландшафте. Конечно, я изменил идентификатор объекта в ландшафтном xml, но забыл сделать такое же изменение в портретной версии. Убедитесь, что если вы изменили один, вы сделаете то же самое с другим xml, иначе вы не получите сообщение об ошибке, пока не запустите / отлаживаете его, и он не сможет найти идентификатор, который вы не изменили. О, глупые ошибки, почему ты так меня наказываешь?
Задайте содержимое активности из ресурса макета. т.е. setContentView(R.layout.basicXml)
;
У меня была такая же проблема. Я использовал стороннюю библиотеку, которая позволяет переопределить их адаптер для GridView и указать собственный макет для каждой ячейки GridView.
Наконец я понял, что происходит. Eclipse все еще использовал XML-файл макета библиотеки для каждой ячейки в GridView, хотя он не дал никаких указаний на это. В моем пользовательском адаптере он указал, что он использует ресурс xml из моего собственного проекта, хотя во время выполнения он не был.
Так что я сделал, чтобы убедиться, что мои собственные макеты xml и идентификаторы отличаются от тех, которые все еще сидят в библиотеке, очистили проект, а затем начали читать правильные пользовательские макеты, которые были в моем проекте.
Короче говоря, будьте осторожны, если вы переопределите адаптер сторонней библиотеки и указали свой собственный макет xml для использования адаптером. Если ваш макет внутри вашего проекта имеет то же имя файла, что и в библиотеке, вы можете столкнуться с действительно сложной ошибкой!
В дополнение к вышеуказанным решениям вы убедитесь, что
tools:context=".TakeMultipleImages"
в макете такое же значение в файле mainfest.xml:
android:name=".TakeMultipleImages"
для одного и того же элемента активности. это происходит при использовании копирования и вставки для создания новой активности
У меня такая же проблема, но я думаю, что ее стоит поделиться с вами, ребята. Если вам нужно 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 …
Просто хотел бросить здесь свой конкретный случай. Может помочь кому-то спуститься по линии.
Я использовал эту директиву в своем Android-интерфейсе Android следующим образом:
Родительский взгляд:
...
Вид ребенка (retry_button):
.findViewById (R.id.retry) всегда возвращает null. Но если я переместил идентификатор из дочернего представления в тег include, он начал работать.
Фиксированный родитель:
...
Исправлено:
Я пробовал все вышеперечисленное, ничего не работает. Поэтому мне пришлось сделать статическую public static ImageView texture;
а затем texture = (ImageView) findViewById(R.id.texture_back);
, Я не думаю, что это хороший подход, хотя это действительно сработало для моего дела 🙂
По моему опыту, похоже, что это также может произойти, когда ваш код вызывается после OnDestroyView (когда fragment находится в фоновом стеке.) Если вы обновляете пользовательский интерфейс на входе от BroadCastReceiver, вы должны проверить, действительно ли это так ,
ВПЕРЕДИТЬ ПЛАН! (который содержит идентификатор)
В моем случае findViewById () возвратил null, потому что макет, в котором был написан элемент, не был завышен …
Например. fragment_layout.xml
findViewById (R.id.listview) возвратил null, потому что я не делал inflater.inflate (R.layout.fragment_layout, …, …); перед этим.
Надеюсь, этот ответ поможет некоторым из вас.
Мое решение состояло в том, чтобы просто очистить проект.
findViewById также может возвращать значение null, если вы находитесь внутри fragmentа. Как описано здесь: findViewById в fragmentе
Вы должны вызвать getView (), чтобы вернуть вид верхнего уровня внутри fragmentа. Затем вы можете найти элементы макета (кнопки, текстовые изображения и т. Д.),
В моем случае findViewById возвратил null, когда я переместил вызов из родительского объекта в объект-адаптер, созданный родителем. После неудачных попыток трюков я переместил findViewById обратно в родительский объект и передал результат в качестве параметра во время создания объекта адаптера. Например, я сделал это в родительском объекте:
Spinner hdSpinner = (Spinner)view.findViewById(R.id.accountsSpinner);
Затем я передал hdSpinner в качестве параметра во время создания объекта адаптера:
mTransactionAdapter = new TransactionAdapter(getActivity(), R.layout.transactions_list_item, null, from, to, 0, hdSpinner);