简体   繁体   English

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

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

I just implemented a orientation change feature - eg when the layout changes from portrait to landscape (or vice versa).我刚刚实现了一个方向更改功能 - 例如,当布局从纵向变为横向(反之亦然)时。 How can I detect when the orientation change event finished.如何检测方向更改事件何时完成。

The OrientationEventListener didn't work. OrientationEventListener不起作用。 How can I get notifications about layout orientation change events?如何获得有关布局方向更改事件的通知?

Use the onConfigurationChanged method of Activity.使用 Activity 的onConfigurationChanged方法。 See the following code:请参阅以下代码:

@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();
    }
}

You also have to edit the appropriate您还必须编辑适当的element in your manifest file to include the android:configChanges Just see the code below:清单文件中的元素以包含android:configChanges只需查看以下代码:

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

NOTE: with Android 3.2 (API level 13) or higher, the "screen size" also changes when the device switches between portrait and landscape orientation.注意:对于 Android 3.2(API 级别 13)或更高版本,当设备在纵向和横向之间切换时,“屏幕尺寸”也会发生变化。 Thus, if you want to prevent runtime restarts due to orientation change when developing for API level 13 or higher, you must declare android:configChanges="orientation|screenSize" for API level 13 or higher .因此,如果您想在为 API 级别 13 或更高级别开发时防止由于方向更改而导致运行时重新启动,则必须为 API 级别 13 或更高级别声明android:configChanges="orientation|screenSize"

Hope this will help you... :)希望能帮到你... :)

For loading the layout in layout-land folder means you have two separate layouts then you have to make setContentView in onConfigurationChanged method.要在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);
    }
}

If you have only one layout then no necessary to make setContentView in This method.如果您只有一种布局,则无需在此方法中设置 setContentView。 simply简单地

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

Just wanted to show you a way to save all your Bundle after onConfigurationChanged:只是想向您展示一种在 onConfigurationChanged 后保存所有 Bundle 的方法:

Create new Bundle just after your class:课程结束后创建新的 Bundle:

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

Next, after "protected void onCreate" add this:接下来,在“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");
}

If you add this all your crated classes into MainActivity will be saved.如果您将其添加到 MainActivity 中,您所有的 crated 类都将被保存。

But the best way is to add this in your AndroidManifest:但最好的方法是在你的 AndroidManifest 中添加这个:

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

use this method使用这个方法

@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
   }
}

And Do not forget to Add this in your Androidmainfest.xml并且不要忘记在您的 Androidmainfest.xml 中添加它

android:configChanges="orientation|screenSize"

like this像这样

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

    </activity>

In case this is of use to some newer dev's because its not specified above.如果这对一些较新的开发人员有用,因为上面没有指定。 Just to be very explicit:只是要非常明确:

You need two things if using onConfigurationChanged :如果使用onConfigurationChanged ,您需要做两件事:

  1. An onConfigurationChanged method in your Activity Class Activity 类中的onConfigurationChanged方法

  2. Specify in your manifest which configuration changes will be handled by your onConfigurationChanged method在清单中指定onConfigurationChanged方法将处理哪些配置更改

The manifest snippet in the above answers, while no doubt correct for the particular app that manifest belongs to, is NOT exactly what you need to add in your manifest to trigger the onConfigurationChanged method in your Activity Class.清单片段在上面的答案,而无疑是正确的特定应用程序,明显属于,正是你需要在你的清单中添加,以触发您的活动课的onConfigurationChanged方法是什么。 ie the below manifest entry may not be correct for your app.即以下清单条目可能不适合您的应用程序。

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

In the above manifest entry, there are various Android actions for android:configChanges="" which can trigger the onCreate in your Activity lifecycle.在上面的清单条目中, android:configChanges=""有各种 Android 操作,它们可以在您的 Activity 生命周期中触发 onCreate。

This is very important - The ones NOT Specified in the manifest are the ones that trigger your onCreate and The ones specified in the manifest are the ones that trigger your onConfigurationChanged method in your Activity Class.这非常重要 -清单中未指定的是触发您的 onCreate的那些,清单中指定的是触发您的活动类中的onConfigurationChanged方法的那些

So you need to identify which config changes you need to handle yourself.因此,您需要确定需要自己处理哪些配置更改。 For the Android Encyclopedically Challenged like me, I used the quick hints pop-out in Android Studio and added in almost every possible configuration option.对于像我这样的 Android Encyclopedically Challenged,我使用了 Android Studio 中的快速提示弹出窗口,并添加了几乎所有可能的配置选项。 Listing all of these basically said that I would handle everything and onCreate will never be called due to configurations.列出所有这些基本上是说我会处理所有事情,并且由于配置,永远不会调用 onCreate。

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

Now obviously I don't want to handle everything, so I began eliminating the above options one at a time.现在显然我不想处理所有事情,所以我开始一次消除上述选项。 Re-building and testing my app after each removal.每次删除后重新构建和测试我的应用程序。

Another important point : If there is just one configuration option being handled automatically that triggers your onCreate (You do not have it listed in your manifest above), then it will appear like onConfigurationChanged is not working.另一个重点:如果只有一个配置选项被自动处理触发您的 onCreate(您没有在上面的清单中列出它),那么它看起来就像onConfigurationChanged不起作用。 You must put all relevant ones into your manifest.您必须将所有相关的放入您的清单中。

I ended up with 3 that were triggering onCreate originally, then I tested on an S10+ and I was still getting the onCreate, so I had to do my elimination exercise again and I also needed the |screenSize .我最终得到了 3 个最初触发 onCreate 的结果,然后我在 S10+ 上进行了测试,我仍然得到了 onCreate,所以我不得不再次进行消除练习,而且我还需要|screenSize So test on a selection of platforms.因此,在选择的平台上进行测试。

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

So my suggestion, although I'm sure someone can poke holes in this:所以我的建议,虽然我确信有人可以在这方面戳破洞:

  1. Add your onConfigurationChanged method in your Activity Class with a TOAST or LOG so you can see when its working.使用 TOAST 或 LOG 在您的活动类中添加您的onConfigurationChanged方法,以便您可以看到它何时工作。

  2. Add all possible configuration options to your manifest.将所有可能的配置选项添加到您的清单中。

  3. Confirm your onConfigurationChanged method is working by testing your app.通过测试您的应用程序来确认您的onConfigurationChanged方法正在运行。

  4. Remove each config option from your manifest file one at a time, testing your app after each.一次从清单文件中删除每个配置选项,并在每个选项之后测试您的应用程序。

  5. Test on as large a variety of devices as possible.在尽可能多的设备上进行测试。

  6. Do not copy/paste my snippet above to your manifest file.不要将我上面的代码片段复制/粘贴到您的清单文件中。 Android updates change the list, so use the pop-out Android Studio hints to make sure you get them all. Android 更新会更改列表,因此请使用弹出的 Android Studio 提示确保您获得所有提示。

I hope this saves someone some time.我希望这可以节省一些时间。

My onConfigurationChanged method just for info below.我的onConfigurationChanged方法仅用于以下信息。 onConfigurationChanged is called in the lifecycle after the new orientation is available, but before the UI has been recreated. onConfigurationChanged被称为生命周期后,新的方向是可用的,但之前的UI已创建。 Hence my first if to check the orientation works correctly, and then the 2nd nested if to look at the visibility of my UI ImageView also works correctly.因此,我的第一个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

I just want to propose another alternative that will concern some of you, indeed, as explained above:我只是想提出另一种替代方案,确实会引起你们中的一些人的关注,正如上面所解释的:

android:configChanges="orientation|keyboardHidden" 

implies that we explicitly declare the layout to be injected.意味着我们明确声明要注入的布局。

In case we want to keep the automatic injection thanks to the layout-land and layout folders.如果我们想通过 layout-land 和 layout 文件夹保持自动注入。 All you have to do is add it to the onCreate:您所要做的就是将其添加到 onCreate 中:

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

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

Here, we display or not the actionbar depending on the orientation of the phone在这里,我们根据手机的方向显示或不显示操作栏

Create an instance of OrientationEventListener class and enable it.创建OrientationEventListener类的实例并启用它。

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

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

If accepted answer doesn't work for you, make sure you didn't define in manifest file:如果接受的答案对您不起作用,请确保您没有在清单文件中定义:

android:screenOrientation="portrait"

Which is my case.这是我的情况。

for Kotilin implementation in the simplest form - only fires when screen changes from portrait <--> landscape if need device a flip detection (180 degree) you'll need to tab in to gravity sensor values以最简单的形式实现 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")


    }
}

In case anyone else spends way too long on this like I did - it doesn't work on the emulator.如果其他人像我一样在这方面花费太长时间 - 它在模拟器上不起作用。 Has to be real device.必须是真机。

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

相关问题 Android方向更改和布局 - Android Orientation Change and layout Android:检测设备方向更改 - Android: Detect Device Orientation Change Android 中的动画布局方向更改 - Animate Layout Orientation change in Android 如何在Android中更改/更新方向更改对话框的自定义布局 - How to change/update the custom layout of a Dialog on orientation change in android 如何在android中改变屏幕方向时改变布局的位置? - How to change the position of layout when the orientation of screen change in android? 如何在 Android Studio 中更改方向时更改网格布局中的列跨度? - How to change the column span in grid layout on orientation change in Android Studio? 如何在Android的cocos2d x中检测设备方向变化 - How to detect device orientation change in cocos2d x for Android 如何在仅适用于景观的应用程序的Android上的Corona SDK中检测方向变化? - how to detect an orientation change in Corona SDK on Android for an Landscape Only app? 如何在android方向更改中使用不同的布局 - How can I use different layout in android orientation change Android:如何在方向更改时处理布局的动画? - Android : How to handle animation of a layout while orientation change?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM