web-dev-qa-db-fra.com

Remplacer le visionneur avec fragment - puis naviguer en arrière

J'ai une activité qui héberge initialement un visionneur, accroché à un fragmentpageradapter.

Lorsque l'utilisateur clique sur un élément à l'intérieur du fragment d'enfant du point de vue, j'utilise une fragmentationTransaction pour remplacer une vue de conteneur vide avec un nouveau fragment que je souhaite accéder à.

Si j'utilise addtobackstackstackstack () sur la transaction, engagez la transaction, puis naviguez vers l'arrière, je ne suis pas retourné aux vues du point de vue (la mise en page initiale).

Si je n'utilise pas Addtobackstackstackstack () sur la transaction, engagez la transaction, puis naviguez vers l'arrière, l'application quitte.

Il semble évident que le point de vue ne soit pas ajouté à l'arrière-plan (ce qui n'est pas surprenant car ce n'est pas un fragment en soi) .. Mais je m'attendrais à ce que le comportement par défaut soit que la presse arrière me ramène à cette activité initiale Vue (le visual).

Sur la base de ce que j'ai lu, il semble que, peut-être parce qu'une transaction de fragment se déroule, le point de vue ou le pageradapter perd une voie de quel fragment doit être exposé.

Je suis vraiment confondu avec cela, mais j'ai fini par créer un énorme désordre de code qui remplace l'ouvrage et montrant et cacher les vues de la viewpager. J'aurais pensé qu'il existe un moyen plus simple d'utiliser des comportements par défaut pour effectuer la navigation appropriée.

tl; dr

A est un fragment d'hébergement de visual. B est un nouveau fragment.

Lorsque je remplace A avec B, puis appuyez sur Retour, je m'attends à naviguer vers un, mais cela ne se produit pas.

Tout conseil serait très apprécié.

Code:

Activité principale:

  @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);

        headingLayout = (RelativeLayout) findViewById(R.id.headingLayout);
        headingLayout.setVisibility(View.GONE);

        // Set up the ViewPager, attaching the adapter and setting up a listener
        // for when the
        // user swipes between sections.
        mViewPager = (ViewPager) findViewById(R.id.pager);

        mViewPager.setPageMargin(8);

        /** Getting fragment manager */
        FragmentManager fm = getSupportFragmentManager();

        /** Instantiating FragmentPagerAdapter */
        MyFragmentPagerAdapter pagerAdapter = new MyFragmentPagerAdapter(fm);

        /** Setting the pagerAdapter to the pager object */
        mViewPager.setAdapter(pagerAdapter);
.
.
.
}

    public void onListItemClicked(Fragment fragment) {
        fromPlayer = false;
        InitiateTransaction(fragment, true);

    }


    public void InitiateTransaction(Fragment fragment, boolean addToBackStack) {

        invalidateOptionsMenu();

        FragmentManager fm = getSupportFragmentManager();
        FragmentTransaction ft = fm.beginTransaction();

        ft.replace(R.id.fragmentContainer, fragment).addToBackStack(null)
                .commit();

    }

Pageradapter:

package another.music.player;

import Android.os.Bundle;
import Android.support.v4.app.Fragment;
import Android.support.v4.app.FragmentManager;
import Android.support.v4.app.FragmentPagerAdapter;
import another.music.player.fragments.AlbumListFragment;
import another.music.player.fragments.ArtistListFragment;
import another.music.player.fragments.SongListFragment;

public class MyFragmentPagerAdapter extends FragmentPagerAdapter {

    final int PAGE_COUNT = 3;

    /** Constructor of the class */
    public MyFragmentPagerAdapter(FragmentManager fm) {
        super(fm);
    }

    /** This method will be invoked when a page is requested to create */
    @Override
    public Fragment getItem(int i) {
        switch (i) {
        case 0:
            ArtistListFragment artistListFragment = new ArtistListFragment();
            Bundle artistData = new Bundle();
            artistData.putInt("current_page", i + 1);
            artistListFragment.setArguments(artistData);
            return artistListFragment;

        case 1:
            AlbumListFragment albumListFragment = new AlbumListFragment();
            Bundle albumData = new Bundle();
            albumData.putInt("current_page", i + 1);
            albumData.putBoolean("showHeader", false);
            albumListFragment.setArguments(albumData);
            return albumListFragment;

        default:

            SongListFragment songListFragment = new SongListFragment();
            Bundle songData = new Bundle();
            songData.putInt("current_page", i + 1);
            songListFragment.setArguments(songData);
            return songListFragment;
        }
    }

    /** Returns the number of pages */
    @Override
    public int getCount() {
        return PAGE_COUNT;
    }

    @Override
    public CharSequence getPageTitle(int position) {
        switch (position) {
        case 0:
            return "Artists";

        case 1:
            return "Albums";

        default:
            return "Songs";
        }
    }
}

xML principal (contenant fragmentContainer & ViewPager):

<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:tools="http://schemas.Android.com/tools"
    Android:id="@+id/main_layout"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:background="@drawable/app_background_ics" >

    <RelativeLayout
        Android:id="@+id/headingLayout"
        Android:layout_width="match_parent"
        Android:layout_height="56dp" >
    </RelativeLayout>

    <FrameLayout
        Android:id="@+id/fragmentContainer"
        Android:layout_width="fill_parent"
        Android:layout_height="fill_parent"
        Android:layout_below="@+id/headingLayout" />

    <Android.support.v4.view.ViewPager
        Android:id="@+id/pager"
        Android:layout_width="fill_parent"
        Android:layout_height="fill_parent" >

        <Android.support.v4.view.PagerTabStrip
            Android:id="@+id/pager_title_strip"
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content"
            Android:background="#33b5e5"
            Android:paddingBottom="4dp"
            Android:paddingTop="4dp"
            Android:textColor="#fff" />
    </Android.support.v4.view.ViewPager>

</RelativeLayout>
30
Tim Malseed

J'ai aussi eu ce même problème depuis longtemps. La solution s'avère très simple et vous n'avez pas besoin de hacks avec la visibilité de la viewpager. Je suis décrit dans cet autre SO QUESTION CONNEXE: Fragment dans la viewpager non restauré après la pop-pbackstack

Cependant, pour le rendre simple, tout ce dont vous avez besoin est d'utiliser GetChildFragmentManager () dans votre adaptateur ViewPager, au lieu de GetsUpportfragmentManager (). Donc, au lieu de cela:

    /** Getting fragment manager */
    FragmentManager fm = getSupportFragmentManager();

    /** Instantiating FragmentPagerAdapter */
    MyFragmentPagerAdapter pagerAdapter = new MyFragmentPagerAdapter(fm);

    /** Setting the pagerAdapter to the pager object */
    mViewPager.setAdapter(pagerAdapter);

Tu fais cela:

    /** Getting fragment manager */
    FragmentManager fm = getChildFragmentManager();

    /** Instantiating FragmentPagerAdapter */
    MyFragmentPagerAdapter pagerAdapter = new MyFragmentPagerAdapter(fm);

    /** Setting the pagerAdapter to the pager object */
    mViewPager.setAdapter(pagerAdapter);
37
Felipe Lima

Mise à jour :
[.____] Ce n'est pas la "façon Android" et il en résulte une mauvaise expérience utilisateur pour le cas d'une liste de réception. Au lieu de cela, créez une nouvelle activité.

Pour les personnes recherchant une solution simple à ce problème, je vais simplement résumer ce que j'ai fait.

Mon architecture:

  • ViewPager en fragmentation (action d'action en fait, pour la prise en charge de la barre d'action. Mais Actionbaractivity implémente la fragmentivité).

  • 2 onglets:

    • FragmentContainer1 qui étend le fragment.
    • FragmentContainer2 qui prolonge le fragment.

Pour chaque fragmentContainer, nous appelons GetChildFragmentManager, dans la méthode Oncreate, par exemple, et ajoutez le fragment que nous voulons montrer dans ce conteneur:

FragmentToShow fragment = new FragmentToShow();

getChildFragmentManager()
        .beginTransaction()
        .add(R.id.container, fragment)
        .commit();

Nous ne voulons pas que notre premier fragment soit ajouté à l'arrière-plan du conteneur de fragments car nous ne voulons pas montrer le conteneur de fragments si nous appuyions sur le bouton arrière.

Ensuite, si nous voulons remplacer FragmentToshow par un autre fragment dans notre classe de fragmenttososhow (comme avec une liste de liste):

Fragment itemFragment = new ItemFragment();

getFragmentManager()
        .beginTransaction()
        .replace(R.id.container, itemFragment)
        .addToBackStack(null)
        .commit();

Ici, nous récupérons le gestionnaire de fragments d'enfant et nous ajoutons le produit de l'article à la pile arrière.

Alors maintenant, nous voulons, à l'appui du bouton arrière, pour revenir à la liste ListView (l'instance FragmentTsoshow). Notre activité (fragmentactivité) est la seule au conscience du bouton arrière, nous devons donc remplacer la méthode surbackprimé () dans cette activité:

@Override
public void onBackPressed() {

    // We retrieve the fragment manager of the activity
    FragmentManager frgmtManager = getSupportFragmentManager();

    // We retrieve the fragment container showed right now
    // The viewpager assigns tags to fragment automatically like this
    // mPager is our ViewPager instance
    Fragment fragment = frgmtManager.findFragmentByTag("Android:switcher:" + mPager.getId() + ":" + mPager.getCurrentItem());

    // And thanks to the fragment container, we retrieve its child fragment manager
    // holding our fragment in the back stack
    FragmentManager childFragmentManager = fragment.getChildFragmentManager();

    // And here we go, if the back stack is empty, we let the back button doing its job
    // Otherwise, we show the last entry in the back stack (our FragmentToShow) 
    if(childFragmentManager.getBackStackEntryCount() == 0){
        super.onBackPressed();
    } else {
        childFragmentManager.popBackStack();
    }
}

Depuis que nous appelons GetupportfragmentManager dans notre activité, nous pouvons simplement appeler GetFragmentManager dans nos fragments d'enfant. Cela rendra une instance de fragmentManager de support.

Et c'est tout! Je ne suis pas un expert, alors si vous avez des suggestions ou des remarques, n'hésitez pas.

9
Menerve

La seule façon de réaliser cela est de faire ce qui suit:

Lors de la navigation loin du point de vue, envoyez le point de vue de la vue sur Visiblity.Gone. Ajoutez des transactions de fragment à l'arrière-plan.

Lorsque vous retournez à l'écran ViewPager (via une presse à dos), remplacez l'ONBACKPRESSED. Vous pouvez vérifier combien de fragments sont dans la poitrine. Si le point de vue a été la première vue avant que des transactions de fragments aient eu lieu, vous pouvez vérifier si le décompte de l'entrée de fragment à l'arrière est de 0.

fragmentManager.getbacksttactCountCount () == 0, il n'y a pas de fragments dans l'arrière-plan.

Si cette déclaration est vraie, rapprochez-vous simplement l'affichage de la vue en utilisant la visibilité.Visible.

3
Tim Malseed

Je pense avoir eu un problème très similaire.

Il semble que FragmentManagers se comportent de manière quelque peu hiérarchique. La façon dont j'ai résolu ce problème, était d'utiliser le fragment de fragment "principal" de l'activité, qui héberge le conteneur et le visual, et non celui qui peut être récupéré des fragments à l'intérieur du visionneur.

Pour ce faire, j'ai utilisé:

this.getActivity().getSupportFragmentManager()

this est une instance de fragment.

Maintenant, si je navigue d'un élément dans la fenêtre de vie à un autre fragment avec une transaction "remplacer", je peux voir le visual de l'état que je suis parti.

Plus d'échantillons de code complets ressemble à ceci:

FragmentManager fragmentManager =  MyCurrentFragment.this.getActivity().getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();

transaction.replace(R.id.container, newFragment);
transaction.addToBackStack(null);

transaction.commit();
0
Tadas Šubonis

Si vous utilisez un ViewPager contenant Fragments qui peut démarrer Activities, voici la manière dont vous naviguez correctement dans la position dans le ViewPager, sur la touche dos ou naviguer à partir de ladite Activity (suppose que vous avez une navigation ascendante déclarée pour votre Activities).

Tout d'abord, vous devez passer la position actuelle du ViewPager comme un supplément dans le Intent pour démarrer le nouveau Activity.

Ensuite, vous transmettez cette position au parent Activity faire ceci:

Intent upIntent = NavUtils.getParentActivityIntent(this);
upIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
upIntent.putExtra(FeedPagerActivity.EXTRA_POSITION, position);
NavUtils.navigateUpTo(this, upIntent);

Mettre ce code dans

oNOPTIONSITEMMELLECIDE (NOTE MENUITEM)

0
Sakiboy