findViewById we fragmencie

1035

Próbuję utworzyć ImageView we fragmencie, który będzie odnosił się do elementu ImageView, który utworzyłem w XML dla tego fragmentu. Jednak findViewByIdmetoda działa tylko wtedy, gdy rozszerzę klasę Activity. Czy w ogóle mogę go użyć w Fragmentie?

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);
    }
}

W findViewByIdmetodzie występuje błąd wskazujący, że metoda jest niezdefiniowana.

uproszczony.
źródło
Użyj biblioteki przeglądania ButterKnife dla Androida. Pokaż również, jak to działa, jak zintegrować i używać w tworzeniu aplikacji na Androida, aby przyspieszyć rozwój.
Shomu
Minęło trochę czasu, ale wciąż nie akceptujesz odpowiedzi. Czy możesz wybrać odpowiedź, która najbardziej Ci pomogła, aby można ją było oznaczyć jako odpowiedź?
David3103
Zachęca się do korzystania z Data Binding orang View Binding zamiast ręcznego findViewById
mochadwi

Odpowiedzi:

1433

Użyj metody getView () lub parametru View zaimplementowanej onViewCreatedmetody. Zwraca widok główny fragmentu (ten zwrócony onCreateView()metodą) . Dzięki temu możesz zadzwonić 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); 

Jak getView()działa dopiero później onCreateView(), nie można użyć go wewnątrz onCreate()ani onCreateView()metod fragmentu.

korzyść
źródło
323
Uwaga: działa tylko po onCreateView (). Tak więc nie można użyć tego w onCreate ()
Dmitrij Zajcew
7
więc jaką funkcję mogę zastąpić, aby to zaimplementować, jeśli onCreate nie jest właściwym miejscem?
Nico AD
16
To nie pomaga, jeśli ImageViewpochodzi z zawyżonego układu - szczegóły znajdziesz w mojej odpowiedzi. W przeciwnym razie onCreateView jest właściwym miejscem do zrobienia tego @ N-AccessDev
MattJenko
25
Najlepszym miejscem do tego jest metoda
onViewCreated
37
Dokumentacja stwierdza, że onActivityCreated()jest to zalecane miejsce do wyszukiwania i przechowywania odniesień do twoich widoków. Państwo musi posprzątać te przechowywane referencje ustawiając je z powrotem nullw onDestroyView()lub będzie wyciek Activity.
Monstieur
618

Trzeba nadmuchać widok i połączenie fragmentu jest findViewById()na Viewto zwraca.

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
źródło
4
Gdy wykonasz V.findViewById (R.id.someid), z pewnością będzie to działać tylko dla wszystkich widżetów, które są w napompowanym widoku. Co się stanie, jeśli imageView, który próbuje napompować, znajduje się poza napompowanym widokiem?
Raunak
18
Następnie klasa, która „jest właścicielem” i zawyżała imageView, musi zapewnić publiczny dostęp do niego. To jednak bardzo zła praktyka. Fragmenty powinny mieć dostęp tylko do elementów interfejsu użytkownika obecnych w ich układzie.
LeffelMania
1
Wygląda na to, że coś jest nie tak w twoim kodzie (aktualizacja interfejsu z wątku w tle), a nie mój.
LeffelMania
1
Dzięki, to było przydatne. Jako niepowiązany komentarz: staraj się trzymać się konwencji nazewnictwa Java w swoim kodzie. „V” nie wygląda jak nazwa zmiennej w Javie.
altumano
3
To powinna być właściwa odpowiedź. Zaakceptowany zostawia cię z NullPointerException.
Machado
132

Wewnątrz Fragmentklasy otrzymasz metodę przesłonięcia onViewCreated () , w której zawsze należy inicjalizować swoje widoki, ponieważ w tej metodzie otrzymujesz obiekt widoku, za pomocą którego możesz znaleźć swoje widoki, takie jak:

@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);
}

Zawsze pamiętaj w przypadku Fragmentu, że onViewCreated()metoda nie będzie wywoływana automatycznie, jeśli zwracasz wartość null lub super.onCreateView()z onCreateView()metody. Będzie się nazywać domyślnie w przypadku ListFragmentgdy ListFragmentzwrot FrameLayoutdomyślnie.

Uwaga: widok fragmentu można uzyskać w dowolnym miejscu w klasie, używając getView()raz onCreateView()wykonanego pomyślnie. to znaczy

getView().findViewById("your view id");
Ankur Chaudhary
źródło
4
Dziwi mnie, że niewiele osób głosowało za tą odpowiedzią - jest to poprawny sposób konfigurowania detektorów na fragmentach ... Być może było to nowe rozwinięcie interfejsu API.
Sonny,
Używanie viewprzekazane do onViewCreatednadal powoduje, NullPointerExceptionale używanie getActivity()jest w porządku. Jakieś pomysły dlaczego?
dVaffection
@dVaffection Możliwe, że nie zwracasz widoku o wartości innej niż zero w metodzie fragmentu cyklu życia onCreateView (). Teraz w przypadku getActivity otrzymujesz widoki ze swojej działalności, a nie fragmentaryczny widok główny zależy od przekazywanego identyfikatora. Sprawdź, czy zwracasz widok inny niż null z onCreateView, czy nie? Więc daj mi znać.
Ankur Chaudhary
@AnkurChaudhary Zwracam widok z onCreateViewmetody. Właśnie debugowałem i okazuje się, że jest to układ (w moim przypadku FrameLayout). Biorąc to pod uwagę, gdy próbuję znaleźć element, zwraca null. Dlaczego tak się dzieje?
dVaffection
@dVaffection czy możesz podzielić się swoją klasą fragmentów i odpowiadającym im układem.
Ankur Chaudhary
66

Zdaję sobie sprawę, że to stare pytanie, ale dominująca odpowiedź pozostawia wiele do życzenia.

Pytanie nie jest jasne, czego się wymaga imageView- czy przekazujemy je z powrotem jako widok, czy po prostu zachowujemy odniesienie na później?

Tak czy inaczej, jeśli ImageViewpochodzi z napompowanego układu, poprawnym sposobem byłoby:

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
źródło
1
Jak w takim razie zaktualizowałbyś imageView z ListFragment? Czy wymagałoby to FragmentManager? Innymi słowy, jak możesz zaktualizować imageView we fragmencie szczegółów z onListItemClick oddzielnej klasy?
Whyoz
1
Możesz zapisać odniesienie do imageView w przydatnym miejscu lub fragment.getView (). FindViewById (R.id.my_image), gdy jest to potrzebne. W przypadku ListFragment, zakładając, że obraz znajduje się w elemencie listy, zwykle tworzysz uchwyt referencyjny za pomocą metod setTag / getTag elementu widoku listy w metodzie getView adaptera - istnieje wiele przykładów tego, jak to zrobić.
MattJenko
47

Uzyskaj najpierw widok fragmentu, a następnie uzyskaj z tego widoku swoją 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
źródło
Czy metoda onCreate jest przydatna we fragmencie?
Tsunaze
onCreateView tworzy i zwraca hierarchię widoków powiązaną z fragmentem. onCreate jest wywoływany w celu początkowego utworzenia fragmentu. Rzeczywiście, zależy to od tego, co piszesz tymi metodami.
xevincent
No dobrze, ale jak mogę zadeklarować zmienną w onCreate? Ponieważ widok znajduje się w metodzie onCreateView.
Tsunaze
@Tsunaze czy kiedykolwiek dowiedziałeś się, jak to zrobić w metodzie onCreate?
StuStirling
1
Zgadzam się. Ta odpowiedź powinna zostać oznaczona jako rozwiązanie.
Boris Karloff,
25

Możesz to również zrobić w onActivityCreatedmetodzie.

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

Tak jak tutaj: http://developer.android.com/reference/android/app/Fragment.html (przestarzałe na poziomie API 28)

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

i

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

są możliwe.

friiky
źródło
18

getView() da widok root

View v = getView().findViewByID(R.id.x); 
programista marzeń
źródło
17

Możesz zastąpić funkcję onViewCreated (), która jest wywoływana zaraz po zawyżeniu wszystkich widoków. To właściwe miejsce do wypełnienia Viewzmiennych członka Fragmentu . Oto przykład:

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);
    }
}
Lez
źródło
17

Wewnątrz Fragmentklasy otrzymujemy onViewCreated()metodę przesłonięcia, w której zawsze powinniśmy inicjalizować nasze widoki, ponieważ w tej metodzie otrzymujemy viewobiekt. Za pomocą tego obiektu możemy znaleźć nasze widoki jak poniżej:

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);
    }
}
Vipul Prajapati
źródło
2
doskonale działał dobrze! wielkie dzięki
Vivek
15

Metoda getView () nie będzie działać na fragmentach poza OnCreate i podobnymi metodami.

Masz dwa sposoby, przekaż widok do funkcji w trakcie tworzenia (co oznacza, że ​​możesz uruchamiać swoje funkcje tylko podczas tworzenia widoku) lub ustawić widok jako zmienną:

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
źródło
11

1) najpierw napompuj układ Fragmentu, a następnie użyj findviewbyId.

View view = inflater.inflate(R.layout.testclassfragment, container, false);
             ImageView imageView = (ImageView) view.findViewById(R.id.my_image);
             return view;
priti
źródło
10
EditText name = (EditText) getView().findViewById(R.id.editText1);
EditText add = (EditText) getView().findViewById(R.id.editText2);  
sandhu
źródło
9

Posługiwać się

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

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

to będzie działać

Manoj Ahirwar
źródło
9

zgodził się findViewById()na wywołanie Widoku.

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
źródło
9

Uwaga :

Z poziomu API 26 nie musisz też specjalnie rzutować wyniku findViewById, ponieważ używa on wnioskowania dla swojego typu zwracanego.

Więc teraz możesz po prostu zrobić,

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;
}
Kartik Shandilya
źródło
1
Pomogło mi to bez rzucania rzeczy wyjaśnione.
shaurya uppal
8

Zgodnie z dokumentacją na poziomie API 11

Odwołanie w Back Stack http://developer.android.com/reference/android/app/Fragment.html

krótki kod

/**
 * 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;
}
Dexter
źródło
8

Za pomocą getView()zwraca widok fragmentu, a następnie można wywołać findViewById()dostęp do dowolnego elementu widoku w widoku fragmentu.

Mahmoud Badri
źródło
3
widok nie jest zajęciem
Steve M.
7

Wypróbuj to, działa dla mnie

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);
    }
}
Bipin Bharti
źródło
Tak, ten kod tutaj jest w porządku. Twoje zmiany w drugim pliku nie są.
OneCricketeer
@ cricket_007 ok, który mnie widziałeś?
Bipin Bharti
Przepraszam, nie rozumiem twojego angielskiego, ale teraz wszystko jest naprawione. Nie mam ci nic do pokazania.
OneCricketeer
5

Najlepszym sposobem na wdrożenie tego jest:

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
}

W ten sposób rootView może być użyty dla każdej kontrolki zdefiniowanej w układzie xml, a kod jest znacznie bardziej przejrzysty w ten sposób.

Mam nadzieję że to pomoże :)

Michele La Ferla
źródło
myślałem, że to może być możliwe, ale to nie zadziałało
Mike Brian Olivera
5

1) Zadeklaruj plik układu.

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

2) Następnie uzyskaj identyfikator swojego widoku

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    TextView nameView = (TextView) view.findViewById(R.id.textview1);
}
Nanda Gopal
źródło
4

Użyj wtyczki gradle szkielet , automatycznie wygeneruje klasy uchwytów widoków w odniesieniu do twojego układu.

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;
    }
}

Zakładając, że masz już ImageViewzadeklarowany my_layout.xmlplik, automatycznie wygeneruje dla ciebie klasę myLayout.

Ilya Gazman
źródło
4

Spróbuj tego:

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

return v;
AbhayBohra
źródło
4

próbować

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
źródło
Nie ma powodu do tego. Zawsze możesz zadzwonić getView()później
OneCricketeer
3

Możesz wywoływać findViewById()za pomocą obiektu aktywności, który znajdziesz w swojej public void onAttach(Activity activity)metodzie wewnątrz fragmentu.

Zapisz działanie w zmiennej, na przykład:

W klasie Fragment : private Activity mainActivity; w onAttach()metodzie: this.mainActivity=activity;

Na koniec wykonaj każde findViewById poprzez vairable: mainActivity.findViewById(R.id.TextView);

mrSurprise
źródło
3

Jest jeszcze jedna metoda o nazwie onViewCreated.

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    ImageView imageView = (ImageView) view.findViewById(R.id.imageview1);
}
Raja Jawahar
źródło
2

Wewnątrz metody onCreateView

1) najpierw musisz nadmuchać układ / widok, który chcesz dodać np. Układ liniowy

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

2) Następnie możesz znaleźć identyfikator imageView z układu

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

3) zwróć napompowany układ

return ll;
Devendra Kulkarni
źródło
Jest to identyczne z odpowiedzią LeffelMania.
Reti43,
2

Musisz nadmuchać widok

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
}}
Surajit Mondal
źródło
2

W fragmentach potrzebujemy widoku tego okna, aby utworzyć onCreateView tego fragmentu.

Następnie uzyskaj widok i użyj go, aby uzyskać dostęp do każdego identyfikatora widoku tego elementu widoku.

  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;
        }
    }
Mayank Garg
źródło
1) Co to dodaje do innych odpowiedzi? 2)
Wygląda
2

Układ inflatora pojawia się tutaj. Layout inflater to klasa, która pozwala nam korzystać z widoków XML w kodzie Java. Możesz więc napompować główny widok xml w zmiennej v następującym kodem. A następnie za pomocą v można znaleźć widoki potomne widoku głównego 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;
    }
}
Wijay Sharma
źródło
1

Najłatwiejszym sposobem korzystania z takich rzeczy jest użycie maślanki. Dzięki temu możesz dodać tyle Onclciklistenerów tylko przez @OnClick (), jak opisano poniżej:

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
źródło
Po co głosować w dół, jeśli go użyjesz, możesz użyć wielu kliknięć również w oświadczeniu.
Amit