解释:
我从 Activity A 开始一个 Activity 转换。
启动新的 Activity B 后,我更改了 B 中某些 View (
View.GONE
) 的可见性状态。
问题是:
当启动一个新的 Activity C 并返回到 Activity B(或在 B 中强制执行一个 onPause)时,具有已更改可见性状态的 View 将再次出现,而无需通过代码或其他方式接触 View 。
以下视频用图片解释了这个问题:https://youtu.be/oqCZo5CSkQk
当不使用过渡时,一切都按预期工作。有谁知道恢复 Activity 时如何防止 View 状态丢失?我是否使用了错误的 ActivityOptionsCompat
?
我使用支持库:
'com.android.support:support-v4:27.1.1'
和
'com.android.support:appcompat-v7:27.1.1'
但这个问题也出现在旧版本和不同的手机制造商(Pixel、三星等)上。
这里是重现问题的代码:
布局
Activity A:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical">
<TextView
style="@style/TextAppearance.AppCompat.Title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="24dp"
android:gravity="center"
android:text="Activity A | this starts the transition to another activity"/>
<android.support.v7.widget.AppCompatImageView
android:id="@+id/imageToAnimate"
android:layout_width="20dp"
android:layout_height="20dp"
app:srcCompat="@android:drawable/star_big_on"/>
<Button
android:id="@+id/start_next_activity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:text="start Another Activity"/>
</LinearLayout>
Activity B:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<TextView
style="@style/TextAppearance.AppCompat.Title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="24dp"
android:gravity="center"
android:text="Activity B | with progressbar"/>
<android.support.v7.widget.AppCompatImageView
android:id="@+id/imageToAnimate"
android:layout_width="100dp"
android:layout_height="100dp"
android:transitionName="toAnimate"
app:srcCompat="@android:drawable/star_big_on"/>
<ProgressBar
android:id="@+id/progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:visibility="gone"/>
<TextView
android:id="@+id/dismiss_text"
style="@style/TextAppearance.AppCompat.Subhead"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="24dp"
android:text="Also a text to dismiss"/>
<Button
android:id="@+id/show"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="SHOW"/>
<Button
android:id="@+id/hide_gone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="SET GONE"/>
<Button
android:id="@+id/hide_invisible"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="SET INVISIBLE"/>
<Button
android:id="@+id/start_activity_c"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="START activity"/>
</LinearLayout>
Activity C:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<TextView
style="@style/TextAppearance.AppCompat.Title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Activity C"
android:textSize="40sp"/>
</LinearLayout>
Activity 源码
Activity A:
public class DebugActivityA extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_a);
findViewById(R.id.start_next_activity).setOnClickListener(v -> startWithTransition());
}
private void startWithTransition() {
ActivityOptionsCompat options = ActivityOptionsCompat
.makeSceneTransitionAnimation(DebugActivityA.this,
findViewById(R.id.imageToAnimate),
"toAnimate");
startActivity(new Intent(DebugActivityA.this, DebugActivityB.class), options.toBundle());
}
}
Activity B:
public class DebugActivityB extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_b);
View progressbar = findViewById(R.id.progress);
View dismissText = findViewById(R.id.dismiss_text);
progressbar.setVisibility(View.VISIBLE);
findViewById(R.id.show).setOnClickListener(v -> {
progressbar.setVisibility(View.VISIBLE);
dismissText.setVisibility(View.VISIBLE);
});
findViewById(R.id.hide_gone).setOnClickListener(v -> {
progressbar.setVisibility(View.GONE);
dismissText.setVisibility(View.GONE);
});
findViewById(R.id.hide_invisible).setOnClickListener(v -> {
progressbar.setVisibility(View.INVISIBLE);
dismissText.setVisibility(View.INVISIBLE);
});
findViewById(R.id.start_activity_c).setOnClickListener(this::startOtherActivity);
}
private void startOtherActivity(View view) {
startActivity(new Intent(this, DebugActivityC.class));
}
}
Activity C:
public class DebugActivityC extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_c);
}
}
最佳答案
您可以使用 onSaveInstanceState
方法在您离开 Activity 时保存 UI 的状态,然后使用 onRestoreInstanceState
将其恢复到该状态。
将 onSaveInstanceState
添加到 Activity B:
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
// Save UI state changes to the savedInstanceState.
// This bundle will be passed to onCreate if the process is
// killed and restarted.
savedInstanceState.putInt("progressbarVisibility", progressbar.getVisibility());
savedInstanceState.putInt("dismissTextVisibility", dismissText.getVisibility());
}
然后修改Activity B的onCreate
方法:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_multi_play);
View progressbar = findViewById(R.id.progress);
View dismissText = findViewById(R.id.dismiss_text);
if (savedInstanceState != null){
dismissText.setVisibility(savedInstanceState.getInt("dismissTextVisibility", View.VISIBLE));
progressbar.setVisibility(savedInstanceState.getInt("progressbarVisibility", View.VISIBLE));
}
// The rest of your code.
}
关于android - 使用先前启动的 Activity 转换恢复 Activity 时查看可见性状态丢失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50969390/