[Android] 关于Window Overscan

Overscan的概念

对于电视机,有一个Overscan的概念,如下图,所谓Overscan区域,就是电视机屏幕四周某些不可见的区域,这是电视机的特性。并且,Overscan的具体值也没有一个明确的标准,不同的电视机厂家的Overscan的值也各不相同。

而对于普通的LCD,由于并没有Overscan的概念,所以设想,将一块没有设置Overscan的Framebuffer显示到有Overscan的电视机上,必定四周有一部分Overscan的区域被切除到无法显示出来。

所以在Android 4.3以后,Google加入了Overscan的API,并且提供了wm工具,可以让用户设定Overscan的值,来满足不同的电视机。

上图中,包含了Overscan的整个区域我们称之为Overscan Screen;

去处Overscan区域后称之为 Unrestricted Area,由绿色和紫色区域组成,绿色区域用于显示Status Bar和Navigation Bar;

剩下的紫色区域为 Restricted Area,这里显示的为mContentFrame。

关于WM Tool

Android 4.3之后,加入了Overscan的概念,并且提供了wm工具来设定Overscan的值。(参考git commit:c652de8141f5b8e3c6bcf8916842b6e106413b1a)

代码调用流程:

简单来讲就是,当我们设置了Overscan值后,WindowManagerService、PhoneWindowManager等会对当前显示的View的参数做重新计算,将计算完的数值会传给View,让其重新Layout。

关于输入法的Bug

一个存在的Bug是,当我们设置完Overscan后,google 的虚拟键盘并没有跟着Overscan的变化而缩放,虚拟键盘的一部分会被Overscan的区域遮挡无法显示。

原因:虚拟键盘是通过Canvas绘制到屏幕上,而虚拟键盘上每一个组件的大小是根据屏幕的实际像素和深度来计算的,代码:

packages/inputmethods/LatinIME/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java

final Resources res = mThemeContext.getResources();
builder.setScreenGeometry(res.getInteger(R.integer.config_device_form_factor),
     res.getConfiguration().orientation, res.getDisplayMetrics().widthPixels);

所以,Keyboard会撑满Overscan Screen,而我们期望的是让Keyboard撑满Unrestricted Area,故我们做以下修改:

1. 让Display.java中的getWidth方法返回除去Overscan长度后的值。

frameworks/base/core/java/android/view/Display.java

     public int getWidth() {
    synchronized (this) {
      updateCachedAppSizeIfNeededLocked();
      updateDisplayInfoLocked();
      return mCachedAppWidthCompat - mDisplayInfo.overscanLeft - mDisplayInfo.overscanRight ;
         }
     }

2. 在LatinIME中添加mWidth变量,用于存放Keyboard宽度。

packages/inputmethods/LatinIME/java/src/com/android/inputmethod/latin/SettingsValues.java

  public static int mWidth;

  public SettingsValues(final SharedPreferences prefs, final InputAttributes inputAttributes, final Context context) {
    if(mWidth == 0){
      mWidth = res.getDisplayMetrics().widthPixels;
    }
  }

3. 每次虚拟键盘弹出前,比较当前的Width和设定Width是否相同,不同和替代,并重新初始化Keyboard。注,此处InputManagerService的getMaxWidth方法最终会调用Step1的getWidth方法。

packages/inputmethods/LatinIME/java/src/com/android/inputmethod/latin/LatinIME.java

    private void onStartInputViewInternal(final EditorInfo editorInfo, final boolean restarting) {
        super.onStartInputView(editorInfo, restarting);
// Deal with overscan area
        if(mCurrentSettings.mWidth != getMaxWidth()){
            mCurrentSettings.mWidth = getMaxWidth();
            loadKeyboard();
        }
 }       

4.将初始化键盘宽度的值从res.getDisplayMetrics().widthPixels改成settingsValues.mWidth。

packages/inputmethods/LatinIME/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java

    public void loadKeyboard(EditorInfo editorInfo, SettingsValues settingsValues) {
        final KeyboardLayoutSet.Builder builder = new KeyboardLayoutSet.Builder(
                mThemeContext, editorInfo);
        final Resources res = mThemeContext.getResources();
//      builder.setScreenGeometry(res.getInteger(R.integer.config_device_form_factor),
//              res.getConfiguration().orientation, res.getDisplayMetrics().widthPixels);
        builder.setScreenGeometry(res.getInteger(R.integer.config_device_form_factor),
                res.getConfiguration().orientation, settingsValues.mWidth);

    }

参考

http://blog.csdn.net/cjj7905150/article/details/17888377

时间: 2024-08-05 06:43:23

[Android] 关于Window Overscan的相关文章

Android Starting Window(Preview Window)

当打开一个Activity时,如果这个Activity所属的应用还没有在运行,系统会为这个Activity所属的应用创建一个进程,但进程的创建与初始化都需要时间,在这个动作完成之前系统要做什么呢?如果没有任何反应的话,如果程序初始化的时间很长,用户可能还以为没有点到相应的位置.但此时所启动的程序还没初始化完,既无法显示程序,又不能停在原处不做任何动作,怎么办?这就有了Starting Window的概念,也可以称之为Preview Window. Starting Window就是一个用于在应用

Android 之 Window、WindowManager 与窗口管理

其实在android中真正展示给用户的是window和view,activity在android中所其的作用主要是处理一些逻辑问题,比如生命周期的管理.建立窗口等.在android中,窗口的管理还是比较重要的一块,因为他直接负责把内容展示给用户,并和用户进行交互.响应用户的输入等. 在讲窗口管理时,有必要先说下ViewManager这个接口,这个接口主要有以下的实现子接口和实现类,分别是:WindowManager和ViewGroup里面还有三个重要的方法: * addView(); * upd

(转) Android的Window类

Android的Window类 2011-03-25 10:02 by Keis, 110 visits, 网摘, 收藏, 编辑 Android的Window类(一)  Android的GUI层并不复杂.它的复杂度类似于WGUI这类基于布局和对话框的GUI,与MFC.QT等大型框架没有可比性,甚至飞漫魏永明的MiniGUI都比它复杂许多.您也许会问,这样简单的GUI如何实现浏览器呢?原因很简单,浏览器有自己一套GUI.Android浏览器(WebKit)的GUI和Android的GUI实用同一套

android设置window背景透明的bug

今天解决了一个bug,在我们产品中的界面上快速点击某个控件(点击完要跳转到其他Activity),会调起其他的app! 最初的想法是,使用了overridependingtransition,导致在切换过程中,App失去了对touch实践的捕获,结果去掉之后还是无法解决. 也没有什么特别好的想法,这种没有日志的bug最难解决!不停的重试,无意中发现,在Activity切换过程中,使用退出动画(缩放)的Activity 后面都是透明的,launcher都显示了出来,虽然面积不大,但还是被我发现了.

Android中Window添加View的底层原理

一,WIndow和windowManager Window是一个抽象类,它的具体实现是PhoneWindow,创建一个window很简单,只需要创建一个windowManager即可,window具体实现在windowManagerService中,windowManager和windowManagerService的交互是一个IPC的过程. 下面是用windowManager的例子: mFloatingButton = new Button(this); mFloatingButton.set

Android View, Window,Activity概念区分(2)

(1)View:最基本的UI组件,表示屏幕上的一个矩形区域. (2)Window: 表示一个窗口,不一定有屏幕那么大,可以很大也可以很小:它包含一个View tree和窗口的layout 参数.View tree的root View可以通过getDecorView得到.还可以设置Window的Content View. (3)Activity:Activity包含一个Window,该Window在Activity的attach方法中通过调用PolicyManager.makeNewWindo创建

QT 5.3.2 for android 在window XP 32bit 和 WIN 8.1 64bit 上面环境搭建 (一)

安装QT 5.3.2 for windows 经过了不少折腾,总算把它安装OK ,helloworld 跑起来了. Windows xp 需要的安装包: 1.android-ndk-r9d-windows-x86.zip 2.adt-bundle-windows-x86-20140321.zip 3.apache-ant-1.9.4-bin.zip 4.JDK的包,我的是jdk1.7.0_15 ,以前就安装好的. 5.qt-opensource-windows-x86-android-5.3.2

Android之Window

window表示的是一个抽象窗口类,该类只是一个抽象窗口类,其具体的唯一实现类是PhoneWindow类.Window对象的获取通过在Activity中调用getWindow()方法获取到Window对象:该类定义了一个CallBack接口,用于处理用户的消息数据,该接口的方法有:dispatchKeyEvent,dispatchTouchEvent等, 他设置了一组通用的窗口操作api.比如setContentView方法,实际上Activity中的setContentView方法是调用的Ac

Android Popup Window 居于控件上方突出显示

public class TestPopupWindowActivity extends PopupWindow { Activity context; public TestPopupWindowActivity(Activity context, View v) { super(context); this.context = context; RelativeLayout mContentView = new RelativeLayout(context); RelativeLayout.