Parça içinde Parça


137

Parça içinde fragman üzerinde çalışma konusunda yardıma ihtiyacım var, aslında geri düğmesine basarken bir sorunla karşılaşıyorum. Uygulama Ana ekranın düğmeleri vardır ve her bir düğme görünümüne basıldığında yeni parça ile değiştirilir (ve bu parça başka bir parçanın içinde bulunur), parçanın dinamik olarak eklenmesi / değiştirilmesi parçanın iyi çalıştığını, düğme1 parçasının değiştirilmesiyle basıldığında aynı olur, ancak düğmesi tekrar bir istisna aldı:

"Duplicate id 0x7f05000a, tag null, or parent id 0x7f050009 with
another fragment for com........ fragmentname"

parçanın veya iç parçaların zaten eklenmiş olduğu anlamına gelir ve bunları tekrar eklemeye çalışıyorum, herkes parçanın içindeki parçayla nasıl çalışacağını ve sorunsuz bir şekilde ileri geri hareket etmeyi destekliyor.

Parçaların dinamik olarak eklendiği ve değiştirildiği MainActivity.

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

Düzen: 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>

Umarım sorunumu gidermeye çalıştım.


1
Yukarıdaki kod android 3.1
Vivek


Yanıtlar:


284

AFAIK, parçalar başka parçaları tutamaz.


GÜNCELLEME

Android Destek paketinin güncel sürümleriyle - veya API Seviyesi 17 ve üzerindeki yerel parçalarla - parçaları yuvalayabilirsiniz getChildFragmentManager(). Bunun, API Düzeyleri 11-16'daki parçaların Android Destek paketi sürümünü kullanmanız gerektiği anlamına geldiğini unutmayın, çünkü bu cihazlarda parçaların yerel bir sürümü olsa da, bu sürümde yoktur getChildFragmentManager().


31
Platform burada gerçekten berbat. Bunu hata ayıklamak için üç saat harcadım çünkü iç parça ilk kez iyi işleyecekti, ancak ekran yönelimi değişikliğinden sonra kaybolacaktı . İstisna yok, günlük bilgisi, hiçbir şey. İç parçaya (merhamet) geçmek getChildFragmentManager()ve çıkarmak setRetainInstance(true), onu düzeltti. Pastırmamı tekrar kaydettiğiniz için teşekkürler, @CommonsWare.
Felix

82

resim açıklamasını buraya girin

Daha fazla içeriğe ihtiyacım vardı, bu yüzden bunun nasıl yapıldığını göstermek için bir örnek verdim. Hazırlanırken okuduğum en faydalı şey şuydu:

Aktivite

activity_main.xml

FrameLayoutÜst parçayı tutmak için etkinliğinize a ekleyin .

<?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

Ana parçayı yükleyin ve parça dinleyicilerini uygulayın. (Bkz. Parça iletişimi .)

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

Üst Parça

fragment_parent.xml

FrameLayoutAlt parça için başka bir kap ekleyin .

<?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

Kullanım getChildFragmentManageriçinde onViewCreatedçocuk parçasını kurmak.

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

Çocuk Parçası

fragment_child.xml

Burada özel bir şey yok.

<?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

Burada da çok özel bir şey yok.

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

notlar



13

Parçalar diğer parçaların içine eklenebilir, ancak daha sonra onDestroyView()ana parça yöntemi çağrıldığında parçayı ana Parçadan kaldırmanız gerekir . Ve tekrar Parent Fragment'ın onCreateView()yöntemine ekleyin .

Sadece şunu yap:

@Override
    public void onDestroyView()
    {
                FragmentManager mFragmentMgr= getFragmentManager();
        FragmentTransaction mTransaction = mFragmentMgr.beginTransaction();
                Fragment childFragment =mFragmentMgr.findFragmentByTag("qa_fragment")
        mTransaction.remove(childFragment);
        mTransaction.commit();
        super.onDestroyView();
    }

4
Bu benim için işe yaramadı. İki çocuk görüşü içeren bir görünümü şişiren bir parçam vardı. İçinde onActivityCreated(), kullanarak görünümlerin her birine bir tane olmak üzere iki parça ekledi getFragmentManager(). Bu ilk kez çalıştı, ancak rotasyonda ve özgeçmişte sadece bir parça görülebilir. Davranış getChildFragmentManager()yerine doğruydu . Burada önerilen yaklaşım, faaliyetin onSaveInstanceState()zaten çağrılması nedeniyle bir istisna attı . İşlemi kullanarak işlem yapmak commitAllowingStateLoss()istisnadan kaçındı, ancak orijinal sorunu çözmedi.
user1978019


9

Bu sorunu çözdüm. Destek kitaplığını ve kullanabilirsiniz ViewPager. Hareketle kaydırmaya ihtiyacınız yoksa kaydırmayı devre dışı bırakabilirsiniz. İşte benim çözüm geliştirmek için bazı kod:

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

PSIt çirkin bir koddur, ancak mümkün olduğunu geliştirir.

PPS İçinde fragmanı ChildFragmentManageriletilmesi gerekenViewPagerAdapter


8

getChildFragmentManager()işlevi kullanabilirsiniz .

misal:

Üst parça:

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

Üst düzen ( 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>

Çocuk Parçası:

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) {


    }


} 

4

Karmaşık bir şey değil. Burada kullanamayız getFragmentManager(). Bir Parçanın içinde Parçacıkları kullanmak için kullanırız getChildFragmentManager(). Dinlenme aynı olacak.


3

Parçayı ekleyebilir FrameLayoutve başlatıldığında başka bir parçayla değiştirebilirsiniz.

Bu şekilde, diğer parçanın ilk parçanın içinde olduğunu düşünebilirsiniz.



2

İç içe geçmiş parça içinde, iç içe geçmiş olan (lar) yalnızca programlı olarak oluşturulmuşsa desteklenir! Yani şu anda xml düzen şemasında iç içe hiçbir parça düzeni desteklenmemektedir!


1

Bu Kotlin üzerinde çalışanlara yardımcı olabilir bu yüzden bir kotlin dosyası oluşturmak "util.kt" diyelim ve bu kod parçasını ekleyin

fun Fragment.addChildFragment(fragment: Fragment, frameId: Int) {

    val transaction = childFragmentManager.beginTransaction()
    transaction.replace(frameId, fragment).commit()
}

Diyelim ki bu çocuğun sınıfı

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

Şimdi çocuklara ekleyebilir baba fragmanı böyle

 FatherPresentation:Fragment()
{
  ...

    override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        val fieldFragment= InputFieldPresentation()
        addChildFragment(fieldFragment,R.id.fragmet_field)
    }
...
}

Burada R.id.fragmet_field , parçayı içerecek olan düzenin id. Bu taslak elbette baba parçasının içindedir. İşte bir örnek

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>

1

Destek yok MapFragment, Android ekibi Android 3.0'dan beri üzerinde çalıştığını söylüyor. Burada sorun hakkında daha fazla bilgi Ama döndüren bir Parça oluşturarak ne yapabilirsiniz MapActivity? İşte bir kod örneği. İnazaruk'a teşekkürler:

Nasıl çalışır :

  • MainFragmentActivity, FragmentActivityiki MapFragment'ı genişleten ve barındıran etkinliktir.
  • MyMapActivity, MapActivity'yi genişletir ve MapView.
  • LocalActivityManagerFragment LocalActivityManager'ı barındırır.
  • MyMapFragment uzanır LocalActivityManagerFragmentve MyMapActivity'nin TabHostdahili örneğini oluşturur.

Herhangi bir şüpheniz varsa lütfen bana bildirin


0

Merhaba ben bu sorunu Fragment başına farklı bir düzen koyarak çözdüm.Ve sadece ilgili Düzeni görünür hale getirdim ve diğer görünürlüğü gitti.

Demek istediğim:

<?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>

Düğme 1 tıklatıldığında sayfanızı açacağınızı varsaydım. Parçanızın tıklama eylemi üzerindeki görünürlüğünü kontrol edebilirsiniz. ve bu yana görünürlük sahiptir görünüm: gitmiş görünmez olduğunu ve bu yaklaşımın herhangi uzay soruna neden olmaz düşünüyorum düzen amaçlı herhangi yer almaz.

Not: Çözüm kodumun sözdizimi hataları veya tamamlanmamış yapısı olabileceğini açıklamaya çalıştım.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.