android辅助功能手势,Android辅助功能——全局手势放大实现原理

在Android的辅助功能中,存在一个点击三次屏幕触发屏幕放大功能。

0178f054a031

辅助功能中打开

0178f054a031

放大后效果

这个功能的使用频率实在是低...但是为什么会想记录一下这个功能的实现原理。第一,在处理性能问题的时候遇到了相关代码;其次其实现的原理还是具有部分启发性质的。主要还是研究启发部分:

1、如何实现手势拦截

2、全局放大的原理(主要在system_server中存在双编舞者协作实现),如下图所示在启动手势放大过程中systrace抓取到下面的现象:

0178f054a031

两个编舞者协同工作

一、手势拦截

在设置中打开放大手势的开关,会设置Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED这个属性值,AccessiblityContentObserver中的onChange会处理这个值的变化:

@Override

4456 public void onChange(boolean selfChange, Uri uri) {

4457 synchronized (mLock) {

4458 // Profiles share the accessibility state of the parent. Therefore,

4459 // we are checking for changes only the parent settings.

4460 UserState userState = getCurrentUserStateLocked();

4461

4462 // If the automation service is suppressing, we will update when it dies.

4463 if (userState.isUiAutomationSuppressingOtherServices()) {

4464 return;

4465 }

4466

4467 if (mTouchExplorationEnabledUri.equals(uri)) {

4468 if (readTouchExplorationEnabledSettingLocked(userState)) {

4469 onUserStateChangedLocked(userState);

4470 }

4471 } else if (mDisplayMagnificationEnabledUri.equals(uri)) {

4472 if (readDisplayMagnificationEnabledSettingLocked(userState)) {

4479 onUserStateChangedLocked(userState);

4480 }

4481 }

在onUserStateChangedLocked中会调用updateMagnificationLocked以及scheduleUpdateInputFilter去更新当前系统状态:

updateMagnificationLocked是用于建立wms和辅助功能服务的联系

scheduleUpdateInputFilter是用于在输入层面建立手势拦截,往Input流程中加入inputfilter

1820 private void updateMagnificationLocked(UserState userState) {

1821 if (userState.mUserId != mCurrentUserId) {

1822 return;

1823 }

1824

1825 if (userState.mIsDisplayMagnificationEnabled ||

1826 userHasListeningMagnificationServicesLocked(userState)) {

1827 // Initialize the magnification controller if necessary

1828 getMagnificationController();

//核心在于放大控制器的注册

1829 mMagnificationController.register();

1830 } else if (mMagnificationController != null) {

//当关闭此功能的时候会调用反注册

1831 mMagnificationController.unregister();

1832 }

1833 }

实际上就是通过MagnificationController去注册。

55/**

56 * This class is used to control and query the state of display magnification

57 * from the accessibility manager and related classes. It is responsible for

58 * holding the current state of magnification and animation, and it handles

59 * communication between the accessibility manager and window manager.

60 */

61class MagnificationController

从对这个类的描述可以看出,它是为了控制和查询当前屏幕的放大状态;其次用于辅助服务和WMS之间的通信工作。这些具体的含义还是放到代码中去一一解释。

首先看看他的register函数:

public void register() {

130 synchronized (mLock) {

131 if (!mRegistered) {

//step1、注册广播监听亮灭屏事件

132 mScreenStateObserver.register();

//step2、注册WMS中的回调(与WMS之间通信)

133 mWindowStateObserver.register();

//step3、使能跟动画相关的函数(虽然这个类名字有点奇怪,但还是能猜到是跟动画相关的)

134 mSpecAnimationBridge.setEnabled(true);

135 // Obtain initial state.

136 mWindowStateObserver.getMagnificationRegion(mMagnificationRegion);

137 mMagnificationRegion.getBounds(mMagnificationBounds);

138 mRegistered = true;

139 }

140 }

141 }

step1就略过从step2开始看它是如何跟wms进行交互的。

/**

957 * This class handles the screen magnification when accessibility is enabled.

958 */

959 private static class WindowStateObserver

960 implements WindowManagerInternal.MagnificationCallbacks {

......

975

976 public WindowStateObserver(Context context, MagnificationController controller) {

977 mController = controller;

978 mWindowManager = LocalServices.getService(WindowManagerInternal.class);

979 mHandler = new CallbackHandler(context);

980 }

981

982 public void register() {

987 mWindowManager.setMagnificationCallbacks(this);

990 }

991

WindowStateObserver实现了接口MagnificationCallbacks,这个接口是wms用于通知放大控制器当前wms端有了哪些变化的:

/**

51 * Callbacks for contextual changes that affect the screen magnification

52 * feature.

53 */

54 public interface MagnificationCallbacks {

55

56 /**

57 * Called when the region where magnification operates changes. Note that this isn't the

58 * entire screen. For example, IMEs are not magnified.

*这种情况在放大的情况下点开了输入法,输入法界面是不能够被放大的,但是由于其占用了一定的屏幕空间,就会导致放大的区域变小,wms就会回调注册的该方法

59 *

60 * @param magnificationRegion the current magnification region

61 */

62 public void onMagnificationRegionChanged(Region magnificationRegion);

63

64 /**

65 * Called when an application requests a rectangle on the screen to allow

66 * the client to apply the appropriate pan and scale.

67 *

68 * @param left The rectangle left.

69 * @param top The rectangle top.

70 * @param right The rectangle right.

71 * @param bottom The rectangle bottom.

72 */

73 public void onRectangleOnScreenRequested(int left, int top, int right, int bottom);

74

75 /**

76 * Notifies that the rotation changed.

77 *

78 * @param rotation The current rotation.

79 */

80 public void onRotationChanged(int rotation);

81

82 /**

83 * Notifies that the context of the user changed. For example, an application

84 * was started.

*context发生变化(个人理解为当前Activity发生了切换)

85 */

86 public void onUserContextChanged();

87 }

通过注册WindowStateObserver到WMS,就建立wms和AccessibilityMS的沟通了。

回到前面的step3,使能SpecAnimationBridge,从下面这个类的注释可以看出它有两个功能

/**

727 * Class responsible for animating spec on the main thread and sending spec

728 * updates to the window manager.

729 */

730 private static class SpecAnimationBridge {

1:将放大相关的参数发送给wms

<
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 要实现在Android应用中的退出提示功能,可以通过以下步骤: 1. 创建一个AlertDialog来显示提示信息。AlertDialog可以通过以下代码创建: ```java AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setMessage("确定要退出应用吗?") .setCancelable(false) .setPositiveButton("确定", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { // 退出应用 finish(); } }) .setNegativeButton("取消", null); AlertDialog alert = builder.create(); alert.show(); ``` 2. 在需要退出应用的地方调用AlertDialog的show()方法。例如,在菜单项中添加退出应用的选项: ```java @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.menu_exit: AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setMessage("确定要退出应用吗?") .setCancelable(false) .setPositiveButton("确定", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { // 退出应用 finish(); } }) .setNegativeButton("取消", null); AlertDialog alert = builder.create(); alert.show(); return true; default: return super.onOptionsItemSelected(item); } } ``` 这样,在用户选择退出应用时,就会弹出AlertDialog并提示用户是否确定退出。如果用户选择确定,则调用finish()方法退出应用。 ### 回答2: Android实现退出提示的功能有多种方法,可以通过对返回键的监听,或者通过自定义的退出按钮来实现。 一种常见的实现方式是对返回键进行监听。当用户按下返回键时,先弹出一个对话框来确认是否退出应用。我们可以在Activity的`onBackPressed()`方法中进行监听,代码如下所示: ```java @Override public void onBackPressed() { new AlertDialog.Builder(this) .setMessage("确定要退出应用吗?") .setPositiveButton("确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // 退出应用 finish(); } }) .setNegativeButton("取消", null) .show(); } ``` 在上面的代码中,我们创建了一个AlertDialog的实例,并设置了对应的消息内容、确定按钮的点击事件和取消按钮的点击事件。当用户点击确定按钮时,调用`finish()`方法来退出应用。 另一种常见的实现方式是通过自定义的退出按钮来实现。在布局文件中添加一个退出按钮,然后在对应的Activity中为按钮设置点击事件,在点击事件中弹出对话框并处理退出逻辑,代码如下所示: ```java Button exitButton = findViewById(R.id.exit_button); exitButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new AlertDialog.Builder(MainActivity.this) .setMessage("确定要退出应用吗?") .setPositiveButton("确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // 退出应用 finish(); } }) .setNegativeButton("取消", null) .show(); } }); ``` 在上面的代码中,我们首先通过findViewById()方法找到退出按钮,并为其设置点击事件。点击事件中弹出对话框,确认后调用`finish()`方法来退出应用。 以上两种方法都是常用的实现退出提示功能的方式,具体根据应用的需求选择适合的方式即可。 ### 回答3: 要实现在Android应用中的退出提示功能,可以通过以下步骤来实现: 1. 在您的MainActivity类中,创建一个全局的boolean变量isExit,并初始化为false。这个变量将用于判断用户是否已经请求退出应用。 2. 在onBackPressed()方法中,判断用户是否已经点击了返回按钮。如果是,则执行退出提示逻辑。 ```java @Override public void onBackPressed() { if (isExit) { super.onBackPressed(); // 如果用户已经点击了返回按钮两次,则执行默认的系统退出逻辑 } else { Toast.makeText(this, "再按一次返回键退出应用", Toast.LENGTH_SHORT).show(); isExit = true; // 2秒后重置isExit变量为false,以便下一次点击返回按钮时重新显示退出提示 new Handler().postDelayed(new Runnable() { @Override public void run() { isExit = false; } }, 2000); } } ``` 3. 这样,当用户第一次点击返回按钮时,会弹出一个提示信息,并将isExit设置为true。之后会通过Handler延时2秒后将isExit设置为false。如果2秒内用户再次点击返回按钮,则会执行super.onBackPressed(),即默认的系统退出逻辑。 通过以上步骤,您就可以在您的Android应用中实现退出提示的功能。用户在点击返回按钮时,会弹出一个提示信息,再次点击返回按钮即可退出应用。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值