findViewById trong Fragment


1035

Tôi đang cố gắng tạo ImageView trong Fragment, nó sẽ tham chiếu đến phần tử ImageView mà tôi đã tạo trong XML cho Fragment. Tuy nhiên, findViewByIdphương thức chỉ hoạt động nếu tôi mở rộng một lớp Activity. Có cách nào tôi có thể sử dụng nó trong Fragment không?

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

Các findViewByIdphương pháp có một lỗi trên đó mà khẳng định rằng phương pháp này là không xác định.


Sử dụng thư viện viewbinding ButterKnife cho Android. Đồng thời trình bày cách thức hoạt động, cách tích hợp và sử dụng trong phát triển ứng dụng Android của bạn để giúp quá trình phát triển của bạn nhanh hơn.
Shomu

Thời gian đã trôi qua nhưng bạn vẫn chưa chấp nhận câu trả lời. Bạn có thể chọn câu trả lời giúp bạn nhiều nhất để câu này có thể được đánh dấu là đã trả lời không?
David3103

Khuyến khích sử dụng Data Binding orang Xem Binding thay vì tìm thủ công findViewById
mochadwi

Câu trả lời:


1433

Sử dụng getView () hoặc tham số View để thực hiện onViewCreatedphương thức. Nó trả về khung nhìn gốc cho đoạn (cái được trả về bởi onCreateView()phương thức) . Với điều này bạn có thể gọi 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()chỉ hoạt động sau đó onCreateView(), bạn không thể sử dụng nó bên trong onCreate()hoặc onCreateView()phương pháp của đoạn.


323
Lưu ý: nó chỉ hoạt động sau khi onCreateView (). Vì vậy, bạn không thể sử dụng điều này trong onCreate ()
Dmitry Zaytsev

7
Vậy chức năng nào tôi có thể ghi đè để thực hiện điều này nếu onCreate không đúng chỗ?
Nico AD

16
Điều này không có ích nếu ImageViewđến từ bố cục bị thổi phồng - xem câu trả lời của tôi để biết chi tiết. Mặt khác, onCreateView là nơi thích hợp để làm điều này @ N-AccessDev
MattJenko

25
Nơi tốt nhất để thực hiện phương thức onViewCreated này
preferej

37
Các tài liệu nêu rõ đó onActivityCreated()là nơi được đề xuất để tìm và lưu trữ các tài liệu tham khảo cho quan điểm của bạn. Bạn phải dọn dẹp những tài liệu tham khảo được lưu trữ bằng cách đặt chúng trở lại nulltrong onDestroyView()hoặc bạn sẽ bị rò rỉ các Activity.
Monstieur

618

Bạn cần phải thổi phồng cái nhìn và lời kêu gọi của Fragment findViewById()trên Viewnó trả về.

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
Khi bạn thực hiện V.findViewById (R.id.someid), chắc chắn điều đó sẽ chỉ hoạt động cho tất cả các tiện ích trong chế độ xem bị thổi phồng. Điều gì sẽ xảy ra nếu imageView mà anh ta đang cố gắng tăng lên nằm ngoài chế độ xem bị thổi phồng?
Raunak

18
Sau đó, lớp "sở hữu" và thổi phồng imageView cần cung cấp quyền truy cập công khai vào nó. Đó là thực tế rất xấu mặc dù. Các mảnh chỉ nên có quyền truy cập vào các thành phần UI có trong bố cục của chúng.
LeffelMania

1
Có vẻ như có gì đó không đúng trong mã của bạn (cập nhật giao diện người dùng từ một luồng nền), không phải của tôi.
LeffelMania

1
Cảm ơn, nó rất hữu ích. Như nhận xét không liên quan: cố gắng tuân theo các quy ước đặt tên Java trong mã của bạn. "V" không giống như một tên biến trong Java.
altumano

3
Đây phải là câu trả lời đúng. Một trong những chấp nhận để lại cho bạn với NullPointerException.
Machado

132

Bên trong Fragmentlớp bạn sẽ nhận được phương thức ghi đè onViewCreated () trong đó bạn phải luôn khởi tạo các khung nhìn của mình như trong phương thức này, bạn có được đối tượng xem bằng cách sử dụng mà bạn có thể tìm thấy các khung nhìn của mình như:

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

Luôn nhớ trong trường hợp Fragment, onViewCreated()phương thức đó sẽ không được gọi tự động nếu bạn trả về null hoặc super.onCreateView()từ onCreateView()phương thức. Nó sẽ được gọi theo mặc định trong trường hợp ListFragmentnhư ListFragmenttrở lại FrameLayouttheo mặc định.

Lưu ý: bạn có thể có được chế độ xem phân đoạn ở bất cứ đâu trong lớp bằng cách sử dụng getView()một lần onCreateView()đã được thực hiện thành công. I E

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

4
Tôi ngạc nhiên khi không có nhiều người ủng hộ phản hồi này - đây là cách chính xác để thiết lập trình nghe trên các đoạn ... Có lẽ đây là một sự phát triển mới trong API.
Sonny

Sử dụng viewthông qua onViewCreatedvẫn còn nguyên nhân NullPointerExceptionnhưng sử dụng getActivity()là tốt. Bất cứ ý tưởng tại sao?
dVaffection

@dVaffection Có thể bạn không trả về chế độ xem không null trong phương thức vòng đời onCreateView (). Bây giờ trong trường hợp getActivity, bạn sẽ có được lượt xem từ hoạt động của mình chứ không phải là chế độ xem chính phân đoạn phụ thuộc vào id bạn đang chuyển. Vui lòng kiểm tra xem bạn có trả lại chế độ xem không null từ onCreateView hay không? Sau đó cho tôi biết.
Ankur Chaudhary

@AnkurChaudhary Tôi quay lại xem từ onCreateViewphương thức. Tôi vừa mới gỡ lỗi và hóa ra có một bố cục (trong trường hợp của tôi FrameLayout). Điều đó được nói khi tôi cố gắng tìm một yếu tố nó trở lại null. Tại sao nó lại xảy ra?
dVaffection

@dVaffection bạn có thể vui lòng chia sẻ lớp phân đoạn của bạn và bố cục tương ứng.
Ankur Chaudhary

66

Tôi nhận ra đây là một câu hỏi cũ, nhưng câu trả lời phổ biến để lại điều gì đó mong muốn.

Câu hỏi không rõ ràng những gì được yêu cầu imageView- chúng ta sẽ chuyển nó trở lại làm chế độ xem hay chỉ lưu một tài liệu tham khảo cho lần sau?

Dù bằng cách nào, nếu ImageViewđến từ bố cục bị thổi phồng, cách chính xác để làm điều này sẽ là:

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
Sau đó, bạn sẽ cập nhật imageView từ ListFragment như thế nào? Điều này sẽ yêu cầu FragmentManager? Nói cách khác, làm thế nào bạn có thể cập nhật imageView trong một đoạn chi tiết từ một lớp riêng của onListItemClick?
whyoz

1
Bạn có thể lưu một tham chiếu đến imageView ở đâu đó tiện dụng hoặc Fragment.getView (). FindViewById (R.id.my_image) khi bạn cần. Trong ListFragment, giả sử hình ảnh nằm trong một mục danh sách, bạn thường sẽ tạo một trình giữ tham chiếu với các phương thức setTag / getTag của mục xem danh sách trong phương thức getView của Adaptor - có nhiều ví dụ về cách thực hiện điều này.
MattJenko

47

Trước tiên hãy xem chế độ phân đoạn và sau đó nhận từ chế độ xem ImageView của bạn.

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

Vì vậy, phương thức onCreate có hữu ích trong một mảnh không?
Tsunaze

onCreateView tạo và trả về hệ thống phân cấp khung nhìn được liên kết với đoạn.onCreate được gọi để thực hiện việc tạo ban đầu của đoạn. Thật vậy, nó phụ thuộc vào những gì bạn viết trong các phương pháp này.
xevincent

Được rồi, nhưng làm thế nào tôi có thể khai báo biến trong onCreate? Bởi vì View nằm bên trong phương thức onCreateView.
Tsunaze

@Tsunaze bạn đã bao giờ tìm hiểu làm thế nào để làm điều này từ phương thức onCreate chưa?
StuStirling

1
Tôi đồng ý. Câu trả lời này nên được đánh dấu là giải pháp.
Boris Karloff

25

Bạn cũng có thể làm điều đó trong onActivityCreatedPhương thức.

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

Giống như họ làm ở đây: http://developer.android.com/reference/android/app/Fragment.html (không dùng ở cấp độ API 28)

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

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

là có thể



17

Bạn có thể ghi đè onViewCreated () được gọi ngay sau khi tất cả các chế độ xem bị thổi phồng. Đây là nơi thích hợp để điền vào các Viewbiến thành viên của Fragment của bạn . Đây là một ví dụ:

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

Bên trong Fragmentlớp chúng ta có onViewCreated()phương thức ghi đè, trong đó chúng ta phải luôn khởi tạo các khung nhìn của mình bởi vì trong phương thức này, chúng ta có viewđối tượng. Sử dụng đối tượng này, chúng tôi có thể tìm thấy quan điểm của chúng tôi như dưới đây:

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
xuất sắc làm việc tốt! cảm ơn rất nhiều
Vivek

15

Phương thức getView () sẽ không hoạt động trên các đoạn bên ngoài OnCreate và các phương thức tương tự.

Bạn có hai cách, chuyển chế độ xem cho hàm trên oncreate (có nghĩa là bạn chỉ có thể chạy các chức năng của mình khi chế độ xem được tạo) hoặc đặt chế độ xem làm biến:

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) bố trí lạm phát đầu tiên của Fragment sau đó bạn có thể sử dụng 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

Sử dụng

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

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

nó sẽ làm việc


9

đồng ý với việc kêu gọi findViewById()trên View.

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

Ghi chú :

Từ API cấp 26, bạn cũng không cần truyền cụ thể kết quả của findViewById vì nó sử dụng suy luận cho loại trả về của nó.

Vì vậy, bây giờ bạn có thể chỉ cần làm,

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
Không có điều giải thích đã giúp tôi.
shaurya uppal

8

Theo tài liệu về API cấp 11

Tham khảo, trong Back Stack http://developer.android.com/reference/android/app/Fragment.html

mã ngắn

/**
 * 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

Sử dụng getView()trả về chế độ xem của đoạn, sau đó bạn có thể gọi findViewById()để truy cập bất kỳ phần tử xem nào trong chế độ xem đoạn.


3
Chế độ xem không phải là hoạt động
Steve M

7

Hãy thử nó nó hoạt động với tôi

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

Vâng, mã này ở đây là được. Chỉnh sửa của bạn để khác không.
OneCricketeer

@ cricket_007 ok cái nào bạn có thể nhìn thấy tôi?
Bipin Bharti

Tôi xin lỗi tôi không thể hiểu tiếng Anh của bạn, nhưng mọi thứ đã được sửa. Tôi không có gì để chỉ cho bạn.
OneCricketeer

5

Cách tốt nhất để thực hiện điều này là như sau:

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
}

Theo cách này, rootView có thể được sử dụng cho mỗi điều khiển được xác định trong bố cục xml và mã sạch hơn theo cách này.

Hi vọng điêu nay co ich :)


tôi nghĩ rằng điều này có thể rõ ràng, nhưng, nó đã không hoạt động
Mike Brian Olivera

5

1) Khai báo tập tin bố trí của bạn.

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

2) Sau đó, lấy id của chế độ xem của bạn

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

4

Sử dụng plugin bộ xương gradle , nó sẽ tự động tạo ra các lớp giữ khung nhìn với tham chiếu đến bố cục của bạn.

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

Bây giờ giả sử bạn đã ImageViewkhai báo trong my_layout.xmltệp của mình , nó sẽ tự động tạo lớp myLayout cho bạn.


4

Thử cái này:

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

return v;

4

thử

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

Không có lý do cho lĩnh vực này. Bạn luôn có thể gọi getView()sau
OneCricketeer

3

Bạn có thể gọi findViewById()với Object Object mà bạn nhận được trong public void onAttach(Activity activity)phương thức của mình bên trong Fragment.

Lưu Activity vào một biến chẳng hạn:

Trong lớp Fragment : private Activity mainActivity; Trong onAttach()phương thức: this.mainActivity=activity;

Cuối cùng thực hiện mọi findViewById thông qua vai: mainActivity.findViewById(R.id.TextView);


3

Có một phương thức nữa gọi là onViewCreated.

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

2

Bên trong phương thức onCreateView

1) trước tiên, bạn phải tăng bố cục / chế độ xem bạn muốn thêm, vd. Tuyến tính

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

2) Sau đó, bạn có thể tìm id hình ảnh của mình từ bố cục

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

3) trả lại bố cục bị thổi phồng

return ll;

Điều này giống hệt với câu trả lời của LeffelMania.
Reti43

2

Bạn phải làm tăng tầm nhìn

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

Trong các đoạn, chúng ta cần một khung nhìn của cửa sổ đó để chúng ta tạo một onCreateView của Fragment này.

Sau đó, lấy chế độ xem và sử dụng nó để truy cập từng id của chế độ xem đó.

  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) Điều này thêm gì vào câu trả lời khác? 2) Bạn dường như đã trả lời hai lần
OneCricketeer

2

Giao diện bố trí đi vào hình ảnh ở đây. Giao diện bố trí là một lớp giúp chúng ta có thể sử dụng các khung nhìn XML trong mã java. Vì vậy, bạn có thể thổi phồng khung nhìn xml gốc trong biến v với mã sau đây. Và sau đó sử dụng v, bạn có thể tìm thấy các khung nhìn con của khung nhìn gốc 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

Cách dễ nhất để sử dụng những thứ như vậy là sử dụng butterknife Bằng cách này, bạn có thể thêm bao nhiêu Onclciklistener chỉ bằng @OnClick () như được mô tả dưới đây:

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

Tại sao lại bỏ phiếu, nếu bạn sử dụng điều này, bạn có thể sử dụng nhiều onclicks cũng trong tuyên bố.
Amit
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.