您可以下载我的整个项目来尝试调试。这是我整个代码的仓库链接:https://bitbucket.org/lexic92/studio48/。
我在尝试用一个空白片段替换另一个空白片段时,出现了“幽灵片段”转换的问题。
如何重现该问题: 我有一个导航抽屉,当我点击其中一项时,它会打开一个填满整个屏幕的片段。
导航抽屉:
当我注释掉两行代码 ".setTransition" 并取消注释两行代码 ".setCustomAnimations" 时,会出现相同的问题。这是自定义动画:
如何使转换过程平稳,不出现“幽灵”片段?
规格:我正在运行 android.support.v7.app.ActionBarActivity,minSdkVersion == 15 和 targetSdkVersion == 21,在 Google Nexus 5 物理设备上(而非模拟器)。
我的猜测答案是:
这个网站似乎给了我提示:http://gotoanswer.com/?q=Android+Animation+within+a+Fragment+not+working。
对我来说,这是关于片段动画的 zPosition 的一个 bug。你看到的是新片段“出现”,因为新片段被附加在当前片段下面。所以,当尝试将一个片段“覆盖”在已存在的片段上时,它似乎什么都没有发生,然后新的片段就“出现”了。我尝试了许多解决方法,比如调整 zPosition(只影响窗口而不是布局,因此对片段没有影响)、在 onAnimationCreate() 中将根布局置于前端,甚至在动画开始和停止时...好像什么也没用。所以,在目前这个时点上,除非编写完全定制的片段转换动画,否则它们还有一些小问题。你可能需要尝试使用 .add(Fragment) 添加片段,等待其添加完成,然后调用 .remove(Fragment) 删除旧片段,这样新片段就会物理放置在现有片段的上方。
我注意到 SongDetailActivity.java 实例化时会调用这段代码,即使我没有点击导航抽屉:
也许当前的片段正在向这个“基础”片段逐渐消失,正如引文所示,然后才会淡入新的片段?
我还将这两个片段的布局(一个空白,一个有很多文本)复制并粘贴到同一个布局中,作为FrameLayout父布局的子项:
它的功能很好,但我不知道如何让它淡入淡出。但这是一个单独的堆栈溢出问题。如果有人解决了幽灵片段谜团,我非常想知道答案。但我决定现在不浪费时间去尝试弄清楚它,特别是过去证明片段转换存在错误(就像在那篇文章中一样)。
我在尝试用一个空白片段替换另一个空白片段时,出现了“幽灵片段”转换的问题。
如何重现该问题: 我有一个导航抽屉,当我点击其中一项时,它会打开一个填满整个屏幕的片段。
导航抽屉:
- 按钮1 - 带文本的片段
按钮2 - 空的片段
当我打开应用程序时,它从带文本的片段开始。然后,我打开导航抽屉并点击按钮2。转换不好,屏幕会在一瞬间变成空白,然后再切换回淡入文字,直到变成了空白屏幕。
如果我打开导航抽屉并再次点击按钮2,它会从完整的文本淡出到空白屏幕。因此,在一瞬间,它显示了不应该显示的带有文本的片段。我通过调试模式逐步运行我的应用程序,来放慢速度,并验证实际发生了这种行为。
如果我打开导航抽屉并第三次再次点击按钮2,则正确地不显示任何动画,因为它正在淡出到相同的屏幕。
有人知道为什么会出现这种情况吗?您认为这与导航抽屉有关吗?
这里有我全部代码的存储库:https://bitbucket.org/lexic92/studio48/ 以下是一些代码片段:SongDetailActivity.java:
@Override
public void onNavigationDrawerItemSelected(int position) {
// update the main content by replacing fragments
FragmentManager fragmentManager = getSupportFragmentManager();
//OPEN THE BLANK SCREEN
if(position == 1) {
fragmentManager.beginTransaction()
//.setCustomAnimations(R.anim.fade_in, R.anim.fade_out)
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
.replace(R.id.songlist_detail_container, PlaceholderFragment.newInstance(position + 1, mSongId))
.commit();
}
//OPEN THE SCREEN WITH TEXT
else {
SongDetailFragment sdf = new SongDetailFragment();
Bundle args = new Bundle();
args.putString(SongDetailFragment.ARG_ITEM_ID, mSongId);
sdf.setArguments(args);
fragmentManager.beginTransaction()
//.setCustomAnimations(R.anim.fade_in, R.anim.fade_out)
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
.replace(R.id.songlist_detail_container, sdf)
.commit();
}
}
当我注释掉两行代码 ".setTransition" 并取消注释两行代码 ".setCustomAnimations" 时,会出现相同的问题。这是自定义动画:
res/anim/fade_out.xml:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha android:fromAlpha="1.0" android:toAlpha="0.0"
android:duration="@android:integer/config_mediumAnimTime" />
</set>
res/anim/fade_in.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
android:duration="@android:integer/config_mediumAnimTime" />
</set>
如何使转换过程平稳,不出现“幽灵”片段?
规格:我正在运行 android.support.v7.app.ActionBarActivity,minSdkVersion == 15 和 targetSdkVersion == 21,在 Google Nexus 5 物理设备上(而非模拟器)。
我的猜测答案是:
这个网站似乎给了我提示:http://gotoanswer.com/?q=Android+Animation+within+a+Fragment+not+working。
对我来说,这是关于片段动画的 zPosition 的一个 bug。你看到的是新片段“出现”,因为新片段被附加在当前片段下面。所以,当尝试将一个片段“覆盖”在已存在的片段上时,它似乎什么都没有发生,然后新的片段就“出现”了。我尝试了许多解决方法,比如调整 zPosition(只影响窗口而不是布局,因此对片段没有影响)、在 onAnimationCreate() 中将根布局置于前端,甚至在动画开始和停止时...好像什么也没用。所以,在目前这个时点上,除非编写完全定制的片段转换动画,否则它们还有一些小问题。你可能需要尝试使用 .add(Fragment) 添加片段,等待其添加完成,然后调用 .remove(Fragment) 删除旧片段,这样新片段就会物理放置在现有片段的上方。
我注意到 SongDetailActivity.java 实例化时会调用这段代码,即使我没有点击导航抽屉:
//OPEN THE SCREEN WITH TEXT
else {
SongDetailFragment sdf = new SongDetailFragment();
Bundle args = new Bundle();
args.putString(SongDetailFragment.ARG_ITEM_ID, mSongId);
sdf.setArguments(args);
fragmentManager.beginTransaction()
//.setCustomAnimations(R.anim.fade_in, R.anim.fade_out)
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
.replace(R.id.songlist_detail_container, sdf)
.commit();
}
也许当前的片段正在向这个“基础”片段逐渐消失,正如引文所示,然后才会淡入新的片段?
我的解决方案
注:我并没有把这个作为答案,因为它在技术上并没有回答我的问题,但这是我能想到的最好的备选方案。
我尝试查看是否在没有动画时问题得到了解决。这个“幽灵片段”没有出现,但我注意到加载片段需要花费一瞬间的时间,看起来很突兀和丑陋。我想要一个流畅的应用程序,如果在没有动画时它不流畅,那么即使我修复了幽灵片段的错误,它也可能是无望的。我了解到片段只是有缺陷的(请参见here)。
我决定隐藏和显示视图。这是我的新代码:
SongDetailActivity.java
//---------- NAVIGATION DRAWER -------------
@Override
public void onNavigationDrawerItemSelected(int position) {
//HOME
if (position == 0) {
}
//LYRICS
else if(position == 1) {
findViewById(R.id.lyrics).setVisibility(View.VISIBLE);
findViewById(R.id.info).setVisibility(View.INVISIBLE);
}
//INFO
else if(position == 2) {
findViewById(R.id.info).setVisibility(View.VISIBLE);
findViewById(R.id.lyrics).setVisibility(View.INVISIBLE);
}
}
我还将这两个片段的布局(一个空白,一个有很多文本)复制并粘贴到同一个布局中,作为FrameLayout父布局的子项:
fragment_songlist_detail.xml:
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent"
android:background="#f8bbd0"
android:layout_width="match_parent"
>
<LinearLayout
android:id="@+id/lyrics"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
...
</LinearLayout>
<LinearLayout
android:id="@+id/info"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
...
</LinearLayout>
</FrameLayout>
它的功能很好,但我不知道如何让它淡入淡出。但这是一个单独的堆栈溢出问题。如果有人解决了幽灵片段谜团,我非常想知道答案。但我决定现在不浪费时间去尝试弄清楚它,特别是过去证明片段转换存在错误(就像在那篇文章中一样)。