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.


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.


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

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

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

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

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,



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

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

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

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;

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

9

Posługiwać się

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

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

to będzie działać


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

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

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

8

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


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

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 :)


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

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.


4

Spróbuj tego:

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

return v;

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

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


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

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;

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

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

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

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

Po co głosować w dół, jeśli go użyjesz, możesz użyć wielu kliknięć również w oświadczeniu.
Amit
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.