findViewById у фрагменті


1035

Я намагаюся створити ImageView у фрагменті, який буде посилатися на елемент ImageView, який я створив у XML для фрагмента. Однак findViewByIdметод працює лише в тому випадку, якщо я розширюю клас діяльності. Чи є в будь-якому випадку я можу це використовувати і в 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

Рекомендується використовувати Data Binding orang View Binding замість ручного findViewById
mochadwi

Відповіді:


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 не потрібне місце?
Ніко AD

16
Це не допоможе, якщо ImageViewвиходить із завищеного макета - детальну інформацію див. У моїй відповіді. Інакше onCreateView - це правильне місце для цього @ N-AccessDev
MattJenko

25
Найкраще місце для цього методом
onViewCreate

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класу ви отримаєте метод переопределення onViewCreate (), де ви завжди повинні ініціалізувати свої погляди, оскільки в цьому методі ви отримуєте об’єкт перегляду, за допомогою якого ви можете знайти свої погляди, як:

@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 ненульовий вигляд чи ні? Тоді дайте мені знати.
Ankur Chaudhary

@AnkurChaudhary Я повертаю погляд з onCreateViewметоду. Я тільки що налагодив, і виявляється, є макет (у моєму випадку FrameLayout). Це було сказано, коли я намагаюся знайти елемент, який він повертає null. Чому це відбувається?
dVaffection

@dVaffection ви можете поділитися своїм класом фрагмента та відповідним макетом.
Ankur Chaudhary

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 десь зручно, або fragment.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 створює та повертає ієрархію подання, пов'язану з fragment.onCreate викликається зробити початкове створення фрагмента. Дійсно, це залежить від того, що ви пишете в цих методах.
xevincent

Гаразд, але як я можу оголосити змінну в onCreate? Оскільки Вид знаходиться всередині методу 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

Ви можете замінити onViewCreate (), який викликається відразу після того, як усі перегляди були завищені. Це правильне місце для заповнення 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
відмінно працював добре! велике спасибі
Vivek

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

Примітка :

Із рівня 26 API вам також не потрібно конкретизувати результат 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

Відповідно до документації на рівні 11 API

Довідка, в 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
погляд не є активністю
Стів М

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 , він автоматично генерує класи власників перегляду з посиланням на ваш макет.

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)методу, всередині вашого фрагмента.

Збережіть активність у змінній, наприклад:

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

Нарешті виконайте кожен findViewById через вавалі: mainActivity.findViewById(R.id.TextView);


3

Є ще один метод, який називається onViewCreate.

@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 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

Тут розміщена надувна макет. Надувний макет - це клас, який дає нам можливість використовувати представлення 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;
    }
}

Чому вниз проголосували, якщо ви користуєтесь цим, ви можете використовувати кілька onclicks також у заяві.
Аміт
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.