Фрагмент Внутри Фрагмента



мне нужна помощь относительно работы на фрагмент внутри фрагмента, на самом деле я
я столкнулся с проблемой при нажатии кнопки Назад. Главный экран приложения
имеет кнопки и нажатие на каждой кнопке вид заменить на новый
фрагмент(и этот фрагмент содержится внутри другого фрагмента),
динамическое добавление / замена фрагмента работает нормально, нажав
фрагмент button1 заменен, то же самое происходит при нажатии кнопки, но если
Я снова нажимаю кнопку, получаю исключение:



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


означает фрагмент или внутренние фрагменты уже добавлены, и я пытаюсь
чтобы добавить их снова, у кого-нибудь есть идея, как работать с фрагментом внутри
фрагмент и перемещение вперед и назад без каких-либо проблем, Спасибо за
поддержка.



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

}
}


вот макет: main.xml



 <?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:id="@+id/linearLayout2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"></LinearLayout>
</LinearLayout>


надеюсь, я попытался очистить мою проблему.

929   13  

13 ответов:

AFAIK, фрагменты не могут содержать другие фрагменты.


обновление

с текущими версиями пакета поддержки Android - или собственные фрагменты на уровне API 17 и выше - вы можете вложить фрагменты, с помощью getChildFragmentManager(). Обратите внимание, что это означает, что вам нужно использовать версию пакета поддержки Android фрагментов на уровнях API 11-16, потому что, хотя на этих устройствах есть собственная версия фрагментов, эта версия не имеет getChildFragmentManager().

Так как Android 4.2 (API 17) вложенные фрагменты становятся доступными http://developer.android.com/about/versions/android-4.2.html#NestedFragments

для размещения фрагмента внутри другого фрагмента используйте getChildFragmentManager ()

Он также доступен в библиотеке поддержки!

enter image description here

мне нужно больше контекста, поэтому я сделал пример, чтобы показать, как это делается. Самое полезное, что я прочитал во время подготовки было это:

активность

activity_main.xml

добавить FrameLayout в вашей деятельности, чтобы держать родителей фрагмент.

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

загрузите Родительский фрагмент и реализуйте прослушиватели фрагментов. (См.фрагмент коммуникации.)

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

Родительский Фрагмент

fragment_parent.xml

добавить FrameLayout контейнер для ребенка фрагмент.

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

использовать getChildFragmentManager на onViewCreated для настройки дочернего фрагмента.

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

Фрагмент Ребенка

fragment_child.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:layout_margin="20dp"
              android:background="#f1ff91">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Child fragment"/>
</LinearLayout>

ChildFragment.java

здесь нет ничего особенного, любой.

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

Примечания

фрагменты могут быть добавлены внутри других фрагментов, но тогда вам нужно будет удалить его из родительского фрагмента каждый раз, когда вызывается метод onDestroyView() родительского фрагмента. И снова добавьте его в метод Oncreateview() родительского фрагмента.

просто сделайте так:

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

Я решил эту проблему. Вы можете использовать библиотеку поддержки и ViewPager. Если вам не нужно пролистывание жестом, вы можете отключить пролистывание. Так вот какой код для улучшения моего решения:

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

P. S. Это уродливый код для тестирования, но он улучшает, что это возможно.

П. П. С. внутри фрагмент ChildFragmentManager должно быть передано в ViewPagerAdapter

можно использовать .

пример:

родитель фрагмент :

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

макет родитель (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>

Ребенок Фрагмент:

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


    }


} 

вы можете добавить FrameLayout к фрагменту и замените его другим фрагментом, Когда он инициализируется.

таким образом, вы можете считать, что другой фрагмент находится внутри первого фрагмента.

используйте getChildFragmentManager (), перейдите по ссылке : Вложенные Фрагмент

нет поддержки MapFragment, команда Android говорит, что работает над ним с Android 3.0. Здесь более подробная информация о проблеме http://code.google.com/p/android/issues/detail?id=15347&utm_source=buffer&buffer_share=acc72 но что вы можете сделать, создав фрагмент, который возвращает MapActivity. Вот пример кода. Спасибо иназаруку:https://github.com/inazaruk/examples/tree/master/MapFragmentExample

Как это работает:

-MainFragmentActivity-это действие, которое расширяет FragmentActivity и содержит два MapFragments. - MyMapActivity расширяет MapActivity и имеет MapView. - LocalActivityManagerFragment хосты LocalActivityManager. -MyMapFragment расширяет LocalActivityManagerFragment и с помощью TabHost создает внутренний экземпляр MyMapActivity. если у вас есть какие-либо сомнения, пожалуйста, дайте мне знать

В настоящее время во вложенном фрагменте вложенные единицы поддерживаются только в том случае, если они генерируются программно! Таким образом, в настоящее время в схеме компоновки xml не поддерживается вложенный фрагмент макета!

ничего сложного. Мы не можем использовать getFragmentManager() здесь. Для использования фрагментов внутри фрагмента мы используем getChildFragmentManager (). Отдых будет таким же.

Привет я решил эту проблему, поместив каждый фрагмент в отдельный макет.И я сделал только что связанный макет видимым и сделал другие видимости исчезли.

Я имею в виду:

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

Я предположил, что вы откроете свою страницу, как кнопка 1 нажата.Вы можете контролировать видимость вашего фрагмента на действие щелчка.Вы можете сделать связанный макет видимым, а другие ушли, и с помощью Диспетчера фрагментов вы можете взять свой фрагмент.Этот подход сработал для меня.И так вид, который имеет видимость: ушел невидим, и он не занимает места для целей макета я думаю, что этот подход не вызывает никаких проблем с пространством.

P. S: Я просто попытался объяснить, что мой код решения может иметь синтаксические ошибки или незавершенную структуру.

что может помочь тем, кто работает на Котлин вы можете использовать функцию расширения Итак, создайте файл kotlin, скажем " util.КТ" и добавить этот кусок кода

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

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

допустим, это класс ребенок

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

теперь вы можете добавить детей в отец фрагмент такой

 FatherPresentation:Fragment()
{
  ...

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

где R. id. fragmet_field - это идентификатор макета, который будет содержать фрагмент.Этот Лют находится внутри фрагмента отца, конечно. Вот пример

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>

Comments

    Ничего не найдено.