繁体   English   中英

如何检测Android布局中的方向变化?

[英]How to detect orientation change in layout in Android?

我刚刚实现了一个方向更改功能 - 例如,当布局从纵向变为横向(反之亦然)时。 如何检测方向更改事件何时完成。

OrientationEventListener不起作用。 如何获得有关布局方向更改事件的通知?

使用 Activity 的onConfigurationChanged方法。 请参阅以下代码:

@Override
public void onConfigurationChanged(@NotNull Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    // Checks the orientation of the screen
    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
    } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
        Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
    }
}

您还必须编辑适当的清单文件中的元素以包含android:configChanges只需查看以下代码:

<activity android:name=".MyActivity"
          android:configChanges="orientation|keyboardHidden"
          android:label="@string/app_name">

注意:对于 Android 3.2(API 级别 13)或更高版本,当设备在纵向和横向之间切换时,“屏幕尺寸”也会发生变化。 因此,如果您想在为 API 级别 13 或更高级别开发时防止由于方向更改而导致运行时重新启动,则必须为 API 级别 13 或更高级别声明android:configChanges="orientation|screenSize"

希望能帮到你... :)

要在layout-land文件夹中加载布局意味着您有两个单独的布局,那么您必须在onConfigurationChanged方法中创建setContentView

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    // Checks the orientation of the screen
    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        setContentView(R.layout.yourxmlinlayout-land);
    } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
        setContentView(R.layout.yourxmlinlayoutfolder);
    }
}

如果您只有一种布局,则无需在此方法中设置 setContentView。 简单地

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
}

只是想向您展示一种在 onConfigurationChanged 后保存所有 Bundle 的方法:

课程结束后创建新的 Bundle:

public class MainActivity extends Activity {
    Bundle newBundy = new Bundle();

接下来,在“protected void onCreate”之后添加:

@Override
public void onConfigurationChanged(Configuration newConfig) {
     super.onConfigurationChanged(newConfig);
     if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
            onSaveInstanceState(newBundy);
        } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
            onSaveInstanceState(newBundy);
        }
}

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putBundle("newBundy", newBundy);
}

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    savedInstanceState.getBundle("newBundy");
}

如果您将其添加到 MainActivity 中,您所有的 crated 类都将被保存。

但最好的方法是在你的 AndroidManifest 中添加这个:

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

使用这个方法

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT)
    {
        Toast.makeText(getActivity(),"PORTRAIT",Toast.LENGTH_LONG).show();
       //add your code what you want to do when screen on PORTRAIT MODE
    }
    else if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE)
    {
        Toast.makeText(getActivity(),"LANDSCAPE",Toast.LENGTH_LONG).show();
        //add your code what you want to do when screen on LANDSCAPE MODE
   }
}

并且不要忘记在您的 Androidmainfest.xml 中添加它

android:configChanges="orientation|screenSize"

像这样

<activity android:name=".MainActivity"
          android:theme="@style/Theme.AppCompat.NoActionBar"
          android:configChanges="orientation|screenSize">

    </activity>

如果这对一些较新的开发人员有用,因为上面没有指定。 只是要非常明确:

如果使用onConfigurationChanged ,您需要做两件事:

  1. Activity 类中的onConfigurationChanged方法

  2. 在清单中指定onConfigurationChanged方法将处理哪些配置更改

清单片段在上面的答案,而无疑是正确的特定应用程序,明显属于,正是你需要在你的清单中添加,以触发您的活动课的onConfigurationChanged方法是什么。 即以下清单条目可能不适合您的应用程序。

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

在上面的清单条目中, android:configChanges=""有各种 Android 操作,它们可以在您的 Activity 生命周期中触发 onCreate。

这非常重要 -清单中未指定的是触发您的 onCreate的那些,清单中指定的是触发您的活动类中的onConfigurationChanged方法的那些

因此,您需要确定需要自己处理哪些配置更改。 对于像我这样的 Android Encyclopedically Challenged,我使用了 Android Studio 中的快速提示弹出窗口,并添加了几乎所有可能的配置选项。 列出所有这些基本上是说我会处理所有事情,并且由于配置,永远不会调用 onCreate。

<activity name= ".MainActivity" android:configChanges="screenLayout|touchscreen|mnc|mcc|density|uiMode|fontScale|orientation|keyboard|layoutDirection|locale|navigation|smallestScreenSize|keyboardHidden|colorMode|screenSize"/>

现在显然我不想处理所有事情,所以我开始一次消除上述选项。 每次删除后重新构建和测试我的应用程序。

另一个重点:如果只有一个配置选项被自动处理触发您的 onCreate(您没有在上面的清单中列出它),那么它看起来就像onConfigurationChanged不起作用。 您必须将所有相关的放入您的清单中。

我最终得到了 3 个最初触发 onCreate 的结果,然后我在 S10+ 上进行了测试,我仍然得到了 onCreate,所以我不得不再次进行消除练习,而且我还需要|screenSize 因此,在选择的平台上进行测试。

<activity name= ".MainActivity" android:configChanges="screenLayout|uiMode|orientation|screenSize"/>

所以我的建议,虽然我确信有人可以在这方面戳破洞:

  1. 使用 TOAST 或 LOG 在您的活动类中添加您的onConfigurationChanged方法,以便您可以看到它何时工作。

  2. 将所有可能的配置选项添加到您的清单中。

  3. 通过测试您的应用程序来确认您的onConfigurationChanged方法正在运行。

  4. 一次从清单文件中删除每个配置选项,并在每个选项之后测试您的应用程序。

  5. 在尽可能多的设备上进行测试。

  6. 不要将我上面的代码片段复制/粘贴到您的清单文件中。 Android 更新会更改列表,因此请使用弹出的 Android Studio 提示确保您获得所有提示。

我希望这可以节省一些时间。

我的onConfigurationChanged方法仅用于以下信息。 onConfigurationChanged被称为生命周期后,新的方向是可用的,但之前的UI已创建。 因此,我的第一个if检查方向是否正常工作,然后第二个嵌套if查看我的 UI ImageView 的可见性也正常工作。

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);

        // Checks the orientation of the screen
        if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
            pokerCardLarge = findViewById(R.id.pokerCardLgImageView);

            if(pokerCardLarge.getVisibility() == pokerCardLarge.VISIBLE){
                Bitmap image = ((BitmapDrawable)pokerCardLarge.getDrawable()).getBitmap();
                pokerCardLarge.setVisibility(pokerCardLarge.VISIBLE);
                pokerCardLarge.setImageBitmap(image);
            }

        } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
            pokerCardLarge = findViewById(R.id.pokerCardLgImageView);

            if(pokerCardLarge.getVisibility() == pokerCardLarge.VISIBLE){
                Bitmap image = ((BitmapDrawable)pokerCardLarge.getDrawable()).getBitmap();
                pokerCardLarge.setVisibility(pokerCardLarge.VISIBLE);
                pokerCardLarge.setImageBitmap(image);
            }

        }
    }

覆盖活动的方法onConfigurationChanged

我只是想提出另一种替代方案,确实会引起你们中的一些人的关注,正如上面所解释的:

android:configChanges="orientation|keyboardHidden" 

意味着我们明确声明要注入的布局。

如果我们想通过 layout-land 和 layout 文件夹保持自动注入。 您所要做的就是将其添加到 onCreate 中:

    if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
        getSupportActionBar().hide();

    } else if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
        getSupportActionBar().show();
    }

在这里,我们根据手机的方向显示或不显示操作栏

创建OrientationEventListener类的实例并启用它。

OrientationEventListener mOrientationEventListener = new OrientationEventListener(YourActivity.this) {
    @Override
    public void onOrientationChanged(int orientation) {
        Log.d(TAG,"orientation = " + orientation);
    }
};

if (mOrientationEventListener.canDetectOrientation())
    mOrientationEventListener.enable();

如果接受的答案对您不起作用,请确保您没有在清单文件中定义:

android:screenOrientation="portrait"

这是我的情况。

以最简单的形式实现 Kotilin - 仅在屏幕从纵向 <--> 横向变化时触发,如果需要设备翻转检测(180 度),您需要标记重力传感器值

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

val rotation = windowManager.defaultDisplay.rotation

    when (rotation) {            
        0 -> Log.d(TAG,"at zero degree")
        1 -> Log.d(TAG,"at 270 degree")
        2 -> Log.d(TAG,"at 180 degree")
        3 -> Log.d(TAG,"at 90 degree")


    }
}

如果其他人像我一样在这方面花费太长时间 - 它在模拟器上不起作用。 必须是真机。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM