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

use*_*015 100 android

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

OrientationEventListener没有工作.如何获取有关布局方向更改事件的通知?

Din*_*rma 278

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

@Override
public void onConfigurationChanged(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();
    }
}
Run Code Online (Sandbox Code Playgroud)

您还必须编辑相应的 清单文件中的元素包含android:configChanges 只需看下面的代码:

<activity android:name=".MyActivity"
          android:configChanges="orientation|keyboardHidden"
          android:label="@string/app_name">
Run Code Online (Sandbox Code Playgroud)

注意:对于Android 3.2(API级别13)或更高版本,当设备在纵向和横向之间切换时,"屏幕大小"也会更改.因此,如果要在开发API级别13或更高级别时因为方向更改而阻止运行时重新启动,则必须为API级别13或更高级别声明android:configChanges ="orientation | screenSize".

希望对你有帮助... :)

  • Aztec Coder,当您包含"android:configChanges ="orientation"时,您声明将处理方向更改,这意味着当您切换到横向时不会重新创建您的活动.而是调用onConfigurationChanged.如果这是不希望的,你可以使用一个变量记住你的活动的方向,每次你通过onPause(例如)检查方向是否仍然相同. (21认同)
  • 如果您正在为API级别13(3.2)或更高级别开发,则应指定android:configChanges ="orientation | screenSize",否则将不会调用onConfigurationChanged:http://developer.android.com/guide/topics/resources /runtime-changes.html#HandlingTheChange (14认同)
  • 这很好,但它会在layout-land文件夹中加载布局xml,它使用纵向xml布局文件. (3认同)
  • 在你的清单文件中使用**android:configChanges ="orientation | screenSize"**而不是android:configChanges ="orientation | keyboardHidden"并检查...... !!! (2认同)

小智 14

layout-land文件夹中加载布局意味着你有两个独立的布局,然后你必须setContentViewonConfigurationChanged方法中.

@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);
    }
}
Run Code Online (Sandbox Code Playgroud)

如果只有一个布局,则无需在此方法中生成setContentView.只是

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
}
Run Code Online (Sandbox Code Playgroud)

  • 而不是覆盖,只需使用layout/main.xml和layout-land/main.xml. (19认同)

Nik*_*tov 13

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

在课程结束后创建新的Bundle:

public class MainActivity extends Activity {
    Bundle newBundy = new Bundle();
Run Code Online (Sandbox Code Playgroud)

接下来,在"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");
}
Run Code Online (Sandbox Code Playgroud)

如果添加此项,则会保存所有已分类的类到MainActivity中.

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

<activity name= ".MainActivity" android:configChanges="orientation|screenSize"/>
Run Code Online (Sandbox Code Playgroud)

  • 这是误导.实现`onConfigurationChanged()`会使方向更改时不会破坏instanceState,因此您不必保存它.您可能希望将其保存为活动生命周期中的其他事件,但我不知道. (6认同)

Sai*_*i N 5

使用这种方法

@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
   }
}
Run Code Online (Sandbox Code Playgroud)

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

android:configChanges="orientation|screenSize"
Run Code Online (Sandbox Code Playgroud)

像这样

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

    </activity>
Run Code Online (Sandbox Code Playgroud)


DMu*_*Mur 5

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

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

  1. onConfigurationChangedActivity 类中的方法

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

上述答案中的清单片段虽然对于清单所属的特定应用程序来说无疑是正确的,但并不完全是您需要在清单中添加以触发 Activity 类中的 onConfigurationChanged 方法的内容。即下面的清单条目可能不适合您的应用程序。

<activity name= ".MainActivity" android:configChanges="orientation|screenSize"/>
Run Code Online (Sandbox Code Playgroud)

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

这非常重要 -清单中未指定的内容是触发 onCreate 的内容清单中指定的内容是触发onConfigurationChangedActivity 类中的方法的内容。

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. Listing all of these basically said that I would handle everything and onCreate will never be called due to configurations.

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

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. 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. So test on a selection of platforms.

<activity name= ".MainActivity" android:configChanges="screenLayout|uiMode|orientation|screenSize"/>
Run Code Online (Sandbox Code Playgroud)

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.

  2. Add all possible configuration options to your manifest.

  3. Confirm your onConfigurationChanged method is working by testing your app.

  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.

I hope this saves someone some time.

我的onConfigurationChanged方法仅供参考。在新方向可用之后、重新创建 UI之前的onConfigurationChanged生命周期中调用。因此,我首先检查方向是否正常工作,然后第二次嵌套检查 UI ImageView 的可见性也正常工作。ifif

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

        }
    }
Run Code Online (Sandbox Code Playgroud)