Activity横竖屏切换

默认情况下,当“屏幕方向”或“键盘显示隐藏” 变化时都会销毁当前Activity,创建新的Activity。

如果不希望重新创建Activity实例,可以按如下配置Activity:

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

注意Android3.2横竖屏幕切换时以上配置configChanges要加上screenSize,要不还会调用onCreate

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

上面的android:configChanges属性指定了要捕获“屏幕方向”和“键盘显示隐藏”变化,

当捕获到这些变化后会调用Activity的onConfigurationChanged()方法。

默认情况下(没有配置android:configChanges属性):

竖屏切横屏,销毁当前Activity之后,创建一个新Activity实例。

横屏切竖屏,销毁当前Activity之后,创建一个新Activity实例,新的Activity实例很快就被销毁,接着又会创建一个新Activity实例。如果只希望创建一个实例,可以配置android:configChanges="orientation"

<activity

android:screenOrientation="portrait"   //竖屏

android:screenOrientation="landscape"   //横屏

/>

上述修改也可以在Java代码中通过类似如下代码来设置

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)

android:screenOrientation属性

他有以下几个参数:

"unspecified":默认值 由系统来判断显示方向.判定的策略是和设备相关的,所以不同的设备会有不同的显示方向.

"landscape":横屏显示(宽比高要长)

"portrait":竖屏显示(高比宽要长)

"user":用户当前首选的方向

"behind":和该Activity下面的那个Activity的方向一致(在Activity堆栈中的)

"sensor":有物理的感应器来决定。如果用户旋转设备这屏幕会横竖屏切换。

"nosensor":忽略物理感应器,这样就不会随着用户旋转设备而更改了("unspecified"设置除外)。

APP的横竖屏切换手动触发

由上面描述可知,当android:screenOrientation为默认值"unspecified"或"sensor"等时,就会有系统根据设备的旋转情况来触发横竖屏的切换,那么有没有方法我们手动在程序中触发横竖屏的变换呢,显然上面为我们提供的setRequestedOrientation就是系统提供的一个入口,下面我们给出一个按键的方式来触发的案列:

public class MainActivity extends Activity implements OnClickListener {

private Button mBtnLandscape;

private Button mBtnPortrait;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

mBtnLandscape = (Button) findViewById(R.id.but_landscape);

mBtnPortrait = (Button) findViewById(R.id.but_portrait);

mBtnLandscape.setOnClickListener(this);

mBtnPortrait.setOnClickListener(this);

}

@Override

public void onClick(View v) {

if(v == mBtnLandscape){

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

}else{

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

}

}

@Override

public void onConfigurationChanged(Configuration newConfig) {

super.onConfigurationChanged(newConfig);

String message=newConfig.orientation==Configuration.ORIENTATION_LANDSCAPE ? "屏幕设置为:横屏" : "屏幕设置为:竖屏";

Toast.makeText(this, message, Toast.LENGTH_LONG).show();

}

}

需要注意的是,手动调用时,无视AndroidManifest中关于screenOrientation的设置;另外上述代码中的onConfigurationChanged要被调用到也是需要条件的,在这里,只给代码,不做讨论,后面再给出一个相关的补充说明。

重启Activity的横竖屏切换

在上面的案列中,缺省状态下,Activity每次横竖屏切换(包括用setRequestedOrientation调用)都会重新调用一轮onPause-> onStop-> onDestory-> onCreate->onStart->onResume操作,从而销毁原来的Activity对象,创建新的Activity对象,这是因为通常情况下软件在横竖屏之间切换,界面的高宽会发生转换,从而可能会要求不同的布局。具体的布局切换可以通过如下两种方法来实现:

1)在res目录下建立layout-land和layout-port目录,相应的layout文件名不变,比如都为main.xml。layout-land是横屏的layout,layout-port是竖屏的layout,其他的不用管,横竖屏切换时模拟器自动寻找main.xml文件。

2)假如布局资源是不一样又不按照如上设置,则需要通过java代码来判断当前是横屏还是竖屏然后来加载相应的xml布局文件(比如mainP为竖屏mainL为横屏)。因为当屏幕变为横屏的时候,系统会重新呼叫当前Activity的onCreate方法,你可以把以下方法放在你的onCreate中来检查当前的方向,然后可以让你的setContentView来载入不同的layout xml。

@Override

protected void onCreate(Bundle icicle) {

super.onCreate(icicle);

int mCurrentOrientation = getResources().getConfiguration().orientation;

if ( mCurrentOrientation == Configuration.ORIENTATION_PORTRAIT ) {

Log.i("info", "portrait"); // 竖屏

setContentView(R.layout.mainP);

} else if ( mCurrentOrientation == Configuration.ORIENTATION_LANDSCAPE ) {

Log.i("info", "landscape"); // 横屏

setContentView(R.layout.mainL);

}

init();//初始化,赋值等操作

findViews();//获得控件

setListensers();//设置控件的各种监听方法

}

上面只是对布局切换做了描述,实际上由于重启Activity在未加处理的情况下必然导致数据的丢失和重新获取,这样用户体验会非常差。为此就要在切换前对数据进行保存,切换重启后对数据进行恢复,具体操作的步骤如下:

重写Activity.onRetainNonConfigurationInstance(),用户横竖屏切换前保存数据

@Override

public Object onRetainNonConfigurationInstance() {

final MyDataObject data = collectMyLoadedData();

return data;

}

在onCreate()函数中调用getLastNonConfigurationInstance(),获取onRetainNonConfigurationInstance()保存的数据

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

final MyDataObject data = (MyDataObject) getLastNonConfigurationInstance();

if (data == null) {

data = loadMyData();

}

...

}

非重启Activity的横竖屏切换

虽然重启Activity为我们提供了保存数据和读取数据的方式,但是如此一来程序会显得有些繁琐,所以有时候程序员往往就不想让Activity重启,Android也为我们提供了解决方案,就是通过onConfigurationChanged拦截横竖屏变换,从而进行必要的重新布局和切换操作。操作步骤如下:

首先,manifest中为相应的Activity设置android:configChanges属性,从而让Activity不延续上述的重建流程,具体如下:

Andorid 3.2以前的SDK可以使用如下配置

android:configChanges="orientation|keyboardHidden"

而Adnroid 3.2以后的SDK必须添加一个screenSize属性,具体如下

android:configChanges="keyboardHidden|orientation|screenSize"

或者

android:configChanges="orientation|screenSize"

其次,在Activity或View的onConfigurationChanged(Configuration newConfig)函数中获取当前横竖屏参数。至于其调用顺序跟touch事件的传递顺序相似,不过他没有消费事件的概念,会顺次调用到每一个onConfigurationChanged函数。下面是重写Activity的例子:

//布局分别在layout-land和layout-port目录中的同名main.xml时

@Override

public void onConfigurationChanged (Configuration newConfig){

super.onConfigurationChanged(newConfig);

setContentView(R.layout.main);

//注意,这里删除了init(),否则又初始化了,状态就丢失

findViews();

setListensers();

}

//布局为不按照layout-land和layout-port目录,而自定义名字时

@Override

public void onConfigurationChanged (Configuration newConfig){

super.onConfigurationChanged(newConfig);

int mCurrentOrientation = getResources().getConfiguration().orientation;

if ( mCurrentOrientation == Configuration.ORIENTATION_PORTRAIT ) {

setContentView(R.layout.mainP);

//注意,这里删除了init(),否则又初始化了,状态就丢失

findViews();

setListensers();

} else if ( mCurrentOrientation == Configuration.ORIENTATION_LANDSCAPE ) {

setContentView(R.layout.mainL);

//注意,这里删除了init(),否则又初始化了,状态就丢失

findViews();

setListensers();

}

}

当然有时候连布局都不用更改的话,就可以直接对原有控件进行调用操作了,比如:

public class MainActivity extends Activity {

private TextView textView;

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

Log.i("--Main--", "onCreate");

textView=(TextView)findViewById(R.id.tv_id);

}

@Override

public void onConfigurationChanged(Configuration newConfig) {

super.onConfigurationChanged(newConfig);

Log.i("--Main--", "onConfigurationChanged");

if(newConfig.orientation==Configuration.ORIENTATION_LANDSCAPE){

textView.setText("当前屏幕为横屏");

}else{

textView.setText("当前屏幕为竖屏");

}

}

}

需要注意的是,onConfigurationChanged函数中只能获得横竖屏切换后的参数,在该函数中获取不到新的Layout和控件的尺寸位置信息,如果要处理尺寸和位置信息,必须通过消息异步或者延时调用,下面是一个App在横竖屏切换时需要重新设置popupWindow位置的代码:

@Override

protected void onConfigurationChanged(Configuration newConfig) {

super.onConfigurationChanged(newConfig);

//View中不用创建Handler,可直接调用post操作

//new Handler().postDelayed(new Runnable() {

//    @Override

//    public void run() {

//        updatePopup();

//    }

//}, 500);

postDelayed(new Runnable() {

@Override

public void run() {

updatePopup();      //

}

}, 500);//如果不在post中,而是直接调用,那么弹出位置就会有问题

}

虽然上面没有看到对布局的显式调用进行重新布局,照理控件的对象没有被销毁,但是控件在横竖屏切换时应该是需要进行重新layout和measure,然后再进行重绘的,否则不会引发弹出框位置的变化,至于如何调用重新layout、measure和Draw操作,在这里就不多展开了。

自适应横竖屏

如果想让它启动的时候是横屏的话就横屏表示,纵屏的话就纵屏表示,然后手机切换横竖屏就不能用了该怎么解决呢?

首先:在Mainfest.xml中追加

android:screenOrientation="sensor"android:configChanges="orientation|keyboardHidden"这两个属性。

第二步:取得屏幕的长和宽,进行比较设置横竖屏的变量。

Display display = getWindowManager().getDefaultDisplay();

int width = display.getWidth();

int height = display.getHeight();

if (width > height) {

orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;

} else {

orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;

}

第三步:在onConfigurationChanged()函数中追加this.setRequestedOrientation(orientation)就行了

@Override

public void onConfigurationChanged(Configuration newConfig) {

super.onConfigurationChanged(newConfig);

this.setRequestedOrientation(mOrientation);

}

但是这样的话你切到别的画面的时候再回到原画面,它就仍然是横的或者是纵的。怎么让它从别的屏幕回来后,又重新横竖屏布局呢?

只要在OnResume()中在设定下就行了。但是这个只支持横竖屏只有一个layout的。横竖屏分别对应layout的还不知道该怎么解决。

@Override

protected void onResume() {

mOrientation = ActivityInfo.SCREEN_ORIENTATION_USER;

this.setRequestedOrientation(mOrientation);

Display display = getWindowManager().getDefaultDisplay();

int width = display.getWidth();

int height = display.getHeight();

if (width > height) {

mOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;

} else {

mOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;

}

super.onResume();

}

时间: 2024-10-10 02:51:07

Activity横竖屏切换的相关文章

无废话Android之activity的生命周期、activity的启动模式、activity横竖屏切换的生命周期、开启新的activity获取他的返回值、利用广播实现ip拨号、短信接收广播、短信监听器(6)

1.activity的生命周期 这七个方法定义了Activity的完整生命周期.实现这些方法可以帮助我们监视其中的三个嵌套生命周期循环: (1)Activity的完整生命周期 自第一次调用onCreate()开始,直到调用onDestory()为止.Activity在onCreate()中设置所有“全局”状态以完成初始化. 而在onDestory()中释放所有系统资源.例如,如果Activity有一个线程在后台运行从网络下载数据,它会在onCreate()创建线程, 而在onDestory()销

Activity横竖屏切换的问题

Activity在横竖屏切换的时候会重新走生命周期的方法,这样做的话会导致一些问题 比如我们在界面上录入的一些数据,但因为重新走了生命周期的方法onCreate()方法,这样就会导致前功尽弃,所以就想办法,在横竖屏切换的时候不能让其重新OnCreate(),Android中我们可以在清单文件中对应的Activity使用如下的属性  android:configChanges="keyboardHidden|orientation|screenSize"  这样就可以避免此类事情的发生.

android开发之activity横竖屏切换时的生命周期以及横竖屏切换时的资源适配方案

背景:之前有过两篇写activity的博客 android之activity的生命周期详解:详细介绍了activity的整个生命周期.各状态间的转换和返回桌面时保存activity的状态 android之activity中onSaveInstanceState和onRestoreInstanceState的触发时机:介绍了activity中这两个方法的触发时机和作用 本篇博客会牵扯到里面的内容,如果你都有所了解可以直接往下看,如果不了解可以进去回忆下. 问题:在做应用的退出对话框时,发现如果对话

Android--纠正Activity横竖屏切换的生命周期的错误

1.本机测试环境 android 4.3, android:targetSdkVersion : 12,13,17 2.关于横竖屏切换的Activity生命周期的错误说法 初学Android,在学习Activity的生命周期时,自己在本机实验时,发现了一些不合理的情况. 那就是在横竖屏切换时,Activity并不会像网上大多数人所说的那样: 不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次. 设置Activi

Activity横竖屏切换不重绘界面

从Android 3.2(API 13),在设置Activity的android:configChanges="orientation|keyboardHidden"后,还是一样会重新调用各个生命周期的.因为screen size也开始跟着设备的横竖切换而改变.所以,在AndroidManifest.xml里设置的MiniSdkVersion和 TargetSdkVersion属性大于等于13的情况下,如果你想阻止程序在运行时重新加载Activity,除了设置"orienta

Activity横竖屏切换时 一些数据的保存

private VideoView videoView; 02.private static final String VIDEO_PATH = Environment 03. .getExternalStorageDirectory() 04. + File.separator 05. + "mymovie" 06. + File.separator + "shenghuaweiji.mp4"; 07. 08./** Called when the activit

android的Activity横竖屏切换时的生命周期

OnCreate()->OnStart->OnResume()->onPause()->onDestory->OnCreate()->OnStart->OnResume() 想要避免这种情况:要在manifest文件里面配置onconfigChanged属性 OnCreate:对象创建完毕,但此时不可见 OnStart: Activity在屏幕可见,但是此时没有焦点 OnResume:Activity在屏幕可见,并且获得焦点 onPause:Activity在屏幕

如何处理Activity横竖屏切换时 fragment会添加一个被又new一次的现象

当屏幕发生旋转,Activity发生重新启动,依附在Activity中的Fragment也会跟着Activity重新创建: 这样造成当旋转的时候,本身存在的Fragment会重新启动,然后当执行Activity的onCreate时,又会再次实例化一个新的Fragment,这就是出现的原因. 解决办法: 通过onCreate的参数Bundle savedInstanceState就可以判断,当前是否发生Activity的重新创建: 默认的savedInstanceState会存储一些数据,包括Fr

Activity嵌套多个Fragment实现横竖屏切换

一.上图 二.需求 近期项目遇到个横竖屏切换的问题,较为复杂,在此记之. 1.Activity中竖屏嵌套3个Fragment,本文简称竖屏FP1,FP2,FP3. 2.其中竖屏FP1与FP2可以切换为横屏的FL1,FL2,即竖屏FP1切换到对应的横屏FL1,竖屏FP2对应切换到横屏FL2. 3.FP3不允许横竖屏切换. 4.竖屏FP1,FP2,FP3用ViewPager实现左右滑动切换. 5.横屏的FL1,FL2用布局中的切换按扭实现左右切换,不允许滑动切换. 看到这需求有点儿晕菜了吧!!!呵呵