web-dev-qa-db-fra.com

Décalage du tiroir de navigation sur Android

J'ai un problème avec le tiroir de navigation, il est trop lent, la solution que je recherche est de fermer le tiroir en premier, puis de montrer l'activité, mais cela ne fonctionne pas, je manque certainement quelque chose. 

private class DrawerItemClickListener implements ListView.OnItemClickListener {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int posicao, long id) {
            setLastPosition(posicao);
            setFragmentList(lastPosition);
            layoutDrawer.closeDrawer(linearDrawer);
        }
    }

    private OnClickListener userOnClick = new OnClickListener() {
        @Override
        public void onClick(View v) {
            layoutDrawer.closeDrawer(linearDrawer);
        }
    };

    private void setFragmentList(int posicao) {

        FragmentManager fragmentManager = getSupportFragmentManager();
        Fragment fragment = new FragmentViagens();

        switch (posicao) {

            case 0:
                fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).commit();
                break;
            case 1:
                fragmentManager.beginTransaction().replace(R.id.content_frame, new FragmentPedidos()).commit();
                break;
            case 2:
                fragmentManager.beginTransaction().replace(R.id.content_frame, new FragmentClientes()).commit();
                break;

        }

        navigationAdapter.setChecked(posicao, true);
        setTitleFragments(lastPosition);
        navigationAdapter.resetarCheck();
        layoutDrawer.closeDrawer(linearDrawer);

    }
13
AND4011002849

Vous pouvez le faire de cette façon pour éviter le décalage du tiroir, changez votre onItemClick:

layoutDrawer.closeDrawer(linearDrawer);
setLastPosition(posicao);
new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            setFragmentList(lastPosition);
        }
    }, 200);

Edit: le mode préféré devrait être de définir DrawerListener sur DrawerLayout et de définir votre fragment dans onDrawerClosed Comme ceci:

Fragment mFragmentToSet = null;

@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
    // Handle navigation view item clicks here.
    switch (item.getItemId()) {
        case R.id.nav_home:
            mFragmentToSet = HomeFragment.newInstance(); 
            break;
    }

    mDrawerLayout.closeDrawer(GravityCompat.START);
    return true;
}

mDrawerLayout.addDrawerListener(new DrawerLayout.DrawerListener() {
        @Override public void onDrawerSlide(View drawerView, float slideOffset) {}
        @Override public void onDrawerOpened(View drawerView) {}
        @Override public void onDrawerStateChanged(int newState) {}

        @Override
        public void onDrawerClosed(View drawerView) {
          //Set your new fragment here
          if (mFragmentToSet != null) {
            getSupportFragmentManager()
                  .beginTransaction()
                  .replace(FRAGMENT_CONTAINER_ID, mFragmentToSet)
                  .commit();
            mFragmentToSet = null;
          }
        }
    });
30
Yuraj

Plutôt que de faire une transaction dans onClick, pourquoi ne pas le faire dans onDrawerClosed from DrawerLayout.DrawerListener?

18
uDevel

Je pense avoir trouvé la meilleure solution pour cela! 

Commencez par faire votre transaction de fragment

new Handler().post(new Runnable() {
                @Override
                public void run() {
                    getSupportFragmentManager()
                            .beginTransaction()
                            .setCustomAnimations(Android.R.anim.fade_in, Android.R.anim.fade_out)
                            .replace(R.id.container, finalMenuFragment)
                            .commit();
                }
            });

Je sais qu’il est inutile de publier un fichier Runnable, mais ce hack évite les retards dans l’animation des clics sur le tiroir, surtout lorsque vous utilisez Android:background="?attr/selectableItemBackground" pour un élément cliquable.

Et puis vous fermez le tiroir AT LA FIN DE LA fonction onResume () de votre fragment (dans cet exemple, il s'agit de "finalMenuFragment") comme ceci:

 new Handler().post(new Runnable() {
        public void run() {

            mDrawerLayout.closeDrawer(mFragmentContainerView);
        }
    });

Encore une fois, je sais que cela semble stupide de publier un Runnable mais cela rend l’animation proche lisse.

De cette façon, le tiroir se fermera aussi vite que possible si vous voulez des animations fluides et si votre fragment ne contient pas beaucoup de vues, il se fermera plus rapidement et toujours sans décalage.

J'aimerais avoir des commentaires à ce sujet si quelqu'un testait cette solution, j'espère que cela aidera!

7
Quentin G.

Je viens de résoudre ce problème en seulement One-Line

accédez à votre fichier Manifest dans votre tiroir Activité Il suffit de mettre HardwareAccelerated true pour éviter les retards dans l'ouverture du tiroir

<activity
        Android:name=".activity.YourDrawerActivity"
        Android:configChanges="keyboardHidden|orientation"
        Android:screenOrientation="portrait"
        Android:hardwareAccelerated="true"  //important 
        Android:theme="@style/AppTheme.NoActionBar"
        Android:windowSoftInputMode="stateHidden" />
5
Darshan

Si cela prend du temps, vous pouvez demander une accélération matérielle . Si manifeste, ajoutez-le à votre activité.

 Android:hardwareAccelerated="true"

si votre méthode oncreate ajoute ce code

getWindow().setFlags(
    WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
    WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);

vous avez maintenant une accélération matérielle dans votre activité . source: https://developer.Android.com/guide/topics/graphics/hardware-accel.html

2
sajad abbasi

Essaye ça. Le tiroir sera dit de fermer en utilisant la diffusion. Ceci permet de s'assurer que l'activité ou le fragment en cours de chargement est terminé avant la fermeture du tiroir.

Dans MainActivity

private BroadcastReceiver xBroadcastReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (Drawer.isDrawerOpen(GravityCompat.START)){
            Drawer.closeDrawers();
        }
    }
};

@Override
protected void onStart() {
    super.onStart();
    IntentFilter filter = new IntentFilter();
    filter.addAction("my.drawer.listener");
    this.registerReceiver(xBroadcastReceiver, filter);
}

@Override
public void onDestroy() {
    super.onDestroy();
    this.unregisterReceiver(xBroadcastReceiver);
}

Activité interne ou fragment

@Override
public void onStart() {
    super.onStart();
    Intent intent = new Intent();
    intent.setAction("my.drawer.listener");
    getActivity().sendBroadcast(intent);
}

vous pouvez le remplacer par onCreate ou onAttach par un processus antérieur, mais cela dépend de votre application.

1
Azizi Musa

Je pense que l’utilisation de retards pour les transactions fragmentées est la solution la plus instable.

Celui qui les exécute onDrawerClosed vous laisse un léger décalage entre la fermeture et l'apparition des fragments.

Je préfère effectuer la transaction immédiatement après le clic de navigation, fermer le tiroir après avec postDelayed 200ms (dans le contrôle exécutable au cas où il n’est pas nul) . Le fragment s’ouvre juste avant que le tiroir ne commence à se fermer.

Non seulement le délai du robinet jusqu'à la fermeture du tiroir est-il plus court que celui qui suit la fermeture du tiroir et l'apparition du fragment suivant, mais il vaut mieux UX car l'utilisateur retire son doigt de l'écran - le délai est moins apparent.

0
Deividas Strioga