findViewById во фрагменте


1035

Я пытаюсь создать ImageView во фрагменте, который будет ссылаться на элемент ImageView, который я создал в XML для фрагмента. Однако findViewByIdметод работает, только если я расширяю класс Activity. Есть ли в любом случае, что я могу использовать его также во Fragment?

public class TestClass extends Fragment {
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        ImageView imageView = (ImageView)findViewById(R.id.my_image);
        return inflater.inflate(R.layout.testclassfragment, container, false);
    }
}

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


Используйте библиотеку видовых привязок ButterKnife для Android. Также продемонстрируйте, как это работает, как интегрировать и использовать в разработке приложений для Android, чтобы ускорить разработку.
Шому

«Некоторое» время прошло, но вы все еще не приняли ответ. Можете ли вы выбрать ответ, который вам больше всего помог, чтобы его можно было пометить как ответ?
David3103

Рекомендуется использовать
привязку данных или привязку

Ответы:


1433

Используйте getView () или параметр View из реализации onViewCreatedметода. Возвращает корневое представление для фрагмента (возвращенного onCreateView()методом) . С этим вы можете позвонить findViewById().

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    ImageView imageView = (ImageView) getView().findViewById(R.id.foo);
    // or  (ImageView) view.findViewById(R.id.foo); 

Как getView()работает только после onCreateView(), вы не можете использовать его внутри onCreate()или onCreateView()методы фрагмента.


323
Примечание: это работает только после onCreateView (). Таким образом, вы не можете использовать это в onCreate ()
Дмитрий Зайцев

7
Так что же это за функция, которую я могу переопределить, чтобы реализовать это, если onCreate не в нужном месте?
Нико А.Д.

16
Это не поможет, если ImageViewэто исходит от раздутого макета - подробности смотрите в моем ответе. В противном случае, onCreateView - подходящее место для этого @ N-
AccessDev

25
Лучшее место для этого - метод
onViewCreated

37
В документации указано, что onActivityCreated()это рекомендуемое место для поиска и хранения ссылок на ваши представления. Вы должны очистить эти сохраненные ссылки, установив их обратно nullв, onDestroyView()иначе вы утечете Activity.
Месье

618

Вам нужно раздувать вид и вызов фрагмента findViewById()на Viewнего возвращается.

public View onCreateView(LayoutInflater inflater, 
                         ViewGroup container, 
                         Bundle savedInstanceState) {
     View view = inflater.inflate(R.layout.testclassfragment, container, false);
     ImageView imageView = (ImageView) view.findViewById(R.id.my_image);
     return view;
}

4
Когда вы делаете V.findViewById (R.id.someid), несомненно, это будет работать только для всех виджетов, которые находятся в раздутом виде. Что если imageView, который он пытается надуть, находится за пределами раздутого вида?
Раунак

18
Затем класс, который «владеет» и раздувает imageView, должен предоставить к нему публичный доступ. Это очень плохая практика. Фрагменты должны иметь доступ только к элементам пользовательского интерфейса, представленным в их макете.
LeffelMania

1
Похоже, что-то не так в вашем коде (обновление пользовательского интерфейса из фонового потока), а не в моем.
LeffelMania

1
Спасибо, это было полезно. Как несвязанный комментарий: попробуйте придерживаться соглашений об именах Java в вашем коде. «V» не похоже на имя переменной в Java.
altumano

3
Это должен быть правильный ответ. Принятый оставляет вас с NullPointerException.
Мачадо

132

Внутри Fragmentкласса вы получите метод переопределения onViewCreated (), в котором вы всегда должны инициализировать ваши представления, так как в этом методе вы получаете объект представления, с помощью которого вы можете найти ваши представления следующим образом:

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    view.findViewById(R.id.yourId).setOnClickListener(this);

    // or
    getActivity().findViewById(R.id.yourId).setOnClickListener(this);
}

Всегда помните , в случае фрагмента , что onViewCreated()метод не вызывается автоматически , если вы возвращаете нуль или super.onCreateView()из onCreateView()метода. Он будет называться по умолчанию в случае , если в ListFragmentкачестве ListFragmentвозврата FrameLayoutпо умолчанию.

Примечание: вы можете получить представление фрагмента в любом месте класса, используя getView()один раз onCreateView()успешно выполненный. т.е.

getView().findViewById("your view id");

4
Я удивлен, что не многие люди проголосовали за этот ответ - это правильный способ настроить слушателей на фрагменты ... Возможно, это была новая разработка в API.
Сонни

Использование viewпередано по- onViewCreatedпрежнему причины, NullPointerExceptionно использование getActivity()в порядке. Есть идеи почему?
dVaffection

@dVaffection Возможно, вы не возвращаете ненулевое представление в методе жизненного цикла фрагмента onCreateView (). Теперь, в случае с getActivity, вы получаете представления от своей активности, а не фрагменты. Основное представление зависит от того, какой идентификатор вы передаете. Пожалуйста, проверьте, возвращаете ли вы ненулевое представление из onCreateView или нет? Тогда дайте мне знать.
Анкур Чаудхари

@AnkurChaudhary Я возвращаю представление из onCreateViewметода. Я только что отладил, и оказалось, что есть макет (в моем случае FrameLayout). При этом, когда я пытаюсь найти элемент, он возвращается null. Почему это происходит?
dVaffection

@dVaffection не могли бы вы поделиться своим классом фрагмента и соответствующего макета.
Анкур Чаудхари

66

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

Вопрос не ясен, что требуется imageView- мы передаем его обратно как представление или просто сохраняем ссылку на будущее?

В любом случае, если ImageViewэто исходит от раздутого макета, правильный способ сделать это будет:

public class TestClass extends Fragment {
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.testclassfragment, container, false);
        ImageView imageView = (ImageView)v.findViewById(R.id.my_image);
        return v;
    }
}

1
Как тогда вы обновите imageView из ListFragment? Для этого потребуется FragmentManager? Другими словами, как вы можете обновить imageView во фрагменте детали из onListItemClick отдельного класса?
Whyoz

1
Вы бы либо сохранили ссылку на imageView где-нибудь под рукой, либо фрагмента .getView (). FindViewById (R.id.my_image), когда вам это нужно. В ListFragment, предполагая, что изображение находится в элементе списка, вы обычно создаете держатель ссылки с помощью методов setTag / getTag элемента представления списка в методе getView вашего адаптера - есть много примеров того, как это сделать.
MattJenko

47

Сначала получите вид фрагмента, а затем получите из этого вида свой ImageView.

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.testclassfragment, container, false);
    ImageView imageView = (ImageView) view.findViewById(R.id.my_image);
    return view;
}

Итак, полезен ли метод onCreate во фрагменте?
Цуназе

onCreateView создает и возвращает иерархию представления, связанную с фрагментом. Вызывается onCreate, чтобы выполнить первоначальное создание фрагмента. Действительно, это зависит от того, что вы пишете в этих методах.
xevincent

Хорошо, но как я могу объявить переменную в onCreate? Потому что View находится внутри метода onCreateView.
Цуназе

@Tsunaze, ты когда-нибудь узнал, как это сделать с помощью метода onCreate?
StuStirling

1
Согласен. Этот ответ должен быть помечен как решение.
Борис Карлофф

25

Вы также можете сделать это в onActivityCreatedметоде.

public void onActivityCreated(Bundle savedInstanceState) { 
      super.onActivityCreated(savedInstanceState);
}

Как они делают здесь: http://developer.android.com/reference/android/app/Fragment.html (устарело на уровне API 28)

getView().findViewById(R.id.foo);

а также

getActivity().findViewById(R.id.foo);

возможны



17

Вы можете переопределить onViewCreated (), который вызывается сразу после того, как все представления были завышены. Это правильное место для заполнения Viewпеременных- членов вашего фрагмента . Вот пример:

class GalleryFragment extends Fragment {
    private Gallery gallery;

    (...)

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        gallery = (Gallery) view.findViewById(R.id.gallery);
        gallery.setAdapter(adapter);
        super.onViewCreated(view, savedInstanceState);
    }
}

17

Внутри Fragmentкласса мы получаем onViewCreated()метод переопределения, где мы всегда должны инициализировать наши представления, потому что в этом методе мы получаем viewобъект. Используя этот объект, мы можем найти наши взгляды, как показано ниже:

class MyFragment extends Fragment {
    private ImageView imageView;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.my_fragment_layout, container, false);
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        //initialize your view here for use view.findViewById("your view id")
        imageView = (ImageView) view.findViewById(R.id.my_image);
    }
}

2
отлично работал хорошо! спасибо
Вивек

15

Метод getView () не будет работать с фрагментами вне OnCreate и аналогичными методами.

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

private View rootView;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
    Bundle savedInstanceState) {
    rootView = inflater.inflate(R.layout.fragment_contatos, container, false);
}

public void doSomething () {
    ImageView thumbnail = (ImageView) rootView.findViewById(R.id.someId);
}

11

1) сначала надуйте макет фрагмента, затем вы можете использовать findviewbyId.

View view = inflater.inflate(R.layout.testclassfragment, container, false);
             ImageView imageView = (ImageView) view.findViewById(R.id.my_image);
             return view;

10
EditText name = (EditText) getView().findViewById(R.id.editText1);
EditText add = (EditText) getView().findViewById(R.id.editText2);  

9

использование

imagebutton = (ImageButton) getActivity().findViewById(R.id.imagebutton1);

imageview = (ImageView) getActivity().findViewById(R.id.imageview1);

это будет работать


9

согласился с заходом findViewById()на Вью.

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View V = inflater.inflate(R.layout.testclassfragment, container, false);
    ImageView imageView = (ImageView) V.findViewById(R.id.my_image);

    return V;
}

9

Замечания :

На уровне API 26 вам также не нужно специально приводить результат findViewById, поскольку он использует логический вывод для своего типа возвращаемого значения.

Так что теперь вы можете просто сделать,

public View onCreateView(LayoutInflater inflater, 
                         ViewGroup container, 
                         Bundle savedInstanceState) {
     View view = inflater.inflate(R.layout.testclassfragment, container, false);
     ImageView imageView =  view.findViewById(R.id.my_image); //without casting the return type
     return view;
}

1
Без кастинга вещь объяснила, помогла мне.
Shaurya Uppal

8

Согласно документации по API уровня 11

Ссылка, в Back Stack http://developer.android.com/reference/android/app/Fragment.html

короткий код

/**
 * The Fragment's UI is just a simple text view showing its
 * instance number.
 */
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.hello_world, container, false);
    View tv = v.findViewById(R.id.text);
    ((TextView)tv).setText("Fragment #" + mNum);
    tv.setBackgroundDrawable(getResources().getDrawable(android.R.drawable.gallery_thumb));
    return v;
}

8

Использование getView()возвращает представление фрагмента, затем вы можете вызвать findViewById()доступ к любому элементу представления в представлении фрагмента.


3
мнение не является деятельностью
Стив M

7

Попробуйте это у меня работает

public class TestClass extends Fragment {
    private ImageView imageView;

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.testclassfragment, container, false);
        findViews(view);
        return view;
    }

    private void findViews(View view) {
        imageView = (ImageView) view.findViewById(R.id.my_image);
    }
}

Да, этот код здесь в порядке. Ваши правки для другого нет.
OneCricketeer

@ cricket_007 хорошо, кого ты меня видел?
Бипин Бхарти

Извините, я не совсем понимаю ваш английский, но теперь все исправлено. Мне нечего вам показать.
OneCricketeer

5

Лучший способ реализовать это следующим образом:

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

rootView = inflater.inflate(R.layout.testclassfragment, container, false);
        ImageView imageView = (ImageView) rootView.findViewById(R.id.my_image);
        return rootView
}

Таким образом, rootView можно использовать для каждого элемента управления, определенного в макете xml, и таким образом код становится намного чище.

Надеюсь это поможет :)


я думал, что это может быть возможно, но это не сработало
Майк Брайан Оливера

5

1) Объявите свой файл макета.

public View onCreateView(LayoutInflater inflater,ViewGroup container, 
                                 Bundle savedInstanceState) {
    return inflate(R.layout.myfragment, container, false);
}

2) Затем получите идентификатор вашего взгляда

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    TextView nameView = (TextView) view.findViewById(R.id.textview1);
}

4

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

public class TestClass extends Fragment {
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        MyLayout myLayout = new MyLayout(inflater, container, false);
        myLayout.myImage.setImageResource(R.drawable.myImage);
        return myLayout.view;
    }
}

Теперь, если у вас есть ImageViewобъявление в вашем my_layout.xmlфайле, он автоматически сгенерирует класс myLayout для вас.


4

Попробуй это:

View v = inflater.inflate(R.layout.testclassfragment, container, false);
ImageView img = (ImageView) v.findViewById(R.id.my_image);

return v;

4

пытаться

private View myFragmentView;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
{
myFragmentView = inflater.inflate(R.layout.myLayoutId, container, false);
myView = myFragmentView.findViewById(R.id.myIdTag)
return myFragmentView;
}

Там нет причин для поля. Вы всегда можете позвонить getView()позже
OneCricketeer

3

Вы можете позвонить findViewById()с объектом деятельности вы получаете внутри вашего public void onAttach(Activity activity)метода внутри вашего фрагмента.

Сохраните Activity в переменную, например:

В классе Fragment : private Activity mainActivity; в onAttach()методе: this.mainActivity=activity;

Наконец, выполните каждый findViewById через переменную: mainActivity.findViewById(R.id.TextView);


3

Есть еще один метод, который называется onViewCreated.

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    ImageView imageView = (ImageView) view.findViewById(R.id.imageview1);
}

2

Внутри метода onCreateView

1) сначала нужно надуть макет / вид, который вы хотите добавить, например. LinearLayout

LinearLayout ll = inflater.inflate(R.layout.testclassfragment, container, false);

2) Затем вы можете найти свой идентификатор imageView из макета

ImageView imageView = (ImageView)ll.findViewById(R.id.my_image);

3) вернуть раздутый макет

return ll;

Это идентично ответу ЛеффельМании.
Reti43

2

Вы должны раздуть вид

public class TestClass extends Fragment {

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.testclassfragment, container, false);
    ImageView imageView = (ImageView)v.findViewById(R.id.my_image);
    return v
}}

2

Во фрагментах нам нужно представление этого окна, чтобы мы создали onCreateView этого фрагмента.

Затем получите представление и используйте его для доступа к каждому идентификатору представления этих элементов представления.

  class Demo extends Fragment
    {
        @Override
        public View onCreateView(final LayoutInflater inflater,ViewGroup container, Bundle savedInstanceState)
        {
            View view =inflater.inflate(R.layout.demo_fragment, container,false);
            ImageView imageview=(ImageView)view.findViewById(R.id.imageview1);

            return view;
        }
    }

1) Что это добавляет к другим ответам? 2) Вы, кажется, ответили дважды
OneCricketeer

2

Макет Inflater входит в картину здесь. Layout Inflater - это класс, который позволяет нам использовать представления XML в коде Java. Таким образом, вы можете накачать корневое представление XML в переменной v с помощью следующего кода. А затем с помощью v вы можете найти дочерние представления корневого представления v.

public class TestClass extends Fragment {
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.testclassfragment, container, false);
    ImageView imageView = (ImageView)v.findViewById(R.id.my_image);
    return v;
    }
}

1

Самый простой способ использовать такие вещи - использовать нож для масла. Таким образом, вы можете добавить столько Onclciklisteners просто с помощью @OnClick (), как описано ниже:

public class TestClass extends Fragment {
    @BindView(R.id.my_image) ImageView imageView;
    @OnClick(R.id.my_image)
    public void my_image_click(){
        yourMethod();
    }
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view=inflater.inflate(R.layout.testclassfragment, container, false);
        ButterKnife.bind(getActivity,view);
        return view;
    }
}

Почему проголосовали, если вы используете это, вы можете использовать несколько щелчков мышью также в заявлении.
Amit
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.