2017-10-11 7 views
0

J'ai rencontré un bug très particulier concernant les transitions de fragments dans android. Il est toujours reproductible si vous mettez votre application en arrière-plan pendant l'animation de la transition. Si je passe du fragment B au fragment A dans la transition vers l'arrière, le fragment B reste visible au-dessus du fragment A. La hiérarchie de vue ne montre aucune trace du fragment B et les éléments visibles du fragment B ne sont pas cliquables. enregistré sur les éléments superposés du fragment A en dessous.android: les anciens fragments restent sur les nouveaux fragments après la transition

J'ai créé une courte vidéo du bug ici: https://imgur.com/In5IZub

Pour comprendre ce qui a mal tourné, j'ai créé une nouvelle application et moi-même travaillé à la configuration de mon application existante. C'est quand je pouvais localiser la source du bug:

maven { url "https://maven.google.com" }

dans mon fichier build.gradle haut niveau. Pourquoi cela provoque-t-il un dysfonctionnement de mon application? Cela semble être un énorme problème pour moi.

contenu complet de build.gradle haut niveau:

// Top-level build file where you can add configuration options common to 
all sub-projects/modules. 

buildscript { 
    repositories { 
    jcenter() 
    } 
    dependencies { 
    classpath 'com.android.tools.build:gradle:2.3.3' 

    // NOTE: Do not place your application dependencies here; they belong 
    // in the individual module build.gradle files 
    } 
} 

allprojects { 
    repositories { 
    jcenter() 
    maven { url "https://maven.google.com" } 
    } 
} 

contenu intégral de mon application build.gradle:

apply plugin: 'com.android.application' 

android { 
    compileSdkVersion 26 
    buildToolsVersion "26.0.2" 
    defaultConfig { 
    applicationId "com.example.mschaidinger.fragmenttransitiontest" 
    minSdkVersion 17 
    targetSdkVersion 26 
    versionCode 1 
    versionName "1.0" 
    testInstrumentationRunner 
    "android.support.test.runner.AndroidJUnitRunner" 
    } 
    buildTypes { 
    release { 
     minifyEnabled false 
     proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 
    } 
    } 
} 


dependencies { 
    compile fileTree(dir: 'libs', include: ['*.jar']) 
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 
    exclude group: 'com.android.support', module: 'support-annotations' 
    }) 
    compile "com.android.support:appcompat-v7:26.+" 
    compile "com.android.support:design:26.+" 
    compile 'com.android.support.constraint:constraint-layout:1.0.2' 
    testCompile 'junit:junit:4.12' 
} 

Si je supprime le dépôt maven.google.com du haut -level gradle fichier, la transition fonctionne comme prévu.

Qu'est-ce que j'ai fait de mal qui m'empêche d'utiliser ce dépôt sans cet effet secondaire?

EDIT: ajout d'un code de transition

transition vers l'avant:

transition vers l'arrière
FragmentTransaction openTransaction = getSupportFragmentManager().beginTransaction(); 

if (animate != ANIM_NONE) { 
    if (animate == ANIM_ENTER) { 
    openTransaction = openTransaction.setCustomAnimations(R.anim.enter, R.anim.exit, R.anim.pop_enter, R.anim.pop_exit); 
    } else { 
    openTransaction = openTransaction.setCustomAnimations(R.anim.pop_enter, R.anim.pop_exit, R.anim.pop_exit, R.anim.pop_enter); 
    } 
} 

openTransaction = openTransaction.replace(R.id.fragmentcontainer, fragment, String.valueOf(fragmentId)); 

if (addToBackStack) { 
    String transactionTag = "from" + oldFragmentId + "To" + fragmentId; 
    openTransaction.addToBackStack(transactionTag); 
} 

openTransaction.commitAllowingStateLoss(); 

est simplement:

onBackPressed(); 

UPDATE:

Le problème n'est pas avec le repo lui-même, mais plutôt avec la version des bibliothèques de support. Localement, j'ai seulement v26.0.0-alpha1 qui semble fonctionner parfaitement en ce qui concerne le problème d'animation. J'ai essayé d'aller chercher cette version exacte du dépôt et cela n'a causé aucun problème. Je suppose maintenant que je dois comprendre pourquoi mon code fonctionne comme prévu avec la bibliothèque de support v26.0.0-alpha1, mais pas avec une version plus récente. J'ai d'abord découvert le problème en utilisant v25.1.0, donc je ne suis toujours pas proche d'une solution, car il a été autour avant la version magique v26.0.0-alpha1 et maintenant aussi après cette version. Je pensais que d'autres applications pourraient avoir le même problème, mais en parcourant mes applications installées, je ne pouvais pas trouver tout en utilisant le même type de transition.

Répondre

0

J'ai trouvé une solution! Tous mes Fragments utilisent FragmentBase comme superclasse. Dans FragmentBase, je garde des références aux animations créées dans onCreateAnimations, et j'ai écrit une fonction pour annuler ces animations quand j'en ai envie.

public abstract class FragmentBase extends Fragment { 

    private AnimationSet animationWrapper; 

    public void interruptAnimation() { 
     if(animationWrapper != null) { 
      animationWrapper.setDuration(0); 
      animationWrapper.cancel(); 
     } 
    } 

    @Override 
    public AnimationSet onCreateAnimation(int transit, final boolean enter, final int nextAnim) { 
     Animation anim; 

     try { 
      anim = AnimationUtils.loadAnimation(getActivity(), nextAnim); 
     } catch (Resources.NotFoundException e) { 
      return null; 
     } 

     AnimationSet animationWrapper = new AnimationSet(false); 
     animationWrapper.addAnimation(anim); 
     this.animationWrapper = animationWrapper; 
     return this.animationWrapper; 
    } 
} 

Dans mon MainActivity, je garde les références aux fragments actuellement visibles (instances de FragmentBase) et OnPause() j'appelle leurs méthodes interruptAnimation().

public class MainActivity extends AppCompatActivity { 

    FragmentBase _currentFragment; 
    FragmentBase _previousFragment; 

    @Override 
    protected void onPause() { 
     if(_currentFragment != null) { 
      _currentFragment.interruptAnimation(); 
     } 
     if(_previousFragment != null) { 
      _previousFragment.interruptAnimation(); 
     } 
    } 
} 

Les références à _currentFragment et _previousFragment changement dans un OnBackStackChangedListener je me inscrire à MainActivity.