ฉันใช้ViewPager
พร้อมกับ a FragmentStatePagerAdapter
เพื่อโฮสต์แฟรกเมนต์ที่แตกต่างกันสามรายการ
- [Fragment1]
- [Fragment2]
- [Fragment3]
เมื่อฉันต้องการที่จะได้รับFragment1
จากในViewPager
FragmentActivity
ปัญหาคืออะไรและฉันจะแก้ไขได้อย่างไร
ฉันใช้ViewPager
พร้อมกับ a FragmentStatePagerAdapter
เพื่อโฮสต์แฟรกเมนต์ที่แตกต่างกันสามรายการ
เมื่อฉันต้องการที่จะได้รับFragment1
จากในViewPager
FragmentActivity
ปัญหาคืออะไรและฉันจะแก้ไขได้อย่างไร
คำตอบ:
คำตอบหลักขึ้นอยู่กับชื่อที่ถูกสร้างโดยกรอบงาน หากสิ่งนั้นเปลี่ยนแปลงไปมันจะไม่ทำงานอีกต่อไป
สิ่งที่เกี่ยวกับการแก้ปัญหานี้การเอาชนะinstantiateItem()
และdestroyItem()
ของคุณFragment(State)PagerAdapter
:
public class MyPagerAdapter extends FragmentStatePagerAdapter {
SparseArray<Fragment> registeredFragments = new SparseArray<Fragment>();
public MyPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public int getCount() {
return ...;
}
@Override
public Fragment getItem(int position) {
return MyFragment.newInstance(...);
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment fragment = (Fragment) super.instantiateItem(container, position);
registeredFragments.put(position, fragment);
return fragment;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
registeredFragments.remove(position);
super.destroyItem(container, position, object);
}
public Fragment getRegisteredFragment(int position) {
return registeredFragments.get(position);
}
}
ดูเหมือนว่าจะใช้ได้กับฉันเมื่อต้องรับมือกับ Fragments ที่มีอยู่ ชิ้นส่วนที่ยังไม่ได้รับการ instantiated จะกลับ null getRegisteredFragment
เมื่อโทร แต่ผมเคยใช้นี้มากที่สุดที่จะได้รับในปัจจุบันFragment
ออกจากViewPager
: และนี้จะไม่กลับมาadapater.getRegisteredFragment(viewPager.getCurrentItem())
null
ฉันไม่ได้ตระหนักถึงข้อเสียอื่น ๆ ของการแก้ปัญหานี้ ถ้ามีฉันอยากจะรู้
MyPagerAdapter
ถูกทำลายเนื่องจากวงจรชีวิต (เช่นการหมุน) จะไม่registerdFragments
สูญหาย การจะActivity
/ Fragment
ใช้MyPagerAdapter
ต้องบันทึกไว้ในonSaveInstanceState
แล้วต้องอัปเดตกับใหม่FragmentManager
โทษ?
getItem
จะไม่ถูกเรียกอีกครั้งเมื่อหมุน (สำหรับ frags ใด ๆ ที่สร้างขึ้นแล้ว) เนื่องจากFragmentManager
คืนสถานะของสถานะที่Fragments
เก็บไว้ในเพจเจอร์ หากinstantiateItem
มีการเรียกเมื่อแต่ละFragment
คืนมีการแก้ไขปัญหานี้ในความเป็นจริงแล้วจะปลอดภัยและพิสูจน์ได้ในอนาคตมากกว่าคำตอบที่ได้รับการยอมรับ ฉันจะลองทำเอง
สำหรับการแยกส่วนออกจาก ViewPager มีคำตอบมากมายที่นี่และในเธรด / บล็อก SO อื่น ๆ ที่เกี่ยวข้อง ทุกคนที่ฉันเห็นถูกทำลายและพวกเขามักจะตกอยู่ในหนึ่งในสองประเภทที่ระบุไว้ด้านล่าง มีบางการแก้ปัญหาที่ถูกต้องอื่น ๆ ถ้าคุณเพียงต้องการที่จะคว้าส่วนปัจจุบันเช่นนี้คำตอบอื่น ๆ ในหัวข้อนี้
ถ้าใช้FragmentPagerAdapter
ดูด้านล่าง หากใช้งานFragmentStatePagerAdapter
คุ้มค่ามองหาที่นี้ ดัชนีการโลภที่ไม่ได้เป็นดัชนีปัจจุบันใน FragmentStateAdapter นั้นไม่ได้มีประโยชน์เท่าที่เป็นไปตามธรรมชาติของมันดัชนีเหล่านี้จะถูกดึงลงอย่างสมบูรณ์โดยไม่มีการดู / ออกนอกขอบเขตของ ScreenLimit
ผิด: รักษารายการชิ้นส่วนภายในของคุณเองเพิ่มเมื่อFragmentPagerAdapter.getItem()
ถูกเรียก
SparseArray
หรือMap
getItem
เรียกว่าเฉพาะในครั้งแรกที่หน้าเว็บถูกเลื่อนไปที่ (หรือได้รับถ้าViewPager.setOffscreenPageLimit(x)
> 0) ในViewPager
หากโฮสติ้งActivity
/ Fragment
ถูกฆ่าหรือรีสตาร์ทแล้วภายในSpaseArray
จะถูกลบออกเมื่อ FragmentPagerActivity ที่กำหนดเองถูกสร้างขึ้น แต่อยู่เบื้องหลัง ชิ้นส่วนภายใน ViewPagers จะถูกสร้างขึ้นใหม่และgetItem
จะไม่ถูกเรียกสำหรับดัชนีใด ๆ ดังนั้นความสามารถในการรับแฟรกเมนต์จากดัชนีจะหายไปตลอดกาล คุณสามารถทำสิ่งนี้ได้โดยการบันทึกและเรียกคืนการอ้างอิงส่วนเหล่านี้ผ่านทางFragmentManager.getFragment()
และ putFragment
แต่สิ่งนี้เริ่มทำให้ IMHO ยุ่งผิด: สร้าง id แท็กของคุณเองที่ตรงกับสิ่งที่ใช้ภายใต้ประทุน FragmentPagerAdapter
และใช้สิ่งนี้เพื่อดึงชิ้นส่วนของหน้าจากFragmentManager
ViewPager
ที่จะทำได้ เปลี่ยนแปลงได้ตลอดเวลาหรือรุ่นระบบปฏิบัติการใด ๆวิธีการที่สร้างขึ้นใหม่สำหรับการแก้ปัญหานี้คือ
private static String makeFragmentName(int viewId, long id) {
return "android:switcher:" + viewId + ":" + id;
}
ViewPager.instantiateItem()
วิธีการที่คล้ายกับgetItem()
ข้างบน แต่ไม่ใช่วงจรการทำลายคือวิธีการนี้ที่จะขอเข้าไปinstantiateItem()
แทนที่แทนที่จะgetItem()
เป็นแบบเก่าจะถูกเรียกทุกครั้งที่มีการสร้าง / เข้าถึงดัชนี ดูคำตอบนี้
FragmentViewPager
สร้างFragmentViewPager
คลาสของคุณเองจากซอร์สของ lib การสนับสนุนล่าสุดและเปลี่ยนวิธีที่ใช้ภายในเพื่อสร้างแท็กแฟรกเมนต์ คุณสามารถแทนที่ด้วยด้านล่าง นี่เป็นข้อดีที่คุณรู้ว่าการสร้างแท็กจะไม่มีวันเปลี่ยนแปลงและคุณไม่ได้ใช้วิธีการส่วนตัว / ซึ่งเป็นอันตรายเสมอ
/**
* @param containerViewId the ViewPager this adapter is being supplied to
* @param id pass in getItemId(position) as this is whats used internally in this class
* @return the tag used for this pages fragment
*/
public static String makeFragmentName(int containerViewId, long id) {
return "android:switcher:" + containerViewId + ":" + id;
}
จากนั้นตามที่หมอบอกว่าเมื่อคุณต้องการที่จะดึงส่วนที่ใช้สำหรับดัชนีให้เรียกสิ่งที่เรียกว่าวิธีนี้ (ซึ่งคุณสามารถใส่ใน custom FragmentPagerAdapter
หรือ subclass) เพื่อทราบว่าผลลัพธ์อาจเป็นโมฆะหาก getItem ยังไม่ได้ถูกเรียกใช้ นั่นคือหน้านั้นยังไม่ได้ถูกสร้างขึ้น
/**
* @return may return null if the fragment has not been instantiated yet for that position - this depends on if the fragment has been viewed
* yet OR is a sibling covered by {@link android.support.v4.view.ViewPager#setOffscreenPageLimit(int)}. Can use this to call methods on
* the current positions fragment.
*/
public @Nullable Fragment getFragmentForPosition(int position)
{
String tag = makeFragmentName(mViewPager.getId(), getItemId(position));
Fragment fragment = getSupportFragmentManager().findFragmentByTag(tag);
return fragment;
}
นี่เป็นวิธีแก้ไขปัญหาที่ง่ายและแก้ไขปัญหาในอีกสองโซลูชันที่พบได้ทุกที่บนเว็บ
instantiateItem()
ซึ่งเป็นเวลาที่คุณต้องการเข้าถึงชิ้นส่วนที่ยังไม่ได้เข้าเยี่ยมชมหลังจากเหตุการณ์รอบการทำงานเกิดขึ้นและมีการเยี่ยมชมก่อนเหตุการณ์รอบการทำงาน ความแตกต่างเล็กน้อยที่ฉันรู้ แต่เป็นสิ่งที่นำไปสู่ข้อบกพร่องที่ละเอียดอ่อนในโปรแกรมของฉันดังนั้นฉันจึงดูในเรื่องนี้
getItemId(pos)
อยู่ภายในFragmentStatePagerAdapter
เพิ่มวิธีถัดไปใน FragmentPagerAdapter ของคุณ:
public Fragment getActiveFragment(ViewPager container, int position) {
String name = makeFragmentName(container.getId(), position);
return mFragmentManager.findFragmentByTag(name);
}
private static String makeFragmentName(int viewId, int index) {
return "android:switcher:" + viewId + ":" + index;
}
getActiveFragment (0) ต้องทำงาน
นี่เป็นวิธีการดำเนินการใน ViewPager https://gist.github.com/jacek-marchwicki/d6320ba9a910c514424d หากสิ่งที่ล้มเหลวคุณจะเห็นบันทึกการชนที่ดี
อีกวิธีง่ายๆ:
public class MyPagerAdapter extends FragmentPagerAdapter {
private Fragment mCurrentFragment;
public Fragment getCurrentFragment() {
return mCurrentFragment;
}
//...
@Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
if (getCurrentFragment() != object) {
mCurrentFragment = ((Fragment) object);
}
super.setPrimaryItem(container, position, object);
}
}
setPrimaryItem()
เรียกหลังจาก ViewPager.OnPageChangeListener#onPageSelected()
ฉันไม่สามารถใช้ :-(
ฉันรู้ว่านี่มีคำตอบไม่กี่ข้อ แต่อาจช่วยคนได้ ฉันได้ใช้วิธีการแก้ปัญหาที่ค่อนข้างง่ายเมื่อฉันต้องการที่จะได้รับจากฉันFragment
ViewPager
ในActivity
หรือFragment
ถือของViewPager
คุณคุณสามารถใช้รหัสนี้เพื่อวนรอบทุก ๆFragment
มัน
FragmentPagerAdapter fragmentPagerAdapter = (FragmentPagerAdapter) mViewPager.getAdapter();
for(int i = 0; i < fragmentPagerAdapter.getCount(); i++) {
Fragment viewPagerFragment = fragmentPagerAdapter.getItem(i);
if(viewPagerFragment != null) {
// Do something with your Fragment
// Check viewPagerFragment.isResumed() if you intend on interacting with any views.
}
}
ถ้าคุณรู้ว่าตำแหน่งของคุณFragment
ในคุณก็สามารถโทรViewPager
getItem(knownPosition)
หากคุณไม่ทราบตำแหน่งของคุณFragment
ในViewPager
คุณสามารถมีบุตรหลานของคุณFragments
ใช้อินเตอร์เฟซด้วยวิธีการเช่นเดียวกับที่ใช้งานgetUniqueId()
และการใช้งานที่แตกต่าง หรือคุณสามารถวนรอบทั้งหมดFragments
และตรวจสอบประเภทของคลาสเช่นif(viewPagerFragment instanceof FragmentClassYouWant)
!!! แก้ไข !!!
ฉันได้ค้นพบว่าgetItem
เพียงได้รับการเรียกโดยFragmentPagerAdapter
เมื่อแต่ละFragment
ความต้องการที่จะสร้างเป็นครั้งแรกหลังจากนั้นก็จะปรากฏขึ้นที่จะนำกลับมาใช้Fragments
FragmentManager
วิธีนี้ใช้งานหลายFragmentPagerAdapter
สร้างใหม่ ในFragment
getItem
โดยใช้วิธีการดังกล่าวข้างต้นของฉันที่นี้หมายถึงเราจะสร้างใหม่Fragment
s ในแต่ละครั้งจะเรียกว่าเป็นเราผ่านรายการทั้งหมดในgetItem
FragmentPagerAdapter
ด้วยเหตุนี้ฉันจึงพบวิธีที่ดีกว่าโดยใช้การFragmentManager
รับเพื่อFragment
แทน (ใช้คำตอบที่ยอมรับ) นี่เป็นวิธีการแก้ปัญหาที่สมบูรณ์มากขึ้นและทำงานได้ดีสำหรับฉัน
FragmentPagerAdapter fragmentPagerAdapter = (FragmentPagerAdapter) mViewPager.getAdapter();
for(int i = 0; i < fragmentPagerAdapter.getCount(); i++) {
String name = makeFragmentName(mViewPager.getId(), i);
Fragment viewPagerFragment = getChildFragmentManager().findFragmentByTag(name);
// OR Fragment viewPagerFragment = getFragmentManager().findFragmentByTag(name);
if(viewPagerFragment != null) {
// Do something with your Fragment
if (viewPagerFragment.isResumed()) {
// Interact with any views/data that must be alive
}
else {
// Flag something for update later, when this viewPagerFragment
// returns to onResume
}
}
}
และคุณจะต้องใช้วิธีนี้
private static String makeFragmentName(int viewId, int position) {
return "android:switcher:" + viewId + ":" + position;
}
ViewPager
ตัวเองตั้งแท็กเหล่านั้น การแก้ปัญหานี้จะเปราะบางเพราะอาศัยการรู้ "ซ่อน" ViewPager
ตั้งชื่อการประชุมของ คำตอบของ Streets of Boston เป็นคำตอบที่ครอบคลุมมากขึ้นซึ่งตอนนี้ฉันใช้ในโครงการของฉัน (แทนที่จะเป็นวิธีนี้)
สำหรับกรณีของฉันไม่มีวิธีการแก้ปัญหาข้างต้นทำงาน
อย่างไรก็ตามเนื่องจากฉันใช้ Child Fragment Manager ใน Fragment จึงมีการใช้สิ่งต่อไปนี้:
Fragment f = getChildFragmentManager().getFragments().get(viewPager.getCurrentItem());
สิ่งนี้จะใช้ได้เฉพาะในกรณีที่แฟรกเมนต์ของคุณในตัวจัดการสอดคล้องกับไอเท็มวิวเพจ
เพื่อให้ได้รับส่วนที่มองเห็นได้ในปัจจุบันจาก ViewPager ฉันใช้คำสั่งง่ายๆนี้และมันใช้ได้ดี
public Fragment getFragmentFromViewpager()
{
return ((Fragment) (mAdapter.instantiateItem(mViewPager, mViewPager.getCurrentItem())));
}
ฉันจัดการโดยทำรายการชิ้นส่วนทั้งหมดก่อนList<Fragment> fragments;
) ที่ฉันจะใช้จากนั้นเพิ่มมันลงในเพจเจอร์เพื่อให้ง่ายต่อการจัดการกับแฟรกเมนต์ที่ดูอยู่ในปัจจุบัน
ดังนั้น:
@Override
onCreate(){
//initialise the list of fragments
fragments = new Vector<Fragment>();
//fill up the list with out fragments
fragments.add(Fragment.instantiate(this, MainFragment.class.getName()));
fragments.add(Fragment.instantiate(this, MenuFragment.class.getName()));
fragments.add(Fragment.instantiate(this, StoresFragment.class.getName()));
fragments.add(Fragment.instantiate(this, AboutFragment.class.getName()));
fragments.add(Fragment.instantiate(this, ContactFragment.class.getName()));
//Set up the pager
pager = (ViewPager)findViewById(R.id.pager);
pager.setAdapter(new MyFragmentPagerAdapter(getSupportFragmentManager(), fragments));
pager.setOffscreenPageLimit(4);
}
ดังนั้นสิ่งนี้จึงถูกเรียกว่า:
public Fragment getFragment(ViewPager pager){
Fragment theFragment = fragments.get(pager.getCurrentItem());
return theFragment;
}
ดังนั้นฉันสามารถโยนมันในคำสั่ง if ที่จะทำงานเฉพาะถ้ามันอยู่ในส่วนที่ถูกต้อง
Fragment tempFragment = getFragment();
if(tempFragment == MyFragmentNo2.class){
MyFragmentNo2 theFrag = (MyFragmentNo2) tempFragment;
//then you can do whatever with the fragment
theFrag.costomFunction();
}
แต่นั่นเป็นเพียงวิธีการแฮ็คและสแลชของฉัน แต่มันใช้งานได้สำหรับฉันฉันใช้มันทำการเปลี่ยนแปลงที่เกี่ยวข้องกับส่วนที่แสดงในปัจจุบันของฉันเมื่อกดปุ่มย้อนกลับ
นี่เป็นไปตามคำตอบของสตีเว่นข้างต้น นี่จะส่งคืนอินสแตนซ์จริงของแฟรกเมนต์ที่แนบกับกิจกรรมพาเรนต์แล้ว
FragmentPagerAdapter fragmentPagerAdapter = (FragmentPagerAdapter) mViewPager.getAdapter();
for(int i = 0; i < fragmentPagerAdapter.getCount(); i++) {
Fragment viewPagerFragment = (Fragment) mViewPager.getAdapter().instantiateItem(mViewPager, i);
if(viewPagerFragment != null && viewPagerFragment.isAdded()) {
if (viewPagerFragment instanceof FragmentOne){
FragmentOne oneFragment = (FragmentOne) viewPagerFragment;
if (oneFragment != null){
oneFragment.update(); // your custom method
}
} else if (viewPagerFragment instanceof FragmentTwo){
FragmentTwo twoFragment = (FragmentTwo) viewPagerFragment;
if (twoFragment != null){
twoFragment.update(); // your custom method
}
}
}
}
ฉันไม่สามารถหาวิธีที่ง่ายและสะอาดในการทำสิ่งนี้ อย่างไรก็ตามวิดเจ็ต ViewPager เป็นอีกหนึ่ง ViewGroup ซึ่งโฮสต์แฟรกเมนต์ของคุณ ViewPager มีแฟรกเมนต์เหล่านี้ในฐานะลูก ๆ ดังนั้นคุณสามารถทำซ้ำได้มากกว่าพวกเขา (โดยใช้. getChildCount () และ. getChildAt ()) และดูว่าอินสแตนซ์ส่วนที่คุณกำลังค้นหานั้นโหลดเข้ามาใน ViewPager หรือไม่และได้รับการอ้างอิง เช่นคุณสามารถใช้ฟิลด์ ID คงที่ที่ไม่ซ้ำกันเพื่อแยกส่วนย่อย
โปรดทราบว่า ViewPager อาจไม่ได้โหลดส่วนที่คุณกำลังมองหาเพราะมันเป็นคอนเทนเนอร์เสมือนจริงเช่น ListView
FragmentPagerAdapter เป็นแฟรกเมนต์ของแฟรกเมนต์ หากต้องการค้นหาแฟรกเมนต์ตามตำแหน่งหากยังอยู่ในหน่วยความจำให้ใช้สิ่งนี้:
public Fragment findFragmentByPosition(int position) {
FragmentPagerAdapter fragmentPagerAdapter = getFragmentPagerAdapter();
return getSupportFragmentManager().findFragmentByTag(
"android:switcher:" + getViewPager().getId() + ":"
+ fragmentPagerAdapter.getItemId(position));
}
โค้ดตัวอย่างสำหรับ v4 support api
คุณไม่จำเป็นต้องโทรgetItem()
หรือวิธีอื่น ๆ ในขั้นตอนต่อมาจะได้รับการอ้างอิงของการเป็นเจ้าภาพภายในFragment
ViewPager
หากคุณต้องการอัปเดตข้อมูลภายในให้Fragment
ใช้วิธีนี้:อัปเดต ViewPager แบบไดนามิกหรือไม่
กุญแจคือการตั้งค่าข้อมูลใหม่ภายในAdaper
และโทรnotifyDataSetChanged()
ที่จะโทรgetItemPosition()
ผ่านการอ้างอิงของคุณFragment
และให้โอกาสคุณอัปเดต วิธีอื่นทั้งหมดกำหนดให้คุณต้องอ้างอิงถึงตัวคุณเองหรือแฮ็คอื่น ๆ ซึ่งไม่ใช่วิธีแก้ปัญหาที่ดี
@Override
public int getItemPosition(Object object) {
if (object instanceof UpdateableFragment) {
((UpdateableFragment) object).update(xyzData);
}
//don't return POSITION_NONE, avoid fragment recreation.
return super.getItemPosition(object);
}
getItemPosition()
เป็นวิธีในอะแดปเตอร์ของคุณ คุณจะไม่เรียกมันโดยตรง คุณมีการอ้างอิงของอะแดปเตอร์ของคุณเพื่อให้คุณโทรadapter.notifyDataSetChanged()
ซึ่งจะเรียกgetItemPosition()
ของอะแดปเตอร์ของคุณโดยผ่านการอ้างอิงของคุณFragment
s คุณสามารถเห็นการใช้งานเต็มรูปแบบได้ที่นี่stackoverflow.com/questions/19891828/…
Fragment
วิธีการรับการอ้างอิงนั้นสามารถอภิปรายได้ วิธีแก้ไขปัญหาอื่น ๆ ได้รับการอ้างอิงจากการFragmentManager
ใช้สตริงที่คล้าย "android:switcher:"+id
หรือย้อนกลับPOSITION_NONE
จากการgetItemosition()
ทำให้ชิ้นส่วนทั้งหมดสร้างขึ้นใหม่
ต้องขยายไปFragmentPagerAdapter
สู่คลาสอะแดปเตอร์ ViewPager ของคุณ
ถ้าคุณใช้FragmentStatePagerAdapter
แล้วคุณจะไม่สามารถที่จะหาคุณFragment
โดยตัวของมันID
public static String makeFragmentName(int viewPagerId, int index) {
return "android:switcher:" + viewPagerId + ":" + index;
}
วิธีใช้วิธีนี้: -
Fragment mFragment = ((FragmentActivity) getContext()).getSupportFragmentManager().findFragmentByTag(
AppMethodUtils.makeFragmentName(mViewPager.getId(), i)
);
InterestViewFragment newFragment = (InterestViewFragment) mFragment;
ทางออกที่ดีที่สุดคือการใช้ส่วนขยายที่เราสร้างขึ้นในCodePathเรียกSmartFragmentStatePagerAdapter การปฏิบัติตามคำแนะนำดังกล่าวทำให้การดึงข้อมูลชิ้นส่วนและชิ้นส่วนที่เลือกในปัจจุบันจาก ViewPager ง่ายขึ้นอย่างมาก นอกจากนี้ยังทำงานได้ดีขึ้นในการจัดการหน่วยความจำของชิ้นส่วนที่ฝังอยู่ภายในอะแดปเตอร์
วิธีที่ง่ายที่สุดและรัดกุมที่สุด หากแฟรกเมนต์ทั้งหมดของคุณอยู่ในViewPager
คลาสที่แตกต่างกันคุณสามารถดึงและแยกแยะได้ดังต่อไปนี้:
public class MyActivity extends Activity
{
@Override
public void onAttachFragment(Fragment fragment) {
super.onAttachFragment(fragment);
if (fragment.getClass() == MyFragment.class) {
mMyFragment = (MyFragment) fragment;
}
}
}
ฉันใช้สิ่งนี้ง่ายด้วยวิธีที่แตกต่างกันเล็กน้อย
FragmentAdapter.getItem แบบกำหนดเองของฉันไม่ได้ส่งคืน MyFragment () ใหม่ แต่เป็นอินสแตนซ์ของ MyFragment ที่สร้างขึ้นในตัวสร้าง FragmentAdapter
ในกิจกรรมของฉันฉันได้รับชิ้นส่วนจากอะแดปเตอร์ตรวจสอบว่าเป็นอินสแตนซ์ของ Fragment ที่จำเป็นหรือไม่จากนั้นใช้วิธีการที่จำเป็น
สร้าง id ทรัพยากรจำนวนเต็มใน /values/integers.xml
<integer name="page1">1</integer>
<integer name="page2">2</integer>
<integer name="page3">3</integer>
จากนั้นในฟังก์ชัน PagerAdapter getItem:
public Fragment getItem(int position) {
Fragment fragment = null;
if (position == 0) {
fragment = FragmentOne.newInstance();
mViewPager.setTag(R.integer.page1,fragment);
}
else if (position == 1) {
fragment = FragmentTwo.newInstance();
mViewPager.setTag(R.integer.page2,fragment);
} else if (position == 2) {
fragment = FragmentThree.newInstance();
mViewPager.setTag(R.integer.page3,fragment);
}
return fragment;
}
จากนั้นในกิจกรรมให้เขียนฟังก์ชันนี้เพื่อรับการอ้างอิงชิ้นส่วน:
private Fragment getFragmentByPosition(int position) {
Fragment fragment = null;
switch (position) {
case 0:
fragment = (Fragment) mViewPager.getTag(R.integer.page1);
break;
case 1:
fragment = (Fragment) mViewPager.getTag(R.integer.page2);
break;
case 2:
fragment = (Fragment) mViewPager.getTag(R.integer.page3);
break;
}
return fragment;
}
รับการอ้างอิงชิ้นส่วนโดยการเรียกใช้ฟังก์ชั่นด้านบนแล้วส่งไปยังส่วนที่กำหนดเองของคุณ:
Fragment fragment = getFragmentByPosition(position);
if (fragment != null) {
FragmentOne fragmentOne = (FragmentOne) fragment;
}
วิธีง่ายๆในการวนซ้ำในตัวจัดการส่วนย่อย ค้นหา viewpager ที่มีการโต้แย้งตำแหน่งส่วนที่วางไว้ใน สาธารณะคง PlaceholderFragment newInstance (int sectionNumber)
public PlaceholderFragment getFragmentByPosition(Integer pos){
for(Fragment f:getChildFragmentManager().getFragments()){
if(f.getId()==R.id.viewpager && f.getArguments().getInt("SECTNUM") - 1 == pos) {
return (PlaceholderFragment) f;
}
}
return null;
}
ในส่วน
public int getArgument(){
return mPage;
{
public void update(){
}
ใน FragmentActivity
List<Fragment> fragments = getSupportFragmentManager().getFragments();
for(Fragment f:fragments){
if((f instanceof PageFragment)&&(!f.isDetached())){
PageFragment pf = (PageFragment)f;
if(pf.getArgument()==pager.getCurrentItem())pf.update();
}
}
ใน TabLayout มีหลายแท็บสำหรับ Fragment คุณสามารถค้นหาชิ้นส่วนด้วยแท็กโดยใช้ดัชนีของส่วน
สำหรับอดีต ดัชนีสำหรับ Fragment1 คือ 0 ดังนั้นในfindFragmentByTag()
วิธีการส่งแท็กสำหรับ Viewpager หลังจากใช้ fragmentTransaction คุณสามารถเพิ่มเปลี่ยนชิ้นส่วน
String tag = "android:switcher:" + R.id.viewPager + ":" + 0;
Fragment1 f = (Fragment1) getSupportFragmentManager().findFragmentByTag(tag);
ตกลงสำหรับอะแดปเตอร์ FragmentStatePagerAdapter
ฉันแก้ปัญหากองทุน:
ใน FragmentActivity ของคุณ:
ActionBar mActionBar = getSupportActionBar();
mActionBar.addTab(mActionBar.newTab().setText("TAB1").setTabListener(this).setTag(Fragment.instantiate(this, MyFragment1.class.getName())));
mActionBar.addTab(mActionBar.newTab().setText("TAB2").setTabListener(this).setTag(Fragment.instantiate(this, MyFragment2.class.getName())));
mActionBar.addTab(mActionBar.newTab().setText("TAB3").setTabListener(this).setTag(Fragment.instantiate(this, MyFragment3.class.getName())));
viewPager = (STViewPager) super.findViewById(R.id.viewpager);
mPagerAdapter = new MyPagerAdapter(getSupportFragmentManager(), mActionBar);
viewPager.setAdapter(this.mPagerAdapter);
และสร้าง methode ในชั้นเรียนของคุณ FragmentActivity - ดังนั้นวิธีการที่ให้คุณเข้าถึง Fragment ของคุณคุณเพียงแค่ต้องให้มันอยู่ในตำแหน่งของชิ้นส่วนที่คุณต้องการ:
public Fragment getActiveFragment(int position) {
String name = MyPagerAdapter.makeFragmentName(position);
return getSupportFragmentManager().findFragmentByTag(name);
}
ในอะแดปเตอร์ของคุณ:
public class MyPagerAdapter extends FragmentStatePagerAdapter {
private final ActionBar actionBar;
private final FragmentManager fragmentManager;
public MyPagerAdapter(FragmentManager fragmentManager, com.actionbarsherlock.app.ActionBarActionBar mActionBar) {super(fragmentManager);
this.actionBar = mActionBar;
this.fragmentManager = fragmentManager;
}
@Override
public Fragment getItem(int position) {
getSupportFragmentManager().beginTransaction().add(mTchatDetailsFragment, makeFragmentName(position)).commit();
return (Fragment)this.actionBar.getTabAt(position);
}
@Override
public int getCount() {
return this.actionBar.getTabCount();
}
@Override
public CharSequence getPageTitle(int position) {
return this.actionBar.getTabAt(position).getText();
}
private static String makeFragmentName(int viewId, int index) {
return "android:fragment:" + index;
}
}
Fragment yourFragment = yourviewpageradapter.getItem(int index);
index
เป็นสถานที่ของแฟรกเมนต์ในอะแด็ปเตอร์เหมือนกับที่คุณเพิ่มfragment1
ก่อนดังนั้น retreive fragment1
pass index
เป็น 0 และอื่น ๆ สำหรับการพักผ่อน
Fragment
ในWeakReference
เพื่อรับประกันว่าคุณจะไม่ป้องกันชิ้นส่วนที่ถูกทำลายจากการถูกเก็บขยะ? ก็ดูเหมือนว่าสิ่งที่ถูกต้องที่จะทำ ...