一般手机只能旋转3个方向,这里将介绍如何让手机可以旋转180度,也就是上下颠倒。
1.静态方法
frameworks/base/core/res/res/values/config.xml
config_allowAllRotations通过这个来设置。
<bool name="config_supportAutoRotation">true</bool>
<bool name="config_allowAllRotations">true</bool>
2.动态方法
在手机确认要旋转后,就会走PhoneWindowManager.java的onProposedRotationChanged。
class MyOrientationListener extends WindowOrientationListener {
private final Runnable mUpdateRotationRunnable = new Runnable() {
@Override
public void run() {
mPowerManagerInternal.powerHint(PowerHint.INTERACTION, 0);
updateRotation(false);
}
};
MyOrientationListener(Context context, Handler handler) {
super(context, handler);
}
@Override
public void onProposedRotationChanged(int rotation) {
if (localLOGV) Slog.v(TAG, "onProposedRotationChanged, rotation=" + rotation);
mHandler.post(mUpdateRotationRunnable);
}
}
然后走
void updateRotation(boolean alwaysSendConfiguration) {
try {
mWindowManager.updateRotation(alwaysSendConfiguration, false);
} catch (RemoteException e) {
}
}
再走WindowManagerService.java的updateRotation。
/**
* Recalculate the current rotation.
*
* Called by the window manager policy whenever the state of the system changes
* such that the current rotation might need to be updated, such as when the
* device is docked or rotated into a new posture.
*/
@Override
public void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
updateRotationUnchecked(alwaysSendConfiguration, forceRelayout);
}
再走
private void updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout) {
if(DEBUG_ORIENTATION) Slog.v(TAG_WM, "updateRotationUnchecked:"
+ " alwaysSendConfiguration=" + alwaysSendConfiguration
+ " forceRelayout=" + forceRelayout);
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "updateRotation");
long origId = Binder.clearCallingIdentity();
try {
final boolean rotationChanged;
final int displayId;
synchronized (mWindowMap) {
final DisplayContent displayContent = getDefaultDisplayContentLocked();
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "updateRotation: display");
rotationChanged = displayContent.updateRotationUnchecked(
false );
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
if (!rotationChanged || forceRelayout) {
displayContent.setLayoutNeeded();
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER,
"updateRotation: performSurfacePlacement");
mWindowPlacerLocked.performSurfacePlacement();
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
displayId = displayContent.getDisplayId();
}
if (rotationChanged || alwaysSendConfiguration) {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "updateRotation: sendNewConfiguration");
sendNewConfiguration(displayId);
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
} finally {
Binder.restoreCallingIdentity(origId);
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
}
再走DisplayContent.java的updateRotationUnchecked
/**
* Update rotation of the display.
*
* Returns true if the rotation has been changed. In this case YOU MUST CALL
* {@link WindowManagerService#sendNewConfiguration(int)} TO UNFREEZE THE SCREEN.
*/
boolean updateRotationUnchecked(boolean inTransaction) {
if (mService.mDeferredRotationPauseCount > 0) {
if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, rotation is paused.");
return false;
}
ScreenRotationAnimation screenRotationAnimation =
mService.mAnimator.getScreenRotationAnimationLocked(mDisplayId);
if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, animation in progress.");
return false;
}
if (mService.mDisplayFrozen) {
if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
"Deferring rotation, still finishing previous rotation");
return false;
}
if (!mService.mDisplayEnabled) {
if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, display is not enabled.");
return false;
}
final int oldRotation = mRotation;
final int lastOrientation = mLastOrientation;
final boolean oldAltOrientation = mAltOrientation;
int rotation = mService.mPolicy.rotationForOrientationLw(lastOrientation, oldRotation);
final boolean rotateSeamlessly = mService.mPolicy.shouldRotateSeamlessly(oldRotation,
rotation);
if (rotateSeamlessly) {
final WindowState seamlessRotated = getWindow((w) -> w.mSeamlesslyRotated);
if (seamlessRotated != null) {
return false;
}
}
。。。。。。
}
最后走PhoneWindowManager.java的rotationForOrientationLw
@Override
public int rotationForOrientationLw(int orientation, int lastRotation) {
if (false) {
Slog.v(TAG, "rotationForOrientationLw(orient="
+ orientation + ", last=" + lastRotation
+ "); user=" + mUserRotation + " "
+ ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED)
? "USER_ROTATION_LOCKED" : "")
);
mAllowAllRotations = -1;
if (mForceDefaultOrientation) {
return Surface.ROTATION_0;
}
synchronized (mLock) {
int sensorRotation = mOrientationListener.getProposedRotation();
if (sensorRotation < 0) {
sensorRotation = lastRotation;
}
final int preferredRotation;
if (mLidState == LID_OPEN && mLidOpenRotation >= 0) {
preferredRotation = mLidOpenRotation;
} else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR
&& (mCarDockEnablesAccelerometer || mCarDockRotation >= 0)) {
preferredRotation = mCarDockEnablesAccelerometer
? sensorRotation : mCarDockRotation;
} else if ((mDockMode == Intent.EXTRA_DOCK_STATE_DESK
|| mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
|| mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK)
&& (mDeskDockEnablesAccelerometer || mDeskDockRotation >= 0)) {
preferredRotation = mDeskDockEnablesAccelerometer
? sensorRotation : mDeskDockRotation;
} else if ((mHdmiPlugged || mWifiDisplayConnected) && mDemoHdmiRotationLock) {
preferredRotation = mDemoHdmiRotation;
} else if (mWifiDisplayConnected && (mWifiDisplayCustomRotation > -1)) {
preferredRotation = mWifiDisplayCustomRotation;
} else if (mHdmiPlugged && mDockMode == Intent.EXTRA_DOCK_STATE_UNDOCKED
&& mUndockedHdmiRotation >= 0) {
preferredRotation = mUndockedHdmiRotation;
} else if (mDemoRotationLock) {
preferredRotation = mDemoRotation;
} else if (orientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
preferredRotation = lastRotation;
} else if (!mSupportAutoRotation) {
preferredRotation = -1;
} else if ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE
&& (orientation == ActivityInfo.SCREEN_ORIENTATION_USER
|| orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
|| orientation == ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
|| orientation == ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
|| orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER))
|| orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
|| orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
|| orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
|| orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) {
if (mAllowAllRotations < 0) {
mAllowAllRotations = Global.getInt(mContext.getContentResolver(), Global.ALLOW_ALL_ROTATION_ON,0);
int enable = Global.getInt(mContext.getContentResolver(), Global.AUTO_ROTATION, 0);
if (enable != 1)
mAllowAllRotations = -1;
}
if (sensorRotation != Surface.ROTATION_180
|| mAllowAllRotations == 1
|| orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
|| orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER) {
preferredRotation =
mPersistentVrModeEnabled ? Surface.ROTATION_0 : sensorRotation;
} else {
preferredRotation = lastRotation;
}
} else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED
&& orientation != ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
preferredRotation = mUserRotation;
} else {
preferredRotation = -1;
}
switch (orientation) {
case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
if (isAnyPortrait(preferredRotation)) {
return preferredRotation;
}
return mPortraitRotation;
case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
if (isLandscapeOrSeascape(preferredRotation)) {
return preferredRotation;
}
return mLandscapeRotation;
case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
if (isAnyPortrait(preferredRotation)) {
return preferredRotation;
}
return mUpsideDownRotation;
case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
if (isLandscapeOrSeascape(preferredRotation)) {
return preferredRotation;
}
return mSeascapeRotation;
case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE:
if (isLandscapeOrSeascape(preferredRotation)) {
return preferredRotation;
}
if (isLandscapeOrSeascape(lastRotation)) {
return lastRotation;
}
return mLandscapeRotation;
case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT:
if (isAnyPortrait(preferredRotation)) {
return preferredRotation;
}
if (isAnyPortrait(lastRotation)) {
return lastRotation;
}
return mPortraitRotation;
default:
if (preferredRotation >= 0) {
return preferredRotation;
}
return Surface.ROTATION_0;
}
}
}
这里主要就是修改mAllowAllRotations的值,虽然每次旋转都要走这个判断要不要选择180度,但是实际上就判断一次,因为mAllowAllRotations这个值变了之后就不会再走赋值的地方了,可以看代码。所以我们要每次都要去根据要不要选择180度来改变这个值,所以每次进来先mAllowAllRotations=-1,然后就会走到赋值的那个里面,进行赋值。
是否要旋转180度的数据库。
mAllowAllRotations = Global.getInt(mContext.getContentResolver(), Global.ALLOW_ALL_ROTATION_ON,0)
注意:如果先把180度关闭,打开自动选择,把手机选择180度,然后再打开180度开关,这时候屏幕不会选择180度,正确的,但是当你再关闭自动旋转的时候,屏幕会先选择180度,然后再旋转回来。有问题,所以多加了个判断。
当自动旋转打开的时候才能旋转180。数据库自己加的。
int enable = Global.getInt(mContext.getContentResolver(), Global.AUTO_ROTATION, 0);
if (enable != 1)
mAllowAllRotations = -1;
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)