android:旧片段在转换后留在新片段之上

时间:2017-10-11 11:51:56

标签: android maven android-fragments

我遇到了一个关于android中片段转换的非常奇怪的错误。如果您在过渡动画期间将应用程序置于背景中,则始终可以重现。如果我在向后转换中从片段B转到片段A,片段B在片段A的顶部保持可见。视图层次结构不显示片段B的任何痕迹,片段B的可见元素不可点击,而是点击在下面的片段A的重叠元素上注册。

我在这里创建了一个关于错误的简短视频:https://imgur.com/In5IZub

为了弄清楚出了什么问题,我创建了一个新的应用程序,并努力设置我现有的应用程序。那时我可以本地化错误的来源:

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

在我的顶级build.gradle文件中。为什么会导致我的应用程序出现故障?这对我来说似乎是个大问题。

顶级build.gradle的完整内容:

// 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" }
  }
}

我的应用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'
}

如果我从顶级gradle文件中删除存储库maven.google.com,则转换按预期工作。

如果没有这种奇怪的副作用,我做错了什么阻止我使用这个存储库?

编辑:添加转换代码

前进过渡:

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();

向后过渡只是:

onBackPressed();

更新

问题不在于repo本身,而在于支持库的版本。本地我只有v26.0.0-alpha1,它似乎在动画问题上完美无缺。我尝试获取存储库的这个确切版本,它没有引起任何问题。我想现在我必须弄清楚为什么我的代码与支持库v26.0.0-alpha1一样工作,但没有任何更新的版本。我最初使用v25.1.0发现了这个问题,所以我仍然没有更接近解决方案,因为它已经出现在神奇版本v26.0.0-alpha1之前,现在也在该版本之后。我认为其他应用可能会遇到同样的问题,但浏览我已安装的应用时,我无法找到使用相同类型的转换。

1 个答案:

答案 0 :(得分:0)

我找到了修复!我的所有片段都使用FragmentBase作为它们的超类。在FragmentBase中,我保留了对onCreateAnimations中创建的动画的引用,并且我写了一个函数来在我想的时候取消这些动画。

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;
    }
}

在我的MainActivity中,我保留对当前可见片段(FragmentBase实例)的引用,并在onPause()中调用它们的interruptAnimation()方法。

public class MainActivity extends AppCompatActivity {

    FragmentBase _currentFragment;
    FragmentBase _previousFragment;

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

在MainActivity中的OnBackStackChangedListener I注册中,对_currentFragment和_previousFragment的引用发生了变化。