Saya butuh bantuan terkait pengerjaan fragmen di dalam fragmen, sebenarnya saya menghadapi masalah saat menekan tombol kembali. Aplikasi Layar utama memiliki tombol dan menekan pada setiap tampilan tombol ganti dengan fragmen baru (dan fragmen itu berisi di dalam fragmen lain), secara dinamis menambahkan / mengganti fragmen berfungsi dengan baik, dengan menekan tombol1 fragmen diganti, sama terjadi saat menekan tombol, tetapi jika saya tekan tombol lagi, mendapat pengecualian:
"Duplicate id 0x7f05000a, tag null, or parent id 0x7f050009 with
another fragment for com........ fragmentname"
Berarti fragmen atau fragmen dalam sudah ditambahkan dan saya mencoba menambahkannya lagi, siapa pun tahu bagaimana bekerja dengan fragmen di dalam fragmen dan bergerak maju mundur tanpa masalah, terima kasih atas dukungannya.
MainActivity, di mana fragmen ditambahkan dan diganti secara dinamis.
public class FragmentInsideFragmentTestActivity extends Activity {
private Button button1;
private Button button2;
private Button button3;
private Button button4;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
button1 =(Button) this.findViewById(R.id.button1);
button1.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
onButtonClick(view);
}
});
button2 =(Button) this.findViewById(R.id.button2);
button2.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
onButtonClick(view);
}
});
button3 =(Button) this.findViewById(R.id.button3);
button3.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
onButtonClick(view);
}
});
button4 =(Button) this.findViewById(R.id.button4);
button4.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
onButtonClick(view);
}
});
}
public void onButtonClick(View v) {
Fragment fg;
switch (v.getId()) {
case R.id.button1:
fg=FirstFragment.newInstance();
replaceFragment(fg);
break;
case R.id.button2:
fg=SecondFragment.newInstance();
replaceFragment(fg);
break;
case R.id.button3:
fg=FirstFragment.newInstance();
replaceFragment(fg);
break;
case R.id.button4:
fg=SecondFragment.newInstance();
replaceFragment(fg);
break;
}
}
private void replaceFragment(Fragment newFragment) {
FragmentTransaction trasection = getFragmentManager().beginTransaction();
if(!newFragment.isAdded()) {
try {
//FragmentTransaction trasection =
getFragmentManager().beginTransaction();
trasection.replace(R.id.linearLayout2, newFragment);
trasection.addToBackStack(null);
trasection.commit();
} catch (Exception e) {
// TODO: handle exception
// AppConstants.printLog(e.getMessage());
} else {
trasection.show(newFragment);
}
}
}
Inilah Layout: main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<LinearLayout
android:id="@+id/linearLayout1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button1" />
<Button
android:id="@+id/button2"
android:text="Button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:id="@+id/button3"
android:text="Button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:id="@+id/button4"
android:text="Button4"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:id="@+id/linearLayout2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" />
</LinearLayout>
Harap saya mencoba untuk menyelesaikan masalah saya.
sumber
Jawaban:
AFAIK, fragmen tidak bisa menampung fragmen lain.
MEMPERBARUI
Dengan versi terbaru dari paket Dukungan Android - atau fragmen asli pada API Level 17 dan yang lebih tinggi - Anda bisa menyarangkan fragmen, melalui
getChildFragmentManager()
. Perhatikan bahwa ini berarti Anda perlu menggunakan versi fragmen paket Dukungan Android pada API Level 11-16, karena meskipun ada versi asli fragmen pada perangkat tersebut, versi tersebut tidak memilikinyagetChildFragmentManager()
.sumber
getChildFragmentManager()
dan menghapussetRetainInstance(true)
dari bagian dalam (kasihan) memperbaikinya. Terima kasih telah menyimpan daging saya lagi, @CommonsWare.Saya membutuhkan lebih banyak konteks, jadi saya membuat contoh untuk menunjukkan bagaimana ini dilakukan. Hal paling berguna yang saya baca saat mempersiapkan adalah ini:
Aktivitas
activity_main.xml
Tambahkan a
FrameLayout
ke aktivitas Anda untuk menampung fragmen induk.<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Activity"/> <FrameLayout android:id="@+id/parent_fragment_container" android:layout_width="match_parent" android:layout_height="200dp"/> </LinearLayout>
MainActivity.java
Muat fragmen induk dan implementasikan pemroses fragmen. (Lihat komunikasi fragmen .)
import android.support.v4.app.FragmentTransaction; import android.support.v7.app.AppCompatActivity; public class MainActivity extends AppCompatActivity implements ParentFragment.OnFragmentInteractionListener, ChildFragment.OnFragmentInteractionListener { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Begin the transaction FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); ft.replace(R.id.parent_fragment_container, new ParentFragment()); ft.commit(); } @Override public void messageFromParentFragment(Uri uri) { Log.i("TAG", "received communication from parent fragment"); } @Override public void messageFromChildFragment(Uri uri) { Log.i("TAG", "received communication from child fragment"); } }
Fragmen Induk
fragment_parent.xml
Tambahkan
FrameLayout
wadah lain untuk fragmen anak.<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="20dp" android:background="#91d0c2"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Parent fragment"/> <FrameLayout android:id="@+id/child_fragment_container" android:layout_width="match_parent" android:layout_height="match_parent"> </FrameLayout> </LinearLayout>
ParentFragment.java
Gunakan
getChildFragmentManager
dionViewCreated
untuk mengatur fragmen anak.import android.support.v4.app.Fragment; import android.support.v4.app.FragmentTransaction; public class ParentFragment extends Fragment { private OnFragmentInteractionListener mListener; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment return inflater.inflate(R.layout.fragment_parent, container, false); } @Override public void onViewCreated(View view, Bundle savedInstanceState) { Fragment childFragment = new ChildFragment(); FragmentTransaction transaction = getChildFragmentManager().beginTransaction(); transaction.replace(R.id.child_fragment_container, childFragment).commit(); } @Override public void onAttach(Context context) { super.onAttach(context); if (context instanceof OnFragmentInteractionListener) { mListener = (OnFragmentInteractionListener) context; } else { throw new RuntimeException(context.toString() + " must implement OnFragmentInteractionListener"); } } @Override public void onDetach() { super.onDetach(); mListener = null; } public interface OnFragmentInteractionListener { // TODO: Update argument type and name void messageFromParentFragment(Uri uri); } }
Fragmen Anak
fragment_child.xml
Tidak ada yang spesial disini.
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="20dp" android:background="#f1ff91"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Child fragment"/> </LinearLayout>
ChildFragment.java
Tidak ada yang terlalu istimewa di sini.
import android.support.v4.app.Fragment; public class ChildFragment extends Fragment { private OnFragmentInteractionListener mListener; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_child, container, false); } @Override public void onAttach(Context context) { super.onAttach(context); if (context instanceof OnFragmentInteractionListener) { mListener = (OnFragmentInteractionListener) context; } else { throw new RuntimeException(context.toString() + " must implement OnFragmentInteractionListener"); } } @Override public void onDetach() { super.onDetach(); mListener = null; } public interface OnFragmentInteractionListener { // TODO: Update argument type and name void messageFromChildFragment(Uri uri); } }
Catatan
sumber
Sejak fragmen bersarang Android 4.2 (API 17) tersedia http://developer.android.com/about/versions/android-4.2.html#NestedFragments
Untuk menempatkan fragmen di dalam fragmen lain, gunakan getChildFragmentManager ()
Ini juga tersedia di perpustakaan dukungan!
sumber
Fragmen dapat ditambahkan ke dalam fragmen lain, tetapi Anda harus menghapusnya dari Fragmen induk setiap kali
onDestroyView()
metode fragmen induk dipanggil. Dan tambahkan lagi dalamonCreateView()
metode Parent Fragment .Lakukan saja seperti ini:
@Override public void onDestroyView() { FragmentManager mFragmentMgr= getFragmentManager(); FragmentTransaction mTransaction = mFragmentMgr.beginTransaction(); Fragment childFragment =mFragmentMgr.findFragmentByTag("qa_fragment") mTransaction.remove(childFragment); mTransaction.commit(); super.onDestroyView(); }
sumber
onActivityCreated()
dalamnya ditambahkan dua fragmen, satu ke masing-masing tampilan, menggunakangetFragmentManager()
. Ini berhasil pertama kali, tetapi pada rotasi dan resume hanya satu fragmen yang terlihat.getChildFragmentManager()
Sebaliknya, perilaku benar . Pendekatan yang disarankan di sini memberikan pengecualian karena aktivitasonSaveInstanceState()
sudah dipanggil. Melakukan transaksi menggunakancommitAllowingStateLoss()
menghindari pengecualian tetapi tidak menyelesaikan masalah asli.Saya memecahkan masalah ini. Anda dapat menggunakan pustaka Dukungan dan
ViewPager
. Jika Anda tidak perlu menggesek dengan gerakan, Anda dapat menonaktifkan gesekan. Jadi inilah beberapa kode untuk meningkatkan solusi saya:public class TestFragment extends Fragment{ @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.frag, container, false); final ArrayList<Fragment> list = new ArrayList<Fragment>(); list.add(new TrFrag()); list.add(new TrFrag()); list.add(new TrFrag()); ViewPager pager = (ViewPager) v.findViewById(R.id.pager); pager.setAdapter(new FragmentPagerAdapter(getChildFragmentManager()) { @Override public Fragment getItem(int i) { return list.get(i); } @Override public int getCount() { return list.size(); } }); return v; } }
PS Ini adalah kode yang jelek untuk pengujian, tetapi itu meningkatkan bahwa itu mungkin.
Fragmen PPS Inside
ChildFragmentManager
harus diteruskan keViewPagerAdapter
sumber
Anda dapat menggunakan
getChildFragmentManager()
fungsi.contoh:
Fragmen induk:
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { rootView = inflater.inflate(R.layout.parent_fragment, container, false); } //child fragment FragmentManager childFragMan = getChildFragmentManager(); FragmentTransaction childFragTrans = childFragMan.beginTransaction(); ChildFragment fragB = new ChildFragment (); childFragTrans.add(R.id.FRAGMENT_PLACEHOLDER, fragB); childFragTrans.addToBackStack("B"); childFragTrans.commit(); return rootView; }
Tata letak induk (
parent_fragment.xml
):<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/white"> <FrameLayout android:id="@+id/FRAGMENT_PLACEHOLDER" android:layout_width="match_parent" android:layout_height="match_parent"/> </LinearLayout>
Fragmen Anak:
public class ChildFragment extends Fragment implements View.OnClickListener{ View v ; @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { // TODO Auto-generated method stub View rootView = inflater.inflate(R.layout.child_fragment, container, false); v = rootView; return rootView; } @Override public void onClick(View view) { } }
sumber
Gunakan getChildFragmentManager (), ikuti link: Fragmen Bersarang
sumber
Tidak ada yang rumit. Kami tidak bisa menggunakan di
getFragmentManager()
sini. Untuk menggunakan Fragmen di dalam Fragmen , kami menggunakangetChildFragmentManager()
. Istirahat akan sama.sumber
Anda dapat menambahkan
FrameLayout
ke fragmen dan menggantinya dengan fragmen lain saat inisialisasi.Dengan cara ini, Anda dapat menganggap fragmen lain berada di dalam fragmen pertama.
sumber
Saat ini dalam fragmen bersarang, yang bertingkat hanya didukung jika dibuat secara terprogram! Jadi saat ini tidak ada layout fragmen bersarang yang didukung dalam skema layout xml!
sumber
Itu dapat membantu mereka yang bekerja di Kotlin, Anda dapat menggunakan fungsi ekstensi jadi buat file kotlin, katakanlah "util.kt" dan tambahkan bagian kode ini
fun Fragment.addChildFragment(fragment: Fragment, frameId: Int) { val transaction = childFragmentManager.beginTransaction() transaction.replace(frameId, fragment).commit() }
Katakanlah ini adalah kelas anak
class InputFieldPresentation: Fragment() { var views: View? = null override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? { views = inflater!!.inflate(R.layout.input_field_frag, container, false) return views } override fun onViewCreated(view: View?, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) ... } ... }
Sekarang Anda dapat menambahkan anak-anak ke fragmen ayah seperti ini
FatherPresentation:Fragment() { ... override fun onViewCreated(view: View?, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) val fieldFragment= InputFieldPresentation() addChildFragment(fieldFragment,R.id.fragmet_field) } ... }
di mana R.id.fragmet_field adalah id tata letak yang akan berisi fragmen. Lyout ini tentu saja ada di dalam fragmen ayah. Berikut ini contohnya
father_fragment.xml :
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" xmlns:android="http://schemas.android.com/apk/res/android" > ... <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:id="@+id/fragmet_field" android:orientation="vertical" > </LinearLayout> ... </LinearLayout>
sumber
Tidak ada dukungan untuk
MapFragment
, kata tim Android sedang mengerjakannya sejak Android 3.0. Di sini informasi lebih lanjut tentang masalah Tapi apa yang dapat Anda lakukan dengan membuat Fragmen yang mengembalikan fileMapActivity
. Berikut adalah contoh kode. Berkat inazaruk:Bagaimana itu bekerja :
FragmentActivity
dan menghosting dua MapFragments.MapView.
LocalActivityManagerFragment
host LocalActivityManager.LocalActivityManagerFragment
dan dengan bantuanTabHost
membuat instance internal MyMapActivity.Jika Anda ragu, beri tahu saya
sumber
Hai, saya memecahkan masalah ini dengan meletakkan per Fragmen ke dalam tata letak yang berbeda. Dan saya hanya membuat Tata Letak terkait terlihat dan membuat visibilitas yang lain hilang.
Maksudku:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <LinearLayout android:id="@+id/linearLayout1" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:layout_width="wrap_content" android:id="@+id/button1" android:layout_height="wrap_content" android:text="Button1"></Button> <Button android:text="Button2" android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button> <Button android:text="Button3" android:id="@+id/button3" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button> <Button android:text="Button4" android:id="@+id/button4" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button> </LinearLayout> <LinearLayout android:layout_width="full_screen" android:layout_height="0dp" android:layout_weight="1" android:id="action_For_Button1" android:visibility="visible"> <Fragment android:layout_width="full_screen" android:layout_height="full_screen" android:id="fragment1" . . . / > </LinearLayout> <LinearLayout android:layout_width="full_screen" android:layout_height="0dp" android:id="action_For_Button1" android:layout_weight="1" android:visibility="gone"> <Fragment android:layout_width="full_screen" android:layout_height="full_screen" android:id="fragment2" . . . / > </LinearLayout> . . . </LinearLayout>
Saya berasumsi bahwa Anda akan membuka halaman Anda saat tombol 1 diklik. Anda dapat mengontrol visibilitas fragmen Anda pada tindakan klik. Anda dapat membuat Layout terkait terlihat dan yang lainnya hilang dan dengan Manajer Fragmen Anda dapat mengambil fragmen. Pendekatan ini berhasil untuk saya. Dan karena tampilan yang memiliki visibilitas: hilang tidak terlihat, dan tidak membutuhkan ruang untuk tujuan tata letak, saya pikir pendekatan ini tidak menyebabkan masalah ruang.
PS: Saya baru saja mencoba menjelaskan kode solusi saya mungkin memiliki kesalahan sintaks atau struktur yang tidak lengkap.
sumber