按键控制屏幕旋转功能

屏幕旋转功能在android源码中已经实现,即有专门的代码实现屏幕的旋转,这部分代码中的状态值是可以通过输入设备来改变的。如键盘、触摸屏等。

通过对android键盘系统分析我们知道,android系统把键盘的按键输入包装成了标准的事件输入。由于每一个按键都对应着相应的中断,而相应的中断对应着相应的中断处理。对于一个做好的产品,每一个按键的功能都是确定的,而且约定俗成的与android系统中键盘布局文件相一致。所以要实现按键来控制屏幕的旋转,可以采用复合按键。

在复合按键的处理代码中,我们只需增加一个分支,即新定义的复合键情况。如长按MENU


先看看android源码中屏幕旋转功能的相关代码。


*******************************************************************************


/framewords/policies/base/phone/android/internal/policy/impl中的PhoneWindowManager.java文件的PhoneWindowManaget类中就有对屏幕旋转进行处理的代码。

1、内部类SettingsObserver的重载方法onChange

try {

mWindowManager.setRotation(USE_LAST_ROTATION, false,

mFancyRotationAnimation);

} catch (RemoteException e) {

}


2、内部类MyOrientationListener中的重载方法onOrientationChanged

public void onOrientationChanged(int rotation) {

if (localLOGV) Log.v(TAG, "onOrientationChanged, rotation changed to " +rotation);

try {

mWindowManager.setRotation(rotation, false,

mFancyRotationAnimation);

} catch (RemoteException e) {

}

}








3、方法readRotation

private int readRotation(int resID) {

try {

int rotation = mContext.getResources().getInteger(resID);

switch (rotation) {

case 0:

return Surface.ROTATION_0;

case 90:

return Surface.ROTATION_90;

case 180:

return Surface.ROTATION_180;

case 270:

return Surface.ROTATION_270;

}

} catch (Resources.NotFoundException e) {

// fall through

}

return -1;

}





















4、完成按键控制屏幕旋转最核心的代码在方法interceptKeyTi。在后面会对这部分代码进行分析。

public boolean interceptKeyTi(WindowState win, int code, int metaKeys, boolean down,

int repeatCount, int flags) {

if ((code == KeyEvent.KEYCODE_HOME) && !down) {

…………

…………

}


*******************************************************************************

/frameworks/base/services/java/com/android/server/WindowManagerServices.java

1、方法:setRotation

public void setRotation(int rotation,

boolean alwaysSendConfiguration, int animFlags) {

if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,

"setRotation()")) {

throw new SecurityException("Requires SET_ORIENTATION permission");

}


setRotationUnchecked(rotation, alwaysSendConfiguration, animFlags);

}


2、紧接着setRotation调用了方法setRotationUnchecked

public void setRotationUnchecked(int rotation,

boolean alwaysSendConfiguration, int animFlags) {

long origId = Binder.clearCallingIdentity();

boolean changed;

synchronized(mWindowMap) {

changed = setRotationUncheckedLocked(rotation, animFlags);

}

if (changed) {

sendNewConfiguration();

synchronized(mWindowMap) {

mLayoutNeeded = true;

performLayoutAndPlaceSurfacesLocked();

}

} else if (alwaysSendConfiguration) {

//update configuration ignoring orientation change

sendNewConfiguration();

}


Binder.restoreCallingIdentity(origId);

}

3、在setRotationUnchecked中,对变量change赋值为了setRotationUncheckedLocked

public boolean setRotationUncheckedLocked(int rotation, int animFlags) {

boolean changed;

if (rotation == WindowManagerPolicy.USE_LAST_ROTATION) {

rotation = mRequestedRotation;

} else {

mRequestedRotation = rotation;

mLastRotationFlags = animFlags;

}

if (DEBUG_ORIENTATION) Log.v(TAG, "new rotation is set to " + rotation);

changed = mDisplayEnabled && mRotation != rotation;

Log.v(TAG, "====Qdroid====" + "mDisplayEnabled = " + mDisplayEnabled + " mRotation = " + mRotation + " changed = " + changed + " rotation = " + rotation);

if (changed) {

if (DEBUG_ORIENTATION) Log.v(TAG,

"Rotation changed to " + rotation

+ " from " + mRotation

+ " (forceApp=" + mForcedAppOrientation

+ ", req=" + mRequestedRotation + ")");

mRotation = rotation;

mWindowsFreezingScreen = true;

mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);

mH.sendMessageDelayed(mH.obtainMessage(H.WINDOW_FREEZE_TIMEOUT),

2000);

startFreezingDisplayLocked();

Log.i(TAG, "Setting rotation to " + rotation + ", animFlags=" + animFlags);

mQueue.setOrientation(rotation);

if (mDisplayEnabled) {

Surface.setOrientation(0, rotation, animFlags);

}

for (int i=mWindows.size()-1; i>=0; i--) {

WindowState w = (WindowState)mWindows.get(i);

if (w.mSurface != null) {

w.mOrientationChanging = true;

}

}

for (int i=mRotationWatchers.size()-1; i>=0; i--) {

try {

mRotationWatchers.get(i).onRotationChanged(rotation);

} catch (RemoteException e) {

}

}

} //end if changed


return changed;

}

1)、mQueue.setOrientation(rotation);这个函数完成了旋转后上下左右键功能的改变:

public void setOrientation(int orientation) {

synchronized(mFirst) {

mOrientation = orientation;

switch (orientation) {

case Surface.ROTATION_90:

mKeyRotationMap = KEY_90_MAP;

break;

case Surface.ROTATION_180:

mKeyRotationMap = KEY_180_MAP;

break;

case Surface.ROTATION_270:

mKeyRotationMap = KEY_270_MAP;

break;

default:

mKeyRotationMap = null;

break;

}

}

}

case Surface.ROTATION_90:为例

static final int[] KEY_90_MAP = new int[] {

KeyEvent.KEYCODE_DPAD_DOWN, KeyEvent.KEYCODE_DPAD_RIGHT,

KeyEvent.KEYCODE_DPAD_RIGHT, KeyEvent.KEYCODE_DPAD_UP,

KeyEvent.KEYCODE_DPAD_UP, KeyEvent.KEYCODE_DPAD_LEFT,

KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.KEYCODE_DPAD_DOWN,

};


2)、Surface.setOrientation(0, rotation, animFlags);则完成了屏幕布局的旋转:

具体实现过程见/frameworks/base/libs/surfaceflinger/路径的SurfaceFlinger.cpp

int SurfaceFlinger::setOrientation(DisplayID dpy, int orientation, uint32_t flags)

{

…………


更多相关文章

  1. 蚊子132 需要了解Android(安卓)SDK支持的配置标识符
  2. Android中关于屏幕的三个小众知识(宽屏适配、禁止截屏和保持屏幕
  3. android修改按键的映射
  4. Android(安卓)OpenGL 坐标系
  5. Vysor让你在电脑上完全控制android手机屏幕镜像
  6. Android(安卓)API Guides---Supporting Multiple Screens
  7. Android(安卓)开发中重力感应的实例
  8. Android(安卓)添加新的键值,自定义按键
  9. 问题小结(14)-旋转动画Rotate

随机推荐

  1. Android应用界面开发_学习笔记_第二周
  2. Android最简单实现日夜间模式切换
  3. 启动android后没有应用图标,找不到应用程
  4. Error : android studio 中mipmap引用.9
  5. Android面试准备(中高级)
  6. Android控件Editext、TextView属性详解
  7. Android Retrofit 2.0 注解的理解
  8. Android服务器搭建Git+Repo+Gerrit
  9. T-Mobile将率先接纳Android
  10. Android 系统信息获取(CPU,RAM,ROM,Batte