android - 使用先前启动的 Activity 转换恢复 Activity 时查看可见性状态丢失

标签 android android-layout android-activity

解释:

  • 我从 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/

相关文章:

Android - 在 TextView 中突出显示一个单词?

android - 如何在布局中将 TextView 居中?

java - 计算距离范围

android - 警报仅在我处于设置它的 Activity 中时触发

android - 多次按 "."(在 EditText 中输入时验证 ip 地址)

android - 使用 OpenCV 检测账单

android - 将自定义样式应用于 Android SpinnerItems

android - 错误 : A factory has already been set on this LayoutInflater (change background color of menu options)

android - 为什么 60dp 的文本会在 60dp TextView 中被剪裁?

android - 从 Actionbar 中删除设置菜单 inflator