findViewById เป็นส่วน ๆ


1035

ฉันพยายามสร้าง ImageView ใน Fragment ซึ่งจะอ้างถึงองค์ประกอบ ImageView ที่ฉันได้สร้างใน XML สำหรับ Fragment อย่างไรก็ตามfindViewByIdวิธีนี้ใช้ได้เฉพาะเมื่อฉันขยายคลาสกิจกรรม มีอะไรบ้างที่ฉันสามารถใช้ในแฟรกเมนต์ได้เช่นกัน?

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 viewbinding library สำหรับ Android ยังแสดงให้เห็นถึงวิธีการทำงานวิธีการรวมและใช้ในการพัฒนาแอพ android ของคุณเพื่อให้การพัฒนาของคุณเร็วขึ้น
Shomu

เวลา 'บาง' ผ่านไปแล้ว แต่คุณยังไม่ได้รับคำตอบ คุณสามารถเลือกคำตอบที่ช่วยคุณได้มากที่สุดเพื่อทำเครื่องหมายคำตอบนี้หรือไม่?
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 ()
Dmitry Zaytsev

7
ดังนั้นอะไรคือฟังก์ชั่นที่ฉันสามารถแทนที่เพื่อนำไปใช้งานได้หาก onCreate ไม่ถูกต้อง?
Nico AD

16
สิ่งนี้ไม่ได้ช่วยถ้าสิ่งที่ImageViewมาจากเค้าโครงที่สูงเกินจริง - ดูคำตอบของฉันสำหรับรายละเอียด มิฉะนั้น onCreateView เป็นสถานที่ที่เหมาะสมในการทำเช่นนี้ @ N-AccessDev
MattJenko

25
สถานที่ที่ดีที่สุดในการทำเช่นนี้กับวิธี
onViewCreated

37
เอกสารคู่มือระบุว่าonActivityCreated()เป็นสถานที่แนะนำสำหรับค้นหาและจัดเก็บข้อมูลอ้างอิงไปยังมุมมองของคุณ คุณจะต้องทำความสะอาดอ้างอิงเหล่านี้เก็บไว้โดยการตั้งค่าพวกเขากลับไปnullในหรือคุณจะรั่วไหลonDestroyView() Activity
Monstieur

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 ที่เขาพยายามขยายนั้นอยู่นอกมุมมองที่ขยายเกินจริง
Raunak

18
จากนั้นคลาสที่ "เป็นเจ้าของ" และขยาย imageView จำเป็นต้องให้สิทธิ์การเข้าถึงแก่สาธารณะ นั่นเป็นการฝึกฝนที่แย่มาก แฟรกเมนต์ควรมีสิทธิ์เข้าถึงองค์ประกอบ UI ที่มีอยู่ในเลย์เอาต์ของพวกเขาเท่านั้น
LeffelMania

1
ดูเหมือนว่ามีสิ่งผิดปกติในรหัสของคุณ (อัปเดต UI จากเธรดพื้นหลัง) ไม่ใช่ของฉัน
LeffelMania

1
ขอบคุณมันมีประโยชน์ ในฐานะที่เป็นความคิดเห็นที่ไม่เกี่ยวข้อง: พยายามที่จะยึดหลักการประชุมการตั้งชื่อ Java ในรหัสของคุณ "V" ดูไม่เหมือนชื่อตัวแปรใน Java
altumano

3
นี่ควรเป็นคำตอบที่ถูกต้อง NullPointerExceptionได้รับการยอมรับอย่างใดอย่างหนึ่งใบกับคุณ
Machado

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

โปรดจำไว้เสมอว่าในกรณี Fragment onViewCreated()วิธีการนั้นจะไม่ถูกเรียกโดยอัตโนมัติหากคุณส่งคืนค่า Null หรือsuper.onCreateView()จากonCreateView()เมธอด มันจะถูกเรียกโดยค่าเริ่มต้นในกรณีListFragmentที่ListFragmentกลับมาเป็นFrameLayoutค่าเริ่มต้น

หมายเหตุ: คุณสามารถรับมุมมองชิ้นส่วนได้ทุกที่ในชั้นเรียนโดยใช้getView()เมื่อonCreateView()ดำเนินการเสร็จสิ้นแล้ว กล่าวคือ

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

4
ฉันประหลาดใจที่มีคนไม่มากที่ยกระดับการตอบสนองนี้ - นี่เป็นวิธีที่ถูกต้องในการตั้งค่าผู้ฟังในส่วนย่อย ๆ ... บางทีนี่อาจเป็นการพัฒนาใหม่ใน API
ซันนี่

การใช้การviewส่งผ่านไปonViewCreatedยังสาเหตุNullPointerExceptionแต่การใช้ไม่getActivity()เป็นผล ความคิดใด ๆ
dVaffection

@dVaffection อาจเป็นเพราะคุณไม่ได้ส่งคืนมุมมองที่ไม่เป็นค่าว่างใน onCreateView () วิธีวงจรชีวิตของแฟรกเมนต์ ตอนนี้ในกรณีที่ getActivity คุณได้รับมุมมองจากกิจกรรมของคุณมากกว่ามุมมองหลักที่แตกออกเป็นส่วน ๆ ขึ้นอยู่กับรหัสที่คุณส่งผ่าน โปรดตรวจสอบว่าคุณส่งคืนมุมมองที่ไม่ใช่ค่า null จาก 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 จะมีประโยชน์ใน Fragment หรือไม่?
Tsunaze

onCreateView สร้างและส่งคืนลำดับชั้นมุมมองที่เชื่อมโยงกับ Fragment.onCreate ถูกเรียกให้ทำการสร้างชิ้นส่วนเริ่มต้น แน่นอนมันขึ้นอยู่กับสิ่งที่คุณเขียนในวิธีการเหล่านี้
xevincent

ตกลง แต่ฉันจะประกาศตัวแปรใน onCreate ได้อย่างไร เนื่องจากมุมมองอยู่ภายในเมธอด onCreateView
Tsunaze

@Tunaze คุณเคยพบวิธีการทำเช่นนี้จากวิธีการ onCreate?
StuStirling

1
ฉันเห็นด้วย. คำตอบนี้ควรถูกทำเครื่องหมายเป็นวิธีแก้ปัญหา
Boris Karloff

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

คุณสามารถแทนที่ onViewCreated () ซึ่งถูกเรียกใช้หลังจากที่มุมมองทั้งหมดถูกขยายเกินจริง เป็นที่ที่เหมาะสมในการเติมViewตัวแปรสมาชิกของ Fragment นี่คือตัวอย่าง:

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) เค้าโครงพองตัวแรกของ Fragment จากนั้นคุณสามารถใช้ findviewbyId

View view = inflater.inflate(R.layout.testclassfragment, container, false);
             ImageView imageView = (ImageView) view.findViewById(R.id.my_image);
             return view;


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

บันทึก :

จาก 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
มุมมองไม่ใช่กิจกรรม
Steve 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 ตกลงคุณเห็นฉันแบบไหน
Bipin Bharti

ฉันขอโทษฉันไม่เข้าใจภาษาอังกฤษของคุณมากนัก แต่ตอนนี้ทุกอย่างได้รับการแก้ไขแล้ว ฉันไม่มีอะไรจะแสดงให้คุณเห็น
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 และโค้ดนั้นสะอาดกว่ามากในวิธีนี้

หวังว่าจะช่วย :)


ฉันคิดว่านี่อาจเป็นไปได้ แต่มันไม่ทำงาน
Mike Brian Olivera

5

1) ประกาศไฟล์เลย์เอาต์ของคุณ

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

2) จากนั้นรับ id ของมุมมองของคุณ

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

4

ใช้ gradle Skeleton pluginมันจะสร้างคลาสตัวยึดมุมมองโดยอัตโนมัติโดยอ้างอิงจากโครงร่างของคุณ

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()ด้วยActivity Object ที่อยู่ภายในpublic void onAttach(Activity activity)วิธีการของคุณในส่วนของคุณ

บันทึกกิจกรรมเป็นตัวแปรเช่น:

ในคลาส Fragment : private Activity mainActivity; ในonAttach()เมธอด: this.mainActivity=activity;

ในที่สุดก็รันทุก findViewById ผ่าน vairable: mainActivity.findViewById(R.id.TextView);


3

มีอีกวิธีหนึ่งที่เรียกว่า onViewCreated

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

2

ภายในวิธีการสร้างมุมมอง

1) ก่อนอื่นคุณต้องขยายเค้าโครง / มุมมองที่คุณต้องการเพิ่มเช่น LinearLayout

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

2) จากนั้นคุณสามารถค้นหา imageView id จากเลย์เอาต์

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

3) ส่งคืนเค้าโครงที่สูงเกินจริง

return ll;

นี่เหมือนกับคำตอบของ LeffelMania
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

ในแฟรกเมนต์เราต้องการมุมมองของหน้าต่างนั้นเพื่อให้เราสร้างมุมมองของแฟรกเมนต์นี้

จากนั้นรับมุมมองและใช้เพื่อเข้าถึงแต่ละมุมมอง id ขององค์ประกอบมุมมองนั้น

  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

เลย์เอาต์เค้าโครงมาเป็นรูปภาพที่นี่ Layout inflater เป็นคลาสที่ทำให้เราสามารถใช้มุมมอง XML ในโค้ดจาวา ดังนั้นคุณสามารถขยายมุมมองรูท 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

วิธีที่ง่ายที่สุดในการใช้สิ่งต่าง ๆ คือการใช้ butterknife โดยคุณสามารถเพิ่ม 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 ในคำสั่ง
Amit
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.