Android键盘系统——改变按键功能(2)

按键控制屏幕旋转功能

    屏幕旋转功能在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)

{

…………


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值