Di bawah ini adalah kode saya yang 3 Fragment classes
masing-masing tertanam dengan masing-masing 3 tab ViewPager
. Saya punya opsi menu. Seperti ditunjukkan dalam onOptionsItemSelected()
, dengan memilih opsi, saya perlu memperbarui fragmen yang saat ini terlihat. Untuk memperbarui itu saya harus memanggil metode yang ada di kelas fragmen. Bisakah seseorang menyarankan cara memanggil metode itu?
public class MainActivity extends ActionBarActivity {
ViewPager ViewPager;
TabsAdapter TabsAdapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ViewPager = new ViewPager(this);
ViewPager.setId(R.id.pager);
setContentView(ViewPager);
final ActionBar bar = getSupportActionBar();
bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
//Attaching the Tabs to the fragment classes and setting the tab title.
TabsAdapter = new TabsAdapter(this, ViewPager);
TabsAdapter.addTab(bar.newTab().setText("FragmentClass1"),
FragmentClass1.class, null);
TabsAdapter.addTab(bar.newTab().setText("FragmentClass2"),
FragmentClass2.class, null);
TabsAdapter.addTab(bar.newTab().setText("FragmentClass3"),
FragmentClass3.class, null);
if (savedInstanceState != null) {
bar.setSelectedNavigationItem(savedInstanceState.getInt("tab", 0));
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.addText:
**// Here I need to call the method which exists in the currently visible Fragment class**
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("tab", getSupportActionBar().getSelectedNavigationIndex());
}
public static class TabsAdapter extends FragmentPagerAdapter
implements ActionBar.TabListener, ViewPager.OnPageChangeListener {
private final Context mContext;
private final ActionBar mActionBar;
private final ViewPager mViewPager;
private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
static final class TabInfo {
private final Class<?> clss;
private final Bundle args;
TabInfo(Class<?> _class, Bundle _args) {
clss = _class;
args = _args;
}
}
public TabsAdapter(ActionBarActivity activity, ViewPager pager) {
super(activity.getSupportFragmentManager());
mContext = activity;
mActionBar = activity.getSupportActionBar();
mViewPager = pager;
mViewPager.setAdapter(this);
mViewPager.setOnPageChangeListener(this);
}
public void addTab(ActionBar.Tab tab, Class<?> clss, Bundle args) {
TabInfo info = new TabInfo(clss, args);
tab.setTag(info);
tab.setTabListener(this);
mTabs.add(info);
mActionBar.addTab(tab);
notifyDataSetChanged();
}
@Override
public void onPageScrollStateChanged(int state) {
// TODO Auto-generated method stub
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
// TODO Auto-generated method stub
}
@Override
public void onPageSelected(int position) {
// TODO Auto-generated method stub
mActionBar.setSelectedNavigationItem(position);
}
@Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
}
@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
Object tag = tab.getTag();
for (int i=0; i<mTabs.size(); i++) {
if (mTabs.get(i) == tag) {
mViewPager.setCurrentItem(i);
}
}
tabPosition = tab.getPosition();
}
@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
}
@Override
public Fragment getItem(int position) {
TabInfo info = mTabs.get(position);
return Fragment.instantiate(mContext, info.clss.getName(), info.args);
}
@Override
public int getCount() {
return mTabs.size();
}
}
}
Misalkan di bawah ini adalah kelas fragmen dengan metode yang updateList()
ingin saya panggil:
public class FragmentClass1{
ArrayList<String> originalData;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View fragmentView = inflater.inflate(R.layout.frag1, container, false);
originalData = getOriginalDataFromDB();
return fragmentView;
}
public void updateList(String text)
{
originalData.add(text);
//Here I could do other UI part that need to added
}
}
Jawaban:
Cara sederhana untuk melakukan ini adalah menggunakan trik yang terkait dengan
FragmentPagerAdapter
implementasi:Pikirkan kembali konvensi penamaan variabel Anda, gunakan sebagai nama variabel, nama kelas sangat membingungkan (jadi tidak
ViewPager ViewPager
, gunakanViewPager mPager
misalnya).sumber
instantiateItem()
metode dan mendapatkan referensi ke fragmen yang tepat.mAdapter.getItem(position)
, luar biasa ... Setidaknya sekarang saya tahu bahwa 8512 percobaan lain tidak berhasil. Terima kasihsumber
onPageSelected
/onPageDeselected
dan memiliki semua fragmen halaman saya memperpanjangnya. KemudiansetPrimaryitem
dapat memanggil metode ini dengan tepat ketika pengguna menggesek ke halaman baru. Ini berarti Anda dapat menerapkan strategi malas untuk memuat data di halaman yang bahkan tidak ditampilkan. Namun Anda harus ingat bahwa selama transisi halaman terlihat lebih baik jika halaman berikutnya sudah diisi dengan data, jadi malas memuat semua dataonPageSelected
mungkin tidak ideal.if
pernyataan itu? Fragmen hanya memanggilequals
metode objek, yang merupakan perbandingan dangkal. Jadi mengapa tidak selalu meneleponmCurrentFragment = ((Fragment) object);
?Pertama-tama, perhatikan semua halaman fragmen "aktif". Dalam hal ini, Anda melacak halaman fragmen di FragmentStatePagerAdapter, yang digunakan oleh ViewPager.
Untuk menghindari menyimpan referensi ke halaman fragmen "tidak aktif", Anda perlu menerapkan metode destroyItem (...) dari FragmentStatePagerAdapter:
dan ketika Anda perlu mengakses halaman yang terlihat saat ini, Anda kemudian memanggil:
Di mana metode getFragment (int) MyAdapter terlihat seperti ini:
Semoga bisa membantu!
sumber
Ini adalah satu-satunya cara saya tidak mendapatkan NullPointerException untuk variabel instan dari kelas fragmen tertentu. Ini mungkin bermanfaat bagi orang lain yang terjebak pada hal yang sama. Dalam onOptionsItemSelected (), saya memberi kode cara di bawah ini:
sumber
FragmentStatePagerAdapter
tanpa mengesampingkan kode apa pun. Bahkan, itu harus sesederhana fungsi hanya kembaliviewPager.getAdapter().instantiateItem(viewPager, viewPager.getCurrentItem())
.FragmentStatePagerAdapter memiliki metode publik dengan nama instantiateItem yang mengembalikan fragmen Anda berdasarkan nilai parameter yang ditentukan, metode ini memiliki dua parameter, ViewGroup (ViewPager), dan posisi.
Menggunakan metode ini untuk mendapatkan fragmen posisi yang ditentukan,
sumber
Saya tahu ini sudah terlambat tetapi saya memiliki cara yang sangat sederhana untuk melakukannya,
// untuk fragmen dengan kepemilikan 0
sumber
Ada banyak jawaban di sini yang tidak benar-benar membahas fakta dasar bahwa benar-benar TIDAK ADA CARA untuk melakukan hal ini dengan cara yang dapat diduga, dan dengan cara yang tidak menghasilkan Anda menembak diri sendiri di beberapa titik di masa depan.
FragmentStatePagerAdapter
adalah satu-satunya kelas yang tahu cara mengakses fragmen yang dapat dipercaya dengan dilacak olehFragmentManager
- setiap upaya untuk mencoba dan menebak id atau tag fragmen tidak dapat diandalkan, jangka panjang. Dan upaya untuk melacak instances secara manual kemungkinan tidak akan berfungsi dengan baik ketika state disimpan / dipulihkan, karenaFragmentStatePagerAdapter
mungkin tidak akan memanggil callback ketika mengembalikan state.Satu-satunya hal yang saya dapat lakukan adalah menyalin kode
FragmentStatePagerAdapter
dan menambahkan metode yang mengembalikan fragmen, diberi posisi (mFragments.get(pos)
). Perhatikan bahwa metode ini mengasumsikan bahwa fragmen sebenarnya tersedia (yaitu terlihat pada beberapa titik).Jika Anda sangat berjiwa petualang, Anda dapat menggunakan refleksi untuk mengakses elemen
mFragments
daftar pribadi , tetapi kemudian kami kembali ke titik awal (nama daftar tidak dijamin tetap sama).sumber
Keluarkan instance yang diambil dari baris di atas ke fragmen yang ingin Anda kerjakan. Bekerja dengan sangat baik.
adalah contoh pager yang mengelola fragmen.
sumber
Untuk mendapatkan referensi ke fragmen yang terlihat saat ini, anggap Anda memiliki referensi
ViewPager
sebagaimPager
. Maka langkah-langkah berikut akan mendapatkan referensi kecurrentFragment
:PageAdapter adapter = mPager.getAdapter();
int fragmentIndex = mPager.getCurrentItem();
FragmentStatePagerAdapter fspa = (FragmentStatePagerAdapter)adapter;
Fragment currentFragment = fspa.getItem(fragmentIndex);
Satu-satunya pemain yang digunakan baris 3 biasanya valid.
FragmentStatePagerAdapter
adalah adaptor yang berguna untuk ViewPager.sumber
Cara terbaik untuk melakukan ini, cukup panggil CallingFragmentName fragment = (CallingFragmentName) viewPager .getAdapter () .instantiateItem (viewPager, viewPager, viewPager.getCurrentItem ()); Ini akan instantiate fragmen panggilan Anda, sehingga tidak akan membuang null pointer exception dan memanggil metode apa pun dari fragmen itu.
sumber
Fragmen saat ini:
Ini berfungsi jika Anda membuat proyek dengan templat tabbar fragmen.
Perhatikan bahwa ini berfungsi dengan implementasi templat aktivitas tab yang standar.
sumber
Saya telah menggunakan yang berikut ini:
sumber
FragmentStatePagerAdapter
memiliki variabel instance pribadi yang disebutmCurrentPrimaryItem
tipeFragment
. Orang hanya bisa bertanya-tanya mengapa Android devs tidak menyediakannya dengan pengambil. Variabel ini dipakai dalamsetPrimaryItem()
metode. Jadi, timpa metode ini sedemikian rupa agar Anda mendapatkan referensi ke variabel ini. Saya hanya berakhir dengan menyatakan milik sayamCurrentPrimaryItem
dan menyalin kontensetPrimaryItem()
untuk menimpa saya.Dalam implementasi Anda
FragmentStatePagerAdapter
:sumber
Anda dapat menentukan
PagerAdapter
seperti ini maka Anda akan bisa mendapatkanFragment
diViewPager
.Untuk mendapatkan arus
Fragment
sumber
Ketika kita menggunakan viewPager, cara yang baik untuk mengakses instance fragmen dalam aktivitas adalah instantiateItem (viewpager, index). // indeks- indeks fragmen yang Anda inginkan misalnya.
misalnya saya mengakses contoh fragmen dari 1 index-
sumber
Dalam implementasi saya sebelumnya, saya menyimpan daftar Fragmen anak untuk dapat mengaksesnya nanti, tetapi ini ternyata implementasi yang salah yang menyebabkan kebocoran memori yang sangat besar.
Saya akhirnya menggunakan
instantiateItem(...)
metode untuk mendapatkan Fragmen saat ini:Atau untuk mendapatkan Fragmen lain di posisi:
Dari dokumentasi :
sumber
Saya memiliki masalah yang sama dan menyelesaikannya menggunakan kode ini.
Cukup ganti nama MyFragment dengan nama fragmen Anda dan tambahkan id wadah fragmen Anda.
sumber
Ini lebih banyak bukti di masa depan daripada jawaban yang diterima:
sumber
Skenario yang dipermasalahkan lebih baik dilayani oleh masing-masing Fragmen menambahkan item menu sendiri dan secara langsung menangani onOptionsItemSelected (), seperti yang dijelaskan dalam dokumentasi resmi . Lebih baik menghindari trik yang tidak berdokumen.
sumber
ViewPager
masalah?Setelah membaca semua komentar dan jawaban saya akan menjelaskan solusi optimal untuk masalah ini. Pilihan terbaik adalah solusi @ rik, jadi peningkatan saya didasarkan pada miliknya.
Daripada harus meminta setiap FragmentClass suka
Buat antarmuka Anda sendiri, dan buat fragmen anak Anda menerapkannya, seperti
Kemudian, Anda dapat melakukan sesuatu seperti ini untuk memulai dan memperbarui fragmen batin Anda.
PS Hati-hati di mana Anda meletakkan kode itu, jika Anda memanggil insatiateItem sebelum sistem benar-benar membuatnya,
savedInstanceState
fragmen anak Anda akan menjadi nol karenanyaAkan merusak aplikasi Anda.
Semoga berhasil
sumber
Berdasarkan apa yang dia jawab @chahat jain:
"Ketika kita menggunakan viewPager, cara yang baik untuk mengakses instance fragmen dalam aktivitas adalah instantiateItem (viewpager, index). // indeks-indeks fragmen yang Anda inginkan instance."
Jika Anda ingin melakukannya di kotlin
0 ke instance fragmen 0
// ================================================ ========================= // // ##################### ######## Contoh penggunaan ############################### // // == ================================================== ===================== //
Berikut adalah contoh lengkap untuk mendapatkan visi yang kalah tentang
di sini adalah veiewPager saya dalam file .xml
Dan aktivitas rumah di mana saya memasukkan tab
sumber
Dalam Aktivitas saya, saya memiliki:
sumber
Kadang-kadang fragmen dapat mengirim objek nol, sehingga Anda bisa menjalankan Runnable baru untuk menyelesaikan masalah saat memuat pertama.
Terima kasih, Rick
sumber
Mengganti setPrimaryItem dari FragmentPagerAdapter Anda: objek adalah fragmen yang terlihat:
sumber
Cukup dapatkan item saat ini dari pager dan kemudian tanyakan adaptor Anda ke fragmen posisi itu.
sumber
getItem
menciptakan contoh baruUntuk mendapatkan fragmen saat ini - dapatkan posisi di ViewPager di public void onPageSelected (posisi int final) , lalu
SECTNUM - argumen posisi yang ditetapkan dalam PlaceStaceFragment public static baruInstance (int sectionNumber); dari Fragmen
getChildFragmentManager () atau getFragmentManager () - tergantung pada cara membuat SectionsPagerAdapter
sumber
Anda dapat menerapkan BroadcastReceiver di Fragmen dan mengirim Intent dari mana saja. Penerima fragmen dapat mendengarkan tindakan spesifik dan memanggil metode instance.
Satu peringatan adalah memastikan komponen View sudah dipakai dan (dan untuk beberapa operasi, seperti menggulir daftar, ListView harus sudah dirender).
sumber
Ini adalah retas paling sederhana:
(kode kotlin)
Panggil saja
instantiateItem(viewPager, viewPager.getCurrentItem()
dan masukkan keFragment
. Item Anda sudah akan dipakai. Untuk memastikan Anda bisa menambahkan cekgetCount
.Bekerja dengan keduanya
FragmentPagerAdapter
danFragmentStatePagerAdapter
!sumber
Jika pager Anda ada di dalam Fragmen maka gunakan ini:
Di mana
R.id.myViewPagerId
id ViewPager Anda di dalam Layout xml.sumber
Anda dapat mendeklarasikan Array fragmen sebagai fragmen register
Maka Anda dapat menggunakannya sebagai
sumber