【问题标题】:Android - screen orientation reloads activityAndroid - 屏幕方向重新加载活动
【发布时间】:2016-12-28 02:07:10
【问题描述】:

我要重新问这个问题,因为那里有太多不好的信息,这真的令人沮丧。简短的故事是,当设备方向发生变化时,我不希望任何事情发生变化或发生。针对这个问题给出的两个最流行的“解决方案”是:

1.您可以通过在清单中添加android:screenOrientation="portrait"(或“landscape”)来将活动锁定在一个方向。

2.您可以通过在标签中指定 android:configChanges="screenOrientation" 来告诉系统您打算自己处理屏幕更改。这样,Activity 将不会被重新创建,而是会收到一个回调(您可以忽略它,因为它对您没有用处)。

这些都不起作用。所以让我更详细地解释我的特殊问题......

我正在尝试一个非常简单的应用程序作为学习练习。我在服务器上有一个文本文件。文本文件中有 1 件事:单行上的单个整数。这个数字是同时存储在这个服务器上的图像文件的数量,并且图像都被命名​​为0.jpg、1.jpg、2.jpg等。

我的所有代码都在我的活动的 onCreate 方法中(就像我说它是一个简单的应用程序)。

应用程序在运行时会执行以下操作:

从文本文件中读取数字。 生成一个从零到文件中数字的随机数。 使用 URL 中的随机数将随机图像加载到 imageview 中。

当屏幕旋转时,我不希望这一切再次发生。我只是不想发生任何事情......除了屏幕应该明显旋转并且图像应该缩放以适应,它确实如此。但每次屏幕旋转时,所有代码都会运行并选择一个新的随机图像。有人可以给我一个简单的解决方案和工作代码来解决这个问题吗?我通过看到来学习,所以如果您不能提供代码示例,它将无济于事。

提前致谢。

ps...我不是在寻找一种不同的方式来做我正在做的事情,这不是重点。我希望按照我目前的方式进行修复。

【问题讨论】:

  • 啊,你的代码一定有问题:android:configChanges="screenOrientation" 是处理你想做的事情的方法。如果您配置正确,您的onCreate 将不会重新运行。如果它重新运行,那么你配置错误。将您的代码放在问题的正文中,我猜答案应该很简单。
  • hhmmm... 你在说什么配置错误?如果你说我要做的唯一一件事就是将那一行添加到我的清单中,我怎么会做错呢?
  • 这就是我不确定的地方,也是我要求查看您的代码的原因。我的工作代码不会在您每次更改方向时触发 onCreate()
  • 是什么参数? android:configChanges="orientation"android:configChanges="screenOrientation"?

标签: android


【解决方案1】:

除非应用程序的 API 级别为 12 或更低,否则使用 android:configChanges="orientation" 的解决方案将不起作用。

在 API 级别 13 或更高版本中,屏幕尺寸会随着方向变化而变化,所以这仍然会导致 Activity 在方向变化时被销毁并启动。

像下面这样简单地添加“screenSize”属性:

<activity>
    android:name=".YourActivityName"
    android:configChanges="orientation|screenSize">
</activity>

现在,当您更改方向(和屏幕大小更改)时,活动保持其状态并调用 onConfigurationChanged()。当方向改变时,这将保留屏幕上的任何内容(即:Webview 中的网页)。

从这个网站了解到这一点:http://developer.android.com/guide/topics/manifest/activity-element.html

此外,这显然是一种不好的做法,因此请阅读以下有关处理运行时更改的链接:

http://developer.android.com/guide/topics/resources/runtime-changes.html

【讨论】:

  • 嗨!我在纵向和横向模式下使用不同的布局,所以我不能使用android:configChanges,还有其他解决方案吗?
【解决方案2】:

这里有一个非常相似的问题:Don't reload application when orientation changes

无论如何,首先你应该将代码从onCreate更改为另一个方法,并将其除以“创建随机数并从网络加载图像”和“设置图像以查看”。

您在 Activity 上有一个 Bitmap,您可以在每次 Activity 启动时验证它是否为空。

如果是,请执行所有操作。如果不是,只需使用您拥有的位图设置 ImageView 或其他任何内容。

为了避免在旋转时破坏位图,请使用:

    Bitmap image = null;

@Override
protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);

 image = (Bitmap) getLastNonConfigurationInstance();

     if(bitmap == null){
         image = downloadImage();
      }
     setImage(bitmap);
}


@Override
public Object onRetainNonConfigurationInstance() {
    return bitmap;
}

这行得通,我 100% 确定。

【讨论】:

  • 是的,这是我的问题。没有一个解决方案有效。人们只是在没有测试代码的情况下继续发布这些东西。有点可笑。
  • @NeTeInStEiN:这是 JJD 的同一个问题。
  • 请注意,您在此处检索的数据应仅用作处理配置更改的优化。您应该始终能够处理返回空指针,并且即使此函数返回 null,活动也必须能够将自身恢复到之前的状态(通过正常的 onSaveInstanceState(Bundle) 机制)。
  • 这是不真实的。我无法从我的 DownLoadImage 函数返回位图,因为我在 try/catch 块中进行工作。如果“返回”在尝试中,则无法识别,如果在尝试中返回,则返回无法识别在尝试中创建的位图变量
  • 您需要复习 Java。您必须在尝试之前定义变量,而不是仅在尝试上下文中 Bitmap name = null; try{ name = ... }catch(Exception e){ ... } return name;
【解决方案3】:

例如,添加到清单中:

<activity android:name=".Explorer" android:label="@string/app_name"
            android:configChanges="orientation" android:launchMode="standard">
        </activity>

然后只覆盖默认函数:

    @Override
        public void onConfigurationChanged(Configuration _newConfig){
            super.onConfigurationChanged(_newConfig);
int height = getWindowManager().getDefaultDisplay().getHeight();
        int width = getWindowManager().getDefaultDisplay().getWidth();
        if(width > height){
// layout for landscape
}else{
// layout for portrait
        }
            }

注意:如果您覆盖此功能,您必须自己重做布局。这是做你想做的事的唯一方法。 Android 修复屏幕尺寸的方法是将整个 Activity 吹走,并以新的尺寸重新显示它。如果您选择不让它把 Activity 吹走,那么您必须处理屏幕尺寸的变化。没有其他选择。

编辑:在这个特定的应用程序中,我有一个纵向显示的表格和一个横向显示的图表。所以我这样做:

void showDataView()
    {
        setContentView(mainView);
        currentView = mainView; 
    }

    void showGraphView()
    {
        if(currentView == mainView){
            if(graphView == null){
                setContentView(R.layout.graphview);
                graphView = (GraphView)findViewById(R.id.graphview);
            }
            setContentView(graphView);
            currentView = graphView;
            graphView.setDataToPlot(DATA_TO_PLOT);
            graphView.clear();
        }
    }

@Override
    public void onConfigurationChanged(Configuration _newConfig){
        super.onConfigurationChanged(_newConfig);
        int height = getWindowManager().getDefaultDisplay().getHeight();
        int width = getWindowManager().getDefaultDisplay().getWidth();
        if(width > height){
            showGraphView();
        }else{
            showDataView();
        }
        if(graphView != null) graphView.setGraphWidth(width);
    }

每次方向改变时,我都会将内容视图从一个切换到另一个。在您的情况下,您可能只需要 invalidate 当前根视图,看看它是否会正确重绘。

这就是您希望平台处理它的原因,因此您无需处理这些废话。您最好使用onSaveInstanceState 来保留您需要的特定数据,然后在onCreate 中检查该数据,然后使用它。有关这方面的信息,请参阅 http://developer.android.com/reference/android/app/Activity.html#ConfigurationChanges

【讨论】:

  • 好的,我把代码放在哪里?在 onCreate 之前的我的活动中?
  • @Femi 这是唯一正确的答案。我发现最好只强制屏幕方向并保持不变。特别是如果它是任何类型的艺术资产繁重的应用程序。这就是为什么市场上的大多数游戏都强制一个方向并且不允许它改变。
  • 我在“横向布局”和“纵向布局”区域放了什么?
  • 在您的 Activity 中:它只是另一个 Android 回调,例如 onCreate:您必须实现 onConfigurationChanged,然后强制执行新布局。它的所有说法都是当屏幕方向发生变化时,而不是destroying 活动,调用此函数,您将自己重做布局。您可能只需获取根视图并 invalidateing 它就可以逃脱。
  • 我仍然不知道我应该在 if/else 部分做什么。可以举个例子吗?
【解决方案4】:

对我有用的是将类变量之一声明为静态的。 原来静态类变量是在加载应用的时候初始化一次,但是在重新加载应用的时候就不会再初始化了。

这些变量可能包含您不想重新初始化的状态或对象。 我不能说这不是超级优雅,但经过测试并为我工作。

【讨论】:

    【解决方案5】:

    将图像详细信息保存在您的onPause()onStop() 中,并在onCreate(Bundle savedInstanceState) 中使用它来恢复图像。

    有关实际过程的更多信息在http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle 中进行了详细说明,因为 Honeycomb 与以前的 Android 版本不同。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多