. Это гарантирует, что вы все равно сможете следить за кликами на уровне верхнего уровня и совместимы с мобильными устройствами.
blockquote>Это было сделано с учетом настольных компьютеров и мобильных устройств. Попал в оболочку jQuery с условием, который проверяет, превышает ли ширина окна 768px.
jQuery
/** Dropdown on hover */ $(".nav-link.dropdown-toggle").hover( function () { // Open up the dropdown $(this).removeAttr('data-toggle'); // remove the data-toggle attribute so we can click and follow link $(this).parent().addClass('show'); // add the class show to the li parent $(this).next().addClass('show'); // add the class show to the dropdown div sibling }, function () { // on mouseout check to see if hovering over the dropdown or the link still var isDropdownHovered = $(this).next().filter(":hover").length; // check the dropdown for hover - returns true of false var isThisHovered = $(this).filter(":hover").length; // check the top level item for hover if(isDropdownHovered || isThisHovered) { // still hovering over the link or the dropdown } else { // no longer hovering over either - lets remove the 'show' classes $(this).attr('data-toggle', 'dropdown'); // put back the data-toggle attr $(this).parent().removeClass('show'); $(this).next().removeClass('show'); } }); // Check the dropdown on hover $(".dropdown-menu").hover( function () { }, function() { var isDropdownHovered = $(this).prev().filter(":hover").length; // check the dropdown for hover - returns true of false var isThisHovered= $(this).filter(":hover").length; // check the top level item for hover if(isDropdownHovered || isThisHovered) { // do nothing - hovering over the dropdown of the top level link } else { // get rid of the classes showing it $(this).parent().removeClass('show'); $(this).removeClass('show'); } });
CSS
@media(min-width: 768px) { .dropdown-menu { margin-top: 0; // fixes closing on slow mouse transition } }
, который возвращает null
blockquote>Возможно потому, что вы вызываете его слишком рано. Подождите, пока
onFinishInflate()
. Вот пример проекта , демонстрирующий пользовательскийView
доступ к его содержимому.
Задайте содержимое активности из ресурса макета. Т. Е, setContentView(R.layout.basicXml)
ОГРАНИЧИВАЙТЕ СРОК! (который содержит id)
В моем случае findViewById () возвратил null, потому что макет, в котором был написан элемент, не был завышен ...
Например. fragment_layout.xml
<ListView
android:id="@+id/listview">
findViewById (R.id.listview) возвратил null, потому что я не делал inflater.inflate (R.layout.fragment_layout, ..., ...); перед ним.
Надеюсь, этот ответ поможет некоторым из вас.
Для меня у меня было два xml-макета для одного и того же действия - один в портретном режиме и один в ландшафте. Конечно, я изменил идентификатор объекта в ландшафтном xml, но забыл сделать такое же изменение в портретной версии. Убедитесь, что если вы изменили один, вы сделаете то же самое с другим xml, иначе вы не получите сообщение об ошибке, пока не запустите / отлаживаете его, и он не сможет найти идентификатор, который вы не изменили. О, глупые ошибки, почему ты так меня наказываешь?
findViewById также может возвращать значение null, если вы находитесь внутри фрагмента. Как описано здесь: findViewById in Fragment
Вы должны вызвать getView () для возврата верхнего уровня в фрагмент. Затем вы можете найти элементы макета (кнопки, текстовые изображения и т. Д.)
В моем случае ничего подобного нет, никаких решений не было. Я предполагаю, что мой взгляд был слишком глубоким в иерархии компоновки. Я переместил его на один уровень, и он больше не был нулевым.
Возможно, вы вызываете findViewById
перед вызовом setContentView
? Если это так, попробуйте позвонить findViewById
ПОСЛЕ вызова setContentView
FWIW, я не вижу, чтобы кто-то решил это так же, как мне было нужно. Никаких жалоб во время компиляции, но я получал нулевой вид во время выполнения и вызывал вещи в правильном порядке. То есть findViewById () после setContentView (). Проблема заключалась в том, что мой взгляд определен в content_main.xml, но в моем activity_main.xml мне не хватало этого одного оператора:
<include layout="@layout/content_main" />
Когда я добавил это в activity_main.xml, больше не было NullPointer.
В моем случае у меня было 2 активности в моем проекте, main.xml
и main2.xml
. С самого начала main2
была копией main
, и все работало хорошо, пока я не добавил новые TextView
в main2
, поэтому R.id.textview1
стал доступен для остальных приложений. Затем я попытался получить его стандартным вызовом:
TextView tv = (TextView) findViewById( R.id.textview1 );
, и он всегда был нулевым. Оказалось, что в конструкторе onCreate
я создавал экземпляр не main2
, а другой. У меня было:
setContentView(R.layout.main);
вместо
setContentView(R.layout.main2);
Я заметил это после того, как я приехал сюда, на сайт.
У меня была такая же проблема. Я использовал стороннюю библиотеку, которая позволяет переопределить их адаптер для GridView и указать свой собственный макет для каждой ячейки GridView.
Я наконец понял, что происходит. Eclipse все еще использовал XML-файл макета библиотеки для каждой ячейки в GridView, хотя он не дал никаких указаний на это. В моем пользовательском адаптере он указал, что он использует ресурс xml из моего собственного проекта, хотя во время выполнения он не был.
Итак, что я сделал, чтобы убедиться, что мои собственные макеты xml и идентификаторы были отличные от тех, которые все еще сидят в библиотеке, очистили проект, а затем начали читать правильные пользовательские макеты, которые были в моем проекте.
Короче говоря, будьте осторожны, если вы переопределяете адаптер сторонней библиотеки и указав свой собственный макет xml для использования адаптером. Если ваш макет внутри вашего проекта имеет то же имя файла, что и в библиотеке, вы можете столкнуться с действительно сложной ошибкой!
В моем случае я использовал ExpandableListView, и я установил android:transcriptMode="normal"
. Это привело к тому, что несколько детей в расширяемой группе исчезли, и я использовал исключение NULL, когда я использовал прокрутку списка.
Убедитесь, что у вас нет нескольких версий макета для разных плотностей экрана. Однажды я столкнулся с этой проблемой при добавлении нового идентификатора в существующий макет, но забыл обновить версию hdpi. Если вы забудете обновить все версии файла макета, он будет работать для некоторых плотностей экрана, но не для других.
Просто хотел бросить здесь свой конкретный случай.
Я использовал эту директиву в своем 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">
Ответ для тех, кто использует 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, по ошибке я добавил материал UI в activity_main.xml
вместо fragment_main.xml
. Мне потребовалось несколько часов, чтобы понять это ...
В моем случае 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);
Мое решение состояло в том, чтобы просто очистить проект.
В моем конкретном случае я пытался добавить нижний колонтитул в 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);
Наряду с классическими причинами, упомянутыми в другом месте:
setContentView()
перед findViewById()
id
вы хотите находится в представлении или макете, которую вы указали на 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 может быть пустым, если вы вызываете неправильный супер-конструктор в пользовательском представлении. Идентификатор тега является частью attrs, поэтому, если вы игнорируете attrs, вы удаляете ID.
Это было бы неправильно
public CameraSurfaceView(Context context, AttributeSet attrs) {
super(context);
}
Правильно
public CameraSurfaceView(Context context, AttributeSet attrs) {
super(context,attrs);
}
У меня такая же проблема, но я думаю, что ее стоит поделиться с вами, ребята. Если вам нужно 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
:
Я пробовал все выше, ничего не работает. Поэтому мне пришлось сделать свой ImageView static public static ImageView texture;
, а затем texture = (ImageView) findViewById(R.id.texture_back);
, я не думаю, что это хороший подход, хотя это действительно сработало для моего случая :)
По моему опыту, похоже, что это также может произойти, когда ваш код вызывается после OnDestroyView (когда фрагмент находится в фоновом стеке.) Если вы обновляете пользовательский интерфейс на входе от BroadCastReceiver, вы должны проверить, это случай.
В дополнение к вышеуказанным решениям вы убедитесь, что tools:context=".TakeMultipleImages"
в макете имеет такое же значение в файле mainfest.xml: android:name=".TakeMultipleImages"
для того же элемента активности. это происходит при использовании копирования и вставки для создания нового действия
onFinishInflate()
. – CommonsWare 12 October 2015 в 16:58