安卓5.0新加辅助功能(高对比性文字/色彩校正/颜色反转)学习

摘要

在安卓L版本中,辅助设置中新加了3个功能,分别是高对比性文字,颜色反转,色彩校正


Accessibility.jpg


高对比性文字

  • 先来看看google是怎么说这个功能的
This information applies only to devices running Android 5.0 and higher.

High contrast makes text easier to read on your device. This feature fixes the text color as either black or white, depending on the original text color.

To enable or disable high contrast text, follow these steps:
Go to Settings > Accessibility.
Select High contrast text.

High-contrast text is currently an experimental feature, so it might not work correctly everywhere on your device.
  • 再来看看效果图
HighContrastText.jpg
google说,这个功能就是让文字更容易阅读,也就是有点类似与文字高亮。最后的效果就是,把文字变成白色或黑色,把背景文字背景变成黑色或白色
也就是说,如果你之前的文字是白色,背景是黑色,就不会去应用这个功能,即使开启了,就想上面设置的actionbar
  • 最后看看怎么实现的,简单分析
HighContrastText.png
从上图可以看出,最后文字为何会这样显示,是因为在操作ViewRootImpl,遍历view,重新绘制。当然上图可能不是很完整,因为重绘前还需要view中之前的状态,比如之前的颜色什么的。
不过,我们大概已经知道,只要实现是通过修改ViewRootImpl来达到系统中所有view都能显示成这个效果的目的


颜色反转

  • 先看看google是怎么说这个功能的
This information applies only to devices running Android 5.0 and higher.

Color inversion exchanges color values. For example, black text on a white screen becomes white text on a black screen.

To enable or disable color inversion, follow these steps:
Go to Settings > Accessibility.
Select Color inversion.

Color inversion is currently an experimental feature, so it might not work correctly everywhere on your device.
  • 再来看看效果图
 下面两幅图是在浏览器页面,第一副是未开启颜色反转功能的,第二幅是开启颜色反转后的。
开启颜色反转后,所有的地方都会出现上述效果
Color Inversion.jpg
从上面的效果图上看出,这个功能与有的浏览器推出的夜间模式很像。
也就是说,我们可以通过这个功能达到晚上玩手机不会刺眼,可以仿真出夜晚效果
  • 最后来看看实现,简单分析
这是开启颜色反转的时序图
再跳转到后面看开启色彩校正后的时序图,会发现这两个操作后的流程是一样的

ColorInversion.png


色彩校正

  • 先看看google是怎么说这个功能的
This information applies only to devices running Android 5.0 and higher.

The color correction setting enables your device to compensate for color blindness.

To enable or disable color correction, follow these steps:
Go to Settings > Accessibility > Color correction.
Set the switch to the on or off position.
To change the color correction mode, select Correction mode, then choose one of the following options:
Deuteranomaly (red-green)
Protanomaly (red-green)
Tritanomaly (blue-yellow)

Color correction is currently an experimental feature, so it might not work correctly everywhere on your device.
  • 再来看看效果图
下面四幅图是在launcher界面,为了让效果更明显,安装了360 launcher,将app按照图标颜色分类
第一副是未开启颜色校正的
第二副是开启后,选择红弱视,会发现红色的图标变暗了
第二副是开启后,选择绿弱视,会发现绿色的图标变暗了
第二副是开启后,选择蓝弱视,会发现蓝色的图标变暗了
ColorCorrection.jpg
根据google说明,该功能是给色盲色弱的提供。
我这里还不是很明白,选择红弱视后,红色变暗了;红弱视本生在较亮的环境下是可以看清楚的,变暗后不是更看不清了吗!!
  • 最后来看看实现,简单分析
这是开启色彩校正后的时序图

ColorCorrection.png
  • 先简单说下颜色反转和色彩校正的实现原理
通过SurfaceFlinger去控制gpu改变屏幕的显示效果,给你视觉上的错觉,控件本身并没有被改变。
高对比性文字是修改了控件,而这两个功能只是给你显示上的错觉,开启后,截屏放到电脑看到的仍然是未开启时的效果
  • 颜色反转和色彩校正流程原理分析
无论是颜色反转还是色彩校正,都会在数据库(SettingsProvider)中保存一个值。
AccessibilityManagerService这个类就是为辅助功能服务的
AccessibilityManagerService会去注册一个监听,监听辅助功能中哪些值被改变了
当开启颜色校正或颜色反转后,AccessibilityManagerService就会监听到,然后按照上面的时序图执行
AccessibilityManagerService会调用DisplayAdjustmentUtils的applyAdjustments方法
在这个方法里会执行multiply,setDaltonizerMode,setColorTransform
multiply方法中主要用于计算颜色矩阵
    private static float[] multiply(float[] matrix, float[] other) {
        if (matrix == null) {
            return other;
        }
        float[] result = new float[16];
        Matrix.multiplyMM(result, 0, matrix, 0, other, 0);
        return result;
    }
setDaltonizerMode方法主要用于设置仿真模式
可以看出该方法会通过binder连接到SurfaceFlinger,将mode传递过去
    /**
     * Sets the surface flinger's Daltonization mode. This adjusts the color
     * space to correct for or simulate various types of color blindness.
     *
     * @param mode new Daltonization mode
     */
    private static void setDaltonizerMode(int mode) {
        try {
            final IBinder flinger = ServiceManager.getService("SurfaceFlinger");
            if (flinger != null) {
                final Parcel data = Parcel.obtain();
                data.writeInterfaceToken("android.ui.ISurfaceComposer");
                data.writeInt(mode);
                flinger.transact(1014, data, null, 0);
                data.recycle();
            }
        } catch (RemoteException ex) {
            Slog.e(LOG_TAG, "Failed to set Daltonizer mode", ex);
        }
    }
setColorTransform主要用于设置颜色转换
可以看出该方法会通过binder连接到SurfaceFlinger,将一个颜色矩阵传递过去
 /**
     * Sets the surface flinger's color transformation as a 4x4 matrix. If the
     * matrix is null, color transformations are disabled.
     *
     * @param m the float array that holds the transformation matrix, or null to
     *            disable transformation
     */
    private static void setColorTransform(float[] m) {
        try {
            final IBinder flinger = ServiceManager.getService("SurfaceFlinger");
            if (flinger != null) {
                final Parcel data = Parcel.obtain();
                data.writeInterfaceToken("android.ui.ISurfaceComposer");
                if (m != null) {
                    data.writeInt(1);
                    for (int i = 0; i < 16; i++) {
                        data.writeFloat(m[i]);
                    }
                } else {
                    data.writeInt(0);
                }
                flinger.transact(1015, data, null, 0);
                data.recycle();
            }
        } catch (RemoteException ex) {
            Slog.e(LOG_TAG, "Failed to set color transform", ex);
        }
    }

接着会调用SurfaceFlinger的onTransact方法
setDaltonizerMode传过来的code值是1014
setColorTransform传过来的code值是1015
当设置颜色反转时,mode为-1,也就是说会执行mDaltonizer.setMode(Daltonizer::simulation);
当设置颜色校正时,mode会大于10(11红弱视,12绿弱视,13蓝弱视),会执行mDaltonizer.setMode(Daltonizer::correction);也会设置相应的type
case 1015中会将setColorTransform传递过来的颜色矩阵拿出来,doDisplayComposition方法会通过shader让gpu显示出效果
最后调用repaintEverything重绘
 frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
 status_t SurfaceFlinger::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
 {
         ......省略数行......
         switch (code) {
		 ......省略数行......
             case 1014: {
                 // daltonize
                 n = data.readInt32();
                 switch (n % 10) {
                     case 1: mDaltonizer.setType(Daltonizer::protanomaly);   break;
                     case 2: mDaltonizer.setType(Daltonizer::deuteranomaly); break;
                     case 3: mDaltonizer.setType(Daltonizer::tritanomaly);   break;
                 }
                 if (n >= 10) {
                     mDaltonizer.setMode(Daltonizer::correction);
                 } else {
                     mDaltonizer.setMode(Daltonizer::simulation);
                 }
                 mDaltonize = n > 0;
                 invalidateHwcGeometry();
                 repaintEverything();
                 return NO_ERROR;
             }
             case 1015: {
                 // apply a color matrix
                 n = data.readInt32();
                 mHasColorMatrix = n ? 1 : 0;
                 if (n) {
                     // color matrix is sent as mat3 matrix followed by vec3
                     // offset, then packed into a mat4 where the last row is
                     // the offset and extra values are 0
                     for (size_t i = 0 ; i < 4; i++) {
                       for (size_t j = 0; j < 4; j++) {
                           mColorMatrix[i][j] = data.readFloat();
                       }
                     }
                 } else {
                     mColorMatrix = mat4();
                 }
                 invalidateHwcGeometry();
                 repaintEverything();
                 return NO_ERROR;
             }
            ......省略数行...... 
         }
     }
     return err;
 }
 
 frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::doDisplayComposition(const sp<const DisplayDevice>& hw,
        const Region& inDirtyRegion)
 {
     ......
 
     if (CC_LIKELY(!mDaltonize && !mHasColorMatrix)) {
         if (!doComposeSurfaces(hw, dirtyRegion)) return;
     } else {
         RenderEngine& engine(getRenderEngine());
         mat4 colorMatrix = mColorMatrix;
         if (mDaltonize) {
             colorMatrix = colorMatrix * mDaltonizer();
         }
         engine.beginGroup(colorMatrix);
         doComposeSurfaces(hw, dirtyRegion);
         engine.endGroup();
     }
      ......
 }
最后看看仿真器
 frameworks/native/services/surfaceflinger/Effects/Daltonizer.h
class Daltonizer {
 public:
     enum ColorBlindnessTypes {
         protanopia,         // L (red) cone missing 红色盲
         deuteranopia,       // M (green) cone missing 绿色盲
         tritanopia,         // S (blue) cone missing 蓝色盲
         protanomaly,        // L (red) cone deficient 红色弱
         deuteranomaly,      // M (green) cone deficient (most common) 绿色弱
         tritanomaly         // S (blue) cone deficient 蓝色弱
     };
 
     enum Mode {
         simulation, //仿真,开启颜色反转后模式
         correction  //校正,开启色彩校正后模式
     };
 ......


小结

高对比性文字主要是修改控件,颜色反转和颜色校正主要是通过操作gpu修改显示效果


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值