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()методы фрагмента.

advantej
источник
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;
}
LeffelMania
источник
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;
    }
}
MattJenko
источник
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;
}
xevincent
источник
Итак, полезен ли метод 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);

возможны

friiky
источник
18

getView() даст корневой вид

View v = getView().findViewByID(R.id.x); 
dreamdeveloper
источник
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);
}
sagits
источник
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;
}
Pajeh
источник
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;
AbhayBohra
источник
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;
}
Ramkumar.M
источник
Там нет причин для поля. Вы всегда можете позвонить getView()позже
OneCricketeer
3

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

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

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

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

mrSurprise
источник
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
источник
Почему проголосовали, если вы используете это, вы можете использовать несколько щелчков мышью также в заявлении.
Amit