android横竖屏切换

横竖屏切换方法:

    1.自动切换:

        1.通过在androidManifest.xml的activity节点添加screenOrientation属性:
//screenOrientation属性说明:

unspecified:默认值,由系统决定;
landscape:设置横屏显示(不管当前手机是什么方向,activity都是横屏且方向不会变);
portrait:设置竖屏显示(activity一直是竖屏的);
behind:与前一个activity方向相同;
sensor:activity方向根据物理传感器方向转动,旋转方向为0度,90度,180度,270度(即手机的四侧,手机顶部在上时activity上部分在手机顶部,手机底部在上时activity上部分在手机底部,手机左侧在上时activity顶部在左侧,手机右侧在上时activity上部分在右侧);
sensorLandscape:activity横屏且根据传感器设置方向(此时方向只有90度,270度,即左右两侧);
sensorPortrait:activity竖屏且根据传感器设置方向(旋转0度或者180度);
nosensor:旋转设备时候,界面不会跟着旋转;
user:用户当前设置的方向;

        此时如果想要activity根据传感器方向变方向时设置screenOrientation为sensor或者sensorLandscape或者sensorPortrait即可。

        2.通过动态注册传感器动态设置:
在activity中或者fragment中或者相应的逻辑中添加:

	private OrientationEventListener mOrientationListener = new OrientationEventListener(getActivity(), SensorManager.SENSOR_DELAY_NORMAL) {
			@Override
			public void onOrientationChanged(int rotation) {
				// 设置竖屏
				if (getActivity() == null || getActivity().isFinishing()) {
					return;
				}
				requestedOrientation(rotation);//根据传感器设置屏幕方向
			}
		};
		
	//设置listener是否启动,在相应时机调用,只有在enable时才能监听传感器方向
	private void enableSensor(){
		if (mOrientationListener.canDetectOrientation()) {
			mOrientationListener.enable();
		} else {
		mOrientationListener.disable();
		}
	}

/**
	 * 描述:改变屏幕方向
	 */
	private void requestedOrientation(int rotation) {//此时的rotation为传感器旋转的角度
		if (rotation < 10 || rotation > 350) {// 手机顶部向上
			activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
		} else if (rotation < 100 && rotation > 80) {// 手机右边向上
			activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
		} else if (rotation < 190 && rotation > 170) {// 手机低边向上
			activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
		} else if (rotation < 280 && rotation > 260) {// 手机左边向上
			activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
		}
	}

注:要在相应的时机注销掉listener,否则会出现内存泄漏:

		if (mOrientationListener != null) {
            mOrientationListener.disable();
            mOrientationListener = null;
        }

        想动态设置activity方向时调用activity.setRequestedOrientation方法即可,其中可设置的值可在ActivityInfo类中查看(属性中有的都可以动态设置,其中类中还有其他的一些有趣的东西有兴趣的话可以看下)。

相关的一些问题:

    1.activity生命周期问题
         横竖屏切换时会先销毁相应activity,后在创建横屏或竖屏的activity,因此生命周期为onPause-> onStop-> onDestory-> onCreate->onStart->onResume;
此时如果如果有layout-land下的activity布局时横竖屏切换时会使用不同的布局xml文件。
如果不想让activity重新创建时在manifest的activity节点处添加属性:

            android:configChanges="orientation|screenSize"

    2.自动切换时布局问题
        横竖屏切换时如果重新创建了activity会重新加载相应的布局文件(layout下的或者layout-land下的),但如果设置了configChanges="orientation|screenSize"由于不会重新创建activity所以布局只会使用竖屏的布局文件。

        屏幕方向变化之后会回调activity或者fragment的onConfigurationChanged方法。

此时如果想要适配横竖屏:
        1.可在onConfigurationChanged中重新设置下contentview:

//1.布局分别在layout-land和layout-port目录中的同名main.xml时
@Override
public void onConfigurationChanged (Configuration newConfig){
   super.onConfigurationChanged(newConfig);
   setContentView(R.layout.main);
   //注意,这里删除了init(),否则又初始化了,状态就丢失
   findViews();
   setListensers();
}


//2.布局为不按照layout-land和layout-port目录,而自定义名字时
@Override
public void onConfigurationChanged (Configuration newConfig){
   super.onConfigurationChanged(newConfig);
   int mCurrentOrientation = getResources().getConfiguration().orientation;
   if ( mCurrentOrientation == Configuration.ORIENTATION_PORTRAIT ) {
       // If current screen is portrait
       setContentView(R.layout.mainP);
       //注意,这里删除了init(),否则又初始化了,状态就丢失
       findViews();
       setListensers();
   } else if ( mCurrentOrientation == Configuration.ORIENTATION_LANDSCAPE ) {
       //If current screen is landscape
       setContentView(R.layout.mainL);
       //注意,这里删除了init(),否则又初始化了,状态就丢失
       findViews();
       setListensers();
   }
}

         2.或者直接设置view的宽高大小或者比例:
                比如直播时竖屏时小屏幕设置自定义的比例,竖屏时设置宽高比的比例即可填满屏幕。

        注:如果使用的screenOrientation为sensorLandscape或者sensorPortrait时,在手机方向切换后并不会触发onConfigurationChanged回调,如果想监听手机屏幕方向改变可添加OrientationEventListener。

    3.使用今日头条适配时横屏列表项尺寸异常问题
        由于在项目中使用了今日头条的适配方案(使用可看:https://blog.csdn.net/weixin_42493749/article/details/82982880 ),但是在横竖屏切换后列表项在滚动时发现尺寸异常了,解决方案为在adapter的bindview或者getview时调用:

AutoSize.autoConvertDensity((Activity) getContext(), 400f, true);

          具体参数的解释可进入方法中查看就不多说了,能解决的原因也可在方法中看到:在view绘制前Density修改了,绘制完成后Density又重置了回去导致view测量绘制所使用的Density值不同就导致了view的大小不同;同时项目中有一个逻辑是在网络请求完成后填充recyclerview时view特别小也是在请求完成后添加了这行代码view尺寸正常了。

发布了46 篇原创文章 · 获赞 23 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/divaid/article/details/88752058