it-roy-ru.com

Заменить один фрагмент другим фрагментом

Я хочу заменить старую Fragment новой Fragment, но я все еще получаю кнопки старой Fragment, которая все еще видна в новом фрагменте.

В старом, по нажатию кнопки enter image description here

FragmentTransaction transaction = getFragmentManager().beginTransaction();
Fragment newFragment = GenericMood.newInstance("a","b");

// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack if needed
transaction.replace(R.id.allmoods, newFragment);
transaction.addToBackStack(null);
transaction.commitAllowingStateLoss();

Я могу заменить старую Fragment новой, но кнопки из R.id.allmoods Fragment все еще видны поверх новой Fragment.

enter image description here

Я попытался с этим приведенным ниже кодом.

FragmentTransaction transaction = getFragmentManager().beginTransaction();
Fragment newFragment = GenericMood.newInstance("a","b");

// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack if needed
transaction.replace(((ViewGroup)getView().getParent()).getId(), newFragment);
transaction.addToBackStack(null);
transaction.commitAllowingStateLoss();

XML-файлы:

<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:tools="http://schemas.Android.com/tools"
    Android:id="@+id/allmoods"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:background="@color/colorPrimary"
    tools:context="com.moodoff.Moods">
     <Button
        Android:text="Button1"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_marginTop="64dp"
        Android:id="@+id/btn_btn"
        Android:height="80dp"
        Android:width="100dp"
        Android:onClick="putmeoff"
        Android:layout_marginLeft="17dp"
        Android:layout_marginStart="17dp"/>
</RelativeLayout>

Это фрагмент, который должен заменить вышеперечисленное:

<FrameLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:app="http://schemas.Android.com/apk/res-auto"
    xmlns:tools="http://schemas.Android.com/tools"
    Android:layout_width="match_parent"
    Android:id="@+id/genericmood"
    Android:layout_height="match_parent"
    Android:background="@color/colorPrimary"
    tools:context="com.moodoff.GenericMood">
    <!-- TODO: Update blank fragment layout -->


    <RelativeLayout
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:background="#000000"
        Android:layout_gravity="fill_horizontal"
        Android:id="@+id/floatingButtons"
        >
        <Android.support.design.widget.FloatingActionButton
            Android:layout_width="wrap_content"
            Android:layout_height="wrap_content"
            Android:layout_marginTop="1dp"
            Android:layout_marginRight="14dp"
            app:backgroundTint="#ffffff"
            Android:layout_alignParentTop="true"
            Android:layout_alignParentRight="true"
            Android:layout_alignParentEnd="true"
            Android:src="@drawable/cameraicon"
            Android:id="@+id/btn_camera"
            app:fabSize="mini"
            />
    </RelativeLayout>
</FrameLayout>

Оба не работают. Что делать? ОБНОВЛЕНИЕ: после замены на соответствующий контейнер кнопки исчезли, но новый фрагмент не создается должным образом. Я получаю чистый чистый белый экран.enter image description here

my activity_alltabs.xml looks like this: 

<?xml version="1.0" encoding="utf-8"?>
    <Android.support.design.widget.CoordinatorLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
        xmlns:app="http://schemas.Android.com/apk/res-auto"
        xmlns:tools="http://schemas.Android.com/tools"
        Android:id="@+id/main_content"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:fitsSystemWindows="true"
        tools:context="com.moodoff.AllTabs">

        <Android.support.design.widget.AppBarLayout
            Android:id="@+id/appbar"
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content"
            Android:theme="@style/AppTheme.AppBarOverlay">

            <Android.support.design.widget.TabLayout
                Android:id="@+id/tabs"
                Android:layout_width="match_parent"
                Android:layout_height="wrap_content"
                Android:background="@Android:color/background_dark" />

        </Android.support.design.widget.AppBarLayout>

        <Android.support.v4.view.ViewPager
            Android:id="@+id/container"
            Android:layout_width="match_parent"
            Android:layout_height="match_parent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior" />

    </Android.support.design.widget.CoordinatorLayout>
9
Santanu

Я работал над фрагментами раньше и надеюсь, что это поможет вам и даст вам лучшее понимание потока. Во-первых, ваш файл MainActivity.xml будет выглядеть так: 

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
   xmlns:app="http://schemas.Android.com/apk/res-auto"
   xmlns:tools="http://schemas.Android.com/tools"
   Android:layout_width="match_parent"
   Android:layout_height="match_parent"
   app:layout_behavior="@string/appbar_scrolling_view_behavior"
   tools:context="com.example.activity.HomeActivity">


    //This frameLayout will contain all your fragments view.
   <FrameLayout
      Android:id="@+id/container_view"
      Android:layout_width="match_parent"
      Android:layout_height="match_parent">
    </FrameLayout>

 </RelativeLayout>

Далее вы создаете два фрагмента, и их XML упоминается ниже: fragment1.xml

<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:tools="http://schemas.Android.com/tools"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:clickable="true" // important to have this
    tools:context=".fragments.frament1">

     <Button
        Android:id="@+id/btn"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:layout_gravity="bottom"/>

 </RelativeLayout>

Следующий фрагмент будет выглядеть точно так же, как указано выше. Вот Fragment1.class:

public class Fragment1 extends Fragment implements View.OnClickListener {
Button btn;

   public Fragment1() {
    // Required empty public constructor
}

     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment1, container, false);
        view.setBackgroundColor(Color.WHITE);

       //Perform required conditions and return view 
       button = (Button) view.findViewById(R.id.btn);
       button.setOnClickListener(this);

       return view;
      }

        public void onClick(View v) {

             switch(v.getId())
             {
                case R.id.btn: 
                 //replace current fragment on button click

                 Fragment fragment2= new Fragment2();

                 getFragmentManager().beginTransaction().
                 replace(R.id.container_view, fragment2).
                 addToBackStack("frags").commit();

               break;
             }
        }
 }

И Fragment2 будет выглядеть следующим образом:

 public class Fragment2 extends Fragment{
 String TAG = "Fragment2";


     public Fragment2() {
      // Required empty public constructor
   }

     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

          View view = inflater.inflate(R.layout.fragment2,container,false);
          view.setBackgroundColor(Color.WHITE);
       return view;
    }
}

Как я упоминал ранее, XML-файл будет таким же, как fragment1.xml. Здесь важнее то, что основное действие будет содержать макет, который будет принимать вид фрагментов, когда пользователь переключает фрагменты. Следовательно, мы используем метод replace, который просто заменит предыдущее представление на представление фрагментов, указанное нами.

5
Rajeev

Чтобы понять поток перехода фрагмента, прежде всего, вы должны знать о его структуре в деятельности . Давайте посмотрим: A) Активность: В основе всего (MainActivity)

activity_main.xml: -

<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:tools="http://schemas.Android.com/tools"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent">

    <FrameLayout
        Android:id="@+id/container"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"/>
</RelativeLayout>

Здесь @ + id/container - это макет, над которым мы выполняем переходы содержимого фрагмента.

B) FragmentA: изначально добавлен фрагмент в контейнер MainActivity.

FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
//Instance of fragment
Fragment newFragment = FragmentA.newInstance("a","b");
//It will replace the fragment content view to container of main activity
ft.replace(R.id.container, newFragment);
//FragmentA is added to back stack with it's name as a tag
ft.addToBackStack(FragmentA.class.getSimpleName());
ft.commitAllowingStateLoss();

B) FragmentB: заменить FragmentA на FragmentB

FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
//Instance of fragment
Fragment newFragment = FragmentB.newInstance("a","b");
//It will replace the fragment content view to container of fragment A which     // is previously replaced to main activity container
ft.replace(R.id.container, newFragment);
//FragmentB is added to back stack with it's name as a tag
ft.addToBackStack(FragmentB.class.getSimpleName());
ft.commitAllowingStateLoss();

Поэтому главное - заменить/добавить представление содержимого фрагмента в представление контейнера действия.

3
Ready Android

В функции onCreate вашей деятельности вы должны вызывать setContentView(R.layout.main), затем, когда вы хотите загрузить фрагмент, вы выбираете ViewParent внутри R.layout.main. Фрагмент станет потомком этого ViewParent. Таким образом, идентификатор, передаваемый в FragmentTransaction.replace , является идентификатором ViewParent в R.layout.main

Имеет смысл, что Button в вашем allmoods RelativeLayout останется, потому что функция FragmentTransaction.replace заменяет только существующий фрагмент, который находится в этом контейнере. Все в R.layout.main останется. Вот как Activity сохраняет статическое содержимое, например, ящики или панели инструментов.

Когда вы загрузите свой «новый фрагмент», вы будете использовать тот же идентификатор. Таким образом, «новый фрагмент» заменяет «старый фрагмент» в качестве нового дочернего элемента ViewParent внутри R.layout.main

Вот Руководство по фрагментам API .

Обновление:

Когда вы вызываете FragmentTransaction.replace в функции onCreate вашей активности, это может быть воссоздание существующего фрагмента. Убедитесь, что saveInstanceState (Bundle, переданный в onCreate) имеет значение null. Если saveInstanceState не является нулевым, то фрагмент, вероятно, уже существует, и вы можете найти его следующим образом;

Fragment f = getFragmentManager().findFragmentByTag(YOUR_FRAGMENT_TAG);

Обновление 2:

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

3
Mike

попробуйте это один раз, 1. если вы передаете какое-либо значение при нажатии кнопки.

Category category=new Category();
            Bundle bundle=new Bundle();
            bundle.putString("heading",heading);
            bundle.putInt("position",position1+1);
            bundle.putString("url",url);
            bundle.putString("sku",sku);
            bundle.putBoolean("flag",flag);
            category.setArguments(bundle);

            FragmentManager fragmentManager = getSupportFragmentManager();
            final FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
            fragmentTransaction.replace(R.id.fragmentCategories,category);
            fragmentTransaction.commit();

Во фрагменте

Bundle bundle=getArguments();
    if(getArguments()!=null) {
        position = bundle.getInt("position");
        heading = bundle.getString("heading");
        url = bundle.getString("url");
        sku=bundle.getString("sku");
        flag=bundle.getBoolean("flag");

        tvHeading.setText(heading);

        video_chapter = handler.getContent_Aspects(position);
        adapter = new Chapter_content_Adapter(getActivity(), video_chapter, url, heading, position);
        gvChapter.setAdapter(adapter);
    }

2. если просто вызывать фрагмент

FragmentManager fragmentManager = getSupportFragmentManager();
    FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
    fragmentCategories=fragmentManager.findFragmentById(R.id.fragmentCategories);
    fragmentTransaction.commit();
1
Ashish Kumar Pal

Попробуйте следующий код. 

А) Создайте активность следующим образом:

Основная деятельность

import Android.app.FragmentTransaction;
import Android.os.Bundle;
import Android.support.v7.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity implements ShowNextFragment{


@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    FragmentA fragmentA=new FragmentA();
    FragmentTransaction fragmentTransaction=getFragmentManager().beginTransaction();
    fragmentTransaction.replace(R.id.container,fragmentA);
    fragmentTransaction.addToBackStack("A");
    fragmentTransaction.commitAllowingStateLoss();

}

@Override
public void showFragment() {
    FragmentB fragmentB=new FragmentB();
    FragmentTransaction fragmentTransaction=getFragmentManager().beginTransaction();
    fragmentTransaction.replace(R.id.container,fragmentB);
    fragmentTransaction.addToBackStack("B");
    fragmentTransaction.commitAllowingStateLoss();
}
}

Б) Создайте 2 фрагмента следующим образом:

Фрагмент А

 import Android.app.Fragment;
 import Android.os.Bundle;
 import Android.support.annotation.Nullable;
 import Android.util.Log;
 import Android.view.LayoutInflater;
 import Android.view.View;
 import Android.view.ViewGroup;


public class FragmentA extends Fragment {
private ShowNextFragment showNextFragment;



@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    try {

        showNextFragment=(ShowNextFragment)getActivity();
        Log.e("CAllback","Set");
    }catch (ClassCastException e){
        Log.e("Error","Please Implement ShowFragment Interface");
    }
    return inflater.inflate(R.layout.fragment_a,container,false);
}

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    view.findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (showNextFragment!=null){
                showNextFragment.showFragment();
            }
        }
    });

}
}

Фрагмент Б

import Android.app.Fragment;
import Android.os.Bundle;
import Android.support.annotation.Nullable;
import Android.view.LayoutInflater; 
import Android.view.View;
import Android.view.ViewGroup;

public class FragmentB extends Fragment {



@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    return inflater.inflate(R.layout.fragment_b,container,false);
}

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);


}
}

В) Создайте интерфейс следующим образом 

public interface ShowNextFragment {
void showFragment();
}

D) создать следующие xmls как:

я) Activity_main

   <?xml version="1.0" encoding="utf-8"?>
   <RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:tools="http://schemas.Android.com/tools"
Android:id="@+id/container"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
>

  </RelativeLayout>

ii) фрагмент_а

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:background="@color/colorcyan"
Android:orientation="vertical">

<Button
    Android:id="@+id/button"
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    Android:text="Show Fragment B" />
</LinearLayout>

iii) фрагмент_b

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:app="http://schemas.Android.com/apk/res-auto"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:background="@color/colorgreen"
Android:orientation="vertical">

<TextView

    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    Android:text="Fragment B"
    Android:layout_centerVertical="true"
    Android:layout_alignRight="@+id/btn_camera"
    Android:layout_alignEnd="@+id/btn_camera" />

<Android.support.design.widget.FloatingActionButton
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    app:backgroundTint="#ffffff"
    Android:src="@Android:drawable/ic_dialog_email"
    Android:id="@+id/btn_camera"
    app:fabSize="mini"
    Android:layout_alignParentBottom="true"
    Android:layout_centerHorizontal="true" />
 </RelativeLayout>
1
avinash

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

Пожалуйста, измените его, чтобы получить идентификатор представления контейнера фрагмента, и он будет работать! Вот код:

транзакция.replace (((ViewGroup) (getView (). getParent ())). getId (), фрагмент); 

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

0
Zhao Lin

Просто сделайте кнопки setVisibility (View.GONE) в вашей деятельности, когда этот фрагмент начинает транзакцию.

0
Vijay Kumar M