web-dev-qa-db-fra.com

Créer des fragments en plein écran par programmation

J'ai un ViewPager et FragmentPagerAdapter mis en place dans une activité avec 3 fragments. Tous les fragments sont chargés simultanément et sont gardés en mémoire en utilisant

mPager.setOffscreenPageLimit(2);

L'un de ces fragments héberge un aperçu de la caméra que je souhaite effectuer en plein écran, sans barre d'état ni barre d'action. Les autres fragments nécessitent que la barre d'action soit affichée.

Comment ferais-je que le fragment d'aperçu de la caméra en plein écran tout en maintenant les deux autres fragments normaux? J'ai essayé d'utiliser des thèmes, ce qui signifie casser la barre d'action. 

Appeler par programme ce qui suit n’aide en rien, car cela force toute l’activité à être en plein écran (et donc les deux autres fragments avec elle):

requestWindowFeature(Window.FEATURE_NO_TITLE); 
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.main);

J'ai également essayé d'implémenter ViewPager.OnPageChangeListener:

public void onPageSelected(int position) {
    if(position == 1)
        getActionBar().hide();
    else
        getActionBar().show();
}

Cela masque la barre d'action, mais pas la barre d'état du système (je parle de l'emplacement des notifications, des icônes d'état et de l'heure), et l'animation masquer/afficher de la barre d'action est également très agitée lors du balayage.

Pour un exemple de ce que je veux faire exactement, voir Snapchat - ils parviennent à glisser parfaitement entre la caméra et d'autres fragments.

Modifier:

J'ai donc changé mon onPageSelected en ceci:

public void onPageSelected(int position) {
    if(position == 1) {
        MainActivity.this.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
        MainActivity.this.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
    } else {
        MainActivity.this.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
        MainActivity.this.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
    }
}

Cela me permet de changer si la barre d'état est affichée ou non. Cependant, il provoque une grande quantité de jank. Même problème avec la barre d'action.

Je remarque que, dans Snapchat, la barre d'état glisse vers le haut et le bas une fois le changement d'onglet terminé. Je ne suis pas sûr de savoir comment mettre cela en œuvre, alors tout conseil concernant cet aspect serait apprécié.

19
Eric Ahn

J'ai compris comment faire cela, même si c'est définitivement un bidouillage.

L'astuce consiste à ne pas utiliser la barre d'action Android, mais bien à créer le vôtre dans vos fichiers de mise en page.

J'ai défini deux autres RelativeLayouts dans mon code:

<RelativeLayout
    Android:id="@+id/padding"
    Android:layout_width="fill_parent"
    Android:layout_height="25dip"
    Android:layout_alignParentTop="true"
    Android:background="@color/abs__background_holo_dark" />

<RelativeLayout
    Android:id="@+id/fake_action_bar"
    Android:layout_width="fill_parent"
    Android:layout_height="48.0dip"
    Android:layout_below="@id/padding" >

<!-- stuff here -->

</RelativeLayout>

Le haut de la page RelativeLayout remplit la barre d’état Android. Je l'ai réglé sur 25dip, mais cela peut varier - il serait probablement préférable de définir cette valeur par programme. Vous devez également définir une couleur noire pour qu'elle corresponde à la couleur de la barre d'état et donne à l'interface utilisateur un aspect plus naturel.

Le RelativeLayout en bas est pour votre fausse barre d'action. Vous devez remplir tout ce dont votre barre d’action a besoin (texte du titre, boutons, etc.) dans RelativeLayout. Je l'ai réglé sur 48dip, mais encore une fois, cela va varier et vous devriez probablement le définir par programme.

Dans l'activité hébergeant vos Fragments, ViewPager et FragmentPagerAdapter, vous devez définir les indicateurs indiquant à Android de transformer la barre d'état en superposition:

WindowManager.LayoutParams params = getWindow().getAttributes();
params.flags |= WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;

Nous devons maintenant masquer et afficher la barre d'état lorsque nous changeons de fragments. Demandez à votre activité d'implémenter ViewPager.OnPageChangeListener, puis utilisez le code suivant:

@Override
public void onPageScrollStateChanged(int state) {
    switch(state) {
    case ViewPager.SCROLL_STATE_IDLE:
        if(mPosition == 1) {
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
            getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
        } else {
            getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
        }
    }
}

@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

}

@Override
public void onPageSelected(int position) {
    mPosition = position;
}

Nous gardons trace du numéro de page en utilisant onPageSelected et l’utilisons dans onPageScrollStateChanged pour masquer/afficher de manière dynamique la barre d’état en fonction du fragment actuellement affiché. Vous ne pouvez pas le faire dans onPageSelected, car la barre d'état s'affichera à mi-parcours.

Vous devez également vous assurer d'ajouter le code approprié pour votre fausse barre d'actions. Pour les boutons, il s'agira de OnClickListener.

12
Eric Ahn

Tout d’abord, dans l’activité/le fragment que vous voulez masquer la barre d’état:.

public static Fragment QSFrag;
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    QSFrag = this;
}

Puis dans votre onPageSelected:

public void onPageSelected(int position) {
        // TODO Auto-generated method stub
        if(position == 1){
            mActionBar.hide();              


            YourActivityWithNoStatusOrActionBar.QSFrag.getActivity().getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);


        }else{

            mActionBar.show();
             // mActionBar.setSelectedNavigationItem(position); I use this, not sure u need/want it.
        }

    }

Je viens de le tester et ça marche. Mais cela n'a pas l'air génial de quitter le fragment sans barre d'état. : p

3
LordMarty