/*
Copyright 2012-2013, Polyvi Inc. (http://polyvi.github.io/openxface)
This program is distributed under the terms of the GNU General Public License.
This file is part of xFace.
xFace is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
xFace is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with xFace. If not, see <http://www.gnu.org/licenses/>.
*/
package com.polyvi.xface.view;
import java.lang.reflect.Field;
import android.os.Build;
import android.webkit.WebView;
import com.polyvi.xface.util.XLog;
/**
* 用于屏蔽input框获得焦点时自动放大问题
*/
public class XInputScaleHandler {
/**
* 处理input框获得焦点后自动放大的问题,通过反射的方法来控制mDefaultScale的值来屏蔽input框放大的行为
*/
public static final int APILEVEL_11 = 11; /** <Android 3.0.x版本API_LEVEL */
private static final int APILEVEL_13 = 13; /** <Android 3.2版本API_LEVEL */
private static final int APILEVEL_16 = 16; /**<Android 4.1/4.1.1版本API_LEVEL*/
private static final String CLASS_NAME = XInputScaleHandler.class.getSimpleName();
private static final int TIME_INTERVAL = 200;/** 根据测试经验连续2次scale change的时间上限 */
private int mAPILevel;
private long mLastScaleChangeTime;/** <记录上一次scale change的时间 */
private float mTransiScale;/** <android4.0一些版本在页面适配的过程中,一部分手机会出现中间态,这个中间态的过渡时间很短,这时不应该调用setDefaultScale去设置
mTransiScale变量用来存放scale change过程中的中间态,中间态针对每个手机,且唯一 */
public XInputScaleHandler() {
mAPILevel = Build.VERSION.SDK_INT;
}
/**
* 设置android4.0及其以上版本的DefaultScale,android4.0及其以上版本在页面scale时没有中间态,不用排除中间态的处理
* @param view
* 缩放处理的view
* @param oldScale
* 缩放之前的scale
* @param newScale
* 缩放过后的scale
*/
private void changeDefaultScaleForApiLevel14AndAbove(WebView view,
float oldScale, float newScale) {
XAppWebView appView = (XAppWebView) view;
//在4.0及以上手机 适配的过程没有中间态的过程,故一次设置到位
setDefaultScaleForApiLevel14AndAbove(newScale,appView);
/** 设置已经适配完成 */
appView.setAdapated(true);
}
/**
* 设置android2.3及其以下版本的DefaultScale,android2.3及其以下版本在页面scale时有中间态,需要排除中间态的scale
* @param view
* 缩放处理的view
* @param oldScale
* 缩放之前的scale
* @param newScale
* 缩放过后的scale
*/
private void changeDefaultScaleForApiLevel10AndBelow(WebView view,
float oldScale, float newScale) {
/** 连续2次scale change的时间间隔小于200ms,则认为中间态存在,提取中间态 */
if((System.currentTimeMillis()-mLastScaleChangeTime)<TIME_INTERVAL && 0 == mTransiScale )
{
mTransiScale = oldScale;
}
/**适配的scale不是中间态才去设置mDefaultScale的值 */
if(newScale != mTransiScale || newScale == oldScale)
{
setDefaultScaleForApiLevel10AndBelow(newScale, view);
XAppWebView appView = (XAppWebView)view;
/** 设置已经适配完成 */
appView.setAdapated(true);
}
mLastScaleChangeTime = System.currentTimeMillis();
}
/**
* 根据android的系统版本改变webview的私有成员变量mDefaultScale
* @param view
* webview实例
* @param oldScale
* 适配之前的scale
* @param newScale
* 适配之后的scale
*/
public void changeDefaultScale(WebView view, float oldScale, float newScale) {
// TODO:目前没有处理API LEVEL 在11到13之间的android版本,以及超过APILEVIE16的版本
if (mAPILevel < APILEVEL_11) {
changeDefaultScaleForApiLevel10AndBelow(view, oldScale, newScale);
} else if (mAPILevel > APILEVEL_13 && mAPILevel < APILEVEL_16) {
changeDefaultScaleForApiLevel14AndAbove(view, oldScale, newScale);
}
//剩下的情况为3.x的android系统,直接将Adapated设置为true来屏蔽双击放大
else
{
XAppWebView appView = (XAppWebView)view;
/** 设置已经适配完成 */
appView.setAdapated(true);
}
}
/**
* 设置当前WebView的mDefaultScale为xface控制mOwnDefaulScale,此方法是适用于Android2.3及以下版本
* @param scale
* 要设置的scale值
*/
public void setDefaultScaleForApiLevel10AndBelow(float defaultScale,
WebView view) {
try {
Field mFieldDefaultScale = WebView.class
.getDeclaredField("mDefaultScale");
mFieldDefaultScale.setAccessible(true);
mFieldDefaultScale.setFloat(view, defaultScale);
} catch (Exception e) {
XLog.e(CLASS_NAME, e.toString());
}
}
//TODO:由于是通过反射的方式来修改mDefaultScale的值,在将来的版本中可能需要修改设置的方法
/**
* 设置当前WebView的mDefaultScale为xface控制mOwnDefaulScale,由于从android4.0
* 版本开始改用mZoomManager来管理缩放,所以反射方法不同
* @param scale
* 要设置的scale值
*/
public void setDefaultScaleForApiLevel14AndAbove(float defaultScale,WebView view) {
try {
Field mFieldZoomManager = WebView.class
.getDeclaredField("mZoomManager");
mFieldZoomManager.setAccessible(true);
Object mObjZoomManager = mFieldZoomManager.get(view);
Class mClassZoomManager = Class
.forName("android.webkit.ZoomManager");
Field mDefaultScale = mClassZoomManager
.getDeclaredField("mDefaultScale");
mDefaultScale.setAccessible(true);
mDefaultScale.setFloat(mObjZoomManager, defaultScale);
} catch (Exception e) {
XLog.e(CLASS_NAME, e.toString());
}
}
}