Add support for adjusting text in the WebView to the preferred zoom scale on Android.

More robust iOS support is forthcoming, but currently works with iOS7
Dynamic Type Fonts by setting the following css on the body and using
relatively sized fonts sizing for child containers, for example:

body {
   font: -apple-system-body;
}

body > .app {
  font-family: 'HelveticaNeue-Light', 'HelveticaNeue', Helvetica,
Arial, sans-serif;
  font-size:0.75em;
  font-weight: 200;
}
This commit is contained in:
Michael Jordan 2014-03-06 21:44:05 -05:00
parent 4b62a1f24a
commit 728a327ab0
7 changed files with 191 additions and 15 deletions

View File

@ -17,8 +17,8 @@
<clobbers target="window.MobileAccessibility" />
</js-module>
<dependency id="org.apache.cordova.device" url="https://git-wip-us.apache.org/repos/asf/cordova-plugin-device.git" />
<dependency id="org.apache.cordova.network-information" url="https://git-wip-us.apache.org/repos/asf/cordova-plugin-network-information.git" />
<dependency id="org.apache.cordova.device" url="https://github.com/apache/cordova-plugin-device.git" />
<dependency id="org.apache.cordova.network-information" url="https://github.com/apache/cordova-plugin-network-information.git" />
<!-- ios -->
<platform name="ios">

View File

@ -15,4 +15,6 @@ public abstract class AbstractMobileAccessibilityHelper {
public abstract void addStateChangeListeners();
public abstract void removeStateChangeListeners();
public abstract void announceForAccessibility(CharSequence text);
public abstract int getTextZoom();
public abstract void setTextZoom(int textZoom);
}

View File

@ -4,8 +4,10 @@ package com.phonegap.plugin.mobileaccessibility;
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.util.Log;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.webkit.WebSettings;
import android.webkit.WebView;
@TargetApi(Build.VERSION_CODES.DONUT)
@ -18,7 +20,6 @@ public class DonutMobileAccessibilityHelper extends
public void initialize(MobileAccessibility mobileAccessibility) {
mMobileAccessibility = mobileAccessibility;
mWebView = mobileAccessibility.webView;
mParent = mobileAccessibility.webView.getParentForAccessibility();
mAccessibilityManager = (AccessibilityManager) mMobileAccessibility.cordova.getActivity().getSystemService(Context.ACCESSIBILITY_SERVICE);
}
@ -76,5 +77,52 @@ public class DonutMobileAccessibilityHelper extends
mAccessibilityManager.sendAccessibilityEvent(event);
}
@SuppressWarnings("deprecation")
@Override
public int getTextZoom() {
int zoom = 100;
WebSettings.TextSize wTextSize = mWebView.getSettings().getTextSize();
switch (wTextSize) {
case LARGEST:
zoom = 200;
break;
case LARGER:
zoom = 150;
break;
case NORMAL:
zoom = 100;
break;
case SMALLER:
zoom = 75;
break;
case SMALLEST:
zoom = 50;
break;
default:
zoom = 100;
break;
}
return zoom;
}
@SuppressWarnings("deprecation")
@Override
public void setTextZoom(int textZoom) {
final int zoom = textZoom;
WebSettings.TextSize wTextSize = WebSettings.TextSize.NORMAL;
if (zoom > 115) {
wTextSize = WebSettings.TextSize.LARGEST;
} else if (zoom > 100) {
wTextSize = WebSettings.TextSize.LARGER;
} else if (zoom == 100) {
wTextSize = WebSettings.TextSize.NORMAL;
} else if (zoom > 50) {
wTextSize = WebSettings.TextSize.SMALLER;
} else {
wTextSize = WebSettings.TextSize.SMALLEST;
}
//Log.i("MobileAccessibility", "fontScale = " + zoom + ", WebSettings.TextSize = " + wTextSize.toString());
mWebView.getSettings().setTextSize(wTextSize);
}
}

View File

@ -3,6 +3,7 @@ package com.phonegap.plugin.mobileaccessibility;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.annotation.TargetApi;
import android.os.Build;
import android.util.Log;
import android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener;
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
@ -29,6 +30,18 @@ public class IceCreamSandwichMobileAccessibilityHelper extends
mAccessibilityStateChangeListener = null;
}
@Override
public int getTextZoom() {
return mWebView.getSettings().getTextZoom();
}
@Override
public void setTextZoom(int textZoom) {
final int zoom = textZoom;
//Log.i("MobileAccessibility", "setTextZoom(" + zoom + ")");
mWebView.getSettings().setTextZoom(zoom);
}
protected class InternalAccessibilityStateChangeListener
implements AccessibilityStateChangeListener {

View File

@ -1,5 +1,7 @@
package com.phonegap.plugin.mobileaccessibility;
import com.phonegap.plugin.mobileaccessibility.MobileAccessibility;
import android.annotation.TargetApi;
import android.os.Build;
import android.view.accessibility.AccessibilityEvent;
@ -8,6 +10,12 @@ import android.view.accessibility.AccessibilityEvent;
public class JellyBeanMobileAccessibilityHelper extends
IceCreamSandwichMobileAccessibilityHelper {
@Override
public void initialize(MobileAccessibility mobileAccessibility) {
super.initialize(mobileAccessibility);
mParent = mobileAccessibility.webView.getParentForAccessibility();
}
@Override
public void announceForAccessibility(CharSequence text) {
if (mAccessibilityManager.isEnabled() && mParent != null) {

View File

@ -22,6 +22,7 @@ public class MobileAccessibility extends CordovaPlugin {
protected boolean mClosedCaptioningEnabled = false;
protected boolean mTouchExplorationEnabled = false;
protected boolean mCachedIsScreenReaderRunning = false;
protected float mFontScale = 1;
@Override
public void initialize(CordovaInterface cordova, CordovaWebView webView) {
@ -58,6 +59,20 @@ public class MobileAccessibility extends CordovaPlugin {
}
}
return true;
} else if(action.equals("getTextZoom")) {
getTextZoom(callbackContext);
return true;
} else if(action.equals("setTextZoom")) {
if (args.length() > 0) {
int textZoom = args.getInt(0);
if (textZoom > 0) {
setTextZoom(textZoom, callbackContext);
}
}
return true;
} else if(action.equals("updateTextZoom")) {
updateTextZoom();
return true;
} else if (action.equals("start")) {
start(callbackContext);
return true;
@ -73,13 +88,13 @@ public class MobileAccessibility extends CordovaPlugin {
}
/**
* Called when the system is about to start resuming a previous activity.
* Called when the system is about to pause the current activity
*
* @param multitasking Flag indicating if multitasking is turned on for app
*/
@Override
public void onPause(boolean multitasking) {
Log.i("MobileAccessibility", "onPause");
//Log.i("MobileAccessibility", "onPause");
mCachedIsScreenReaderRunning = mIsScreenReaderRunning;
}
@ -90,9 +105,9 @@ public class MobileAccessibility extends CordovaPlugin {
*/
@Override
public void onResume(boolean multitasking) {
Log.i("MobileAccessibility", "onResume");
//Log.i("MobileAccessibility", "onResume");
if (mIsScreenReaderRunning && !mCachedIsScreenReaderRunning) {
Log.i("MobileAccessibility", "Reloading page on reload because the Accessibility State has changed.");
//Log.i("MobileAccessibility", "Reloading page on reload because the Accessibility State has changed.");
mCachedIsScreenReaderRunning = mIsScreenReaderRunning;
stop();
cordova.getActivity().runOnUiThread(new Runnable() {
@ -100,9 +115,7 @@ public class MobileAccessibility extends CordovaPlugin {
webView.reload();
}
});
}
}
/**
@ -198,6 +211,45 @@ public class MobileAccessibility extends CordovaPlugin {
});
}
public void getTextZoom(final CallbackContext callbackContext) {
cordova.getActivity().runOnUiThread(new Runnable() {
public void run() {
final int textZoom = mMobileAccessibilityHelper.getTextZoom();
if (callbackContext != null) {
callbackContext.success(textZoom);
}
}
});
}
public void setTextZoom(final int textZoom, final CallbackContext callbackContext) {
cordova.getActivity().runOnUiThread(new Runnable() {
public void run() {
mMobileAccessibilityHelper.setTextZoom(textZoom);
if (callbackContext != null) {
callbackContext.success(mMobileAccessibilityHelper.getTextZoom());
};
}
});
}
public void setTextZoom(final int textZoom) {
cordova.getActivity().runOnUiThread(new Runnable() {
public void run() {
mMobileAccessibilityHelper.setTextZoom(textZoom);
}
});
}
public void updateTextZoom() {
float fontScale = cordova.getActivity().getResources().getConfiguration().fontScale;
if (fontScale != mFontScale) {
mFontScale = fontScale;
}
int textZoom = Math.round(mFontScale * 100);
setTextZoom(textZoom);
}
protected void sendMobileAccessibilityStatusChangedCallback() {
if (this.mCallbackContext != null) {
PluginResult result = new PluginResult(PluginResult.Status.OK, getMobileAccessibilityStatus());
@ -213,9 +265,9 @@ public class MobileAccessibility extends CordovaPlugin {
status.put("isScreenReaderRunning", mIsScreenReaderRunning);
status.put("isClosedCaptioningEnabled", mClosedCaptioningEnabled);
status.put("isTouchExplorationEnabled", mTouchExplorationEnabled);
Log.i("MobileAccessibility", "MobileAccessibility.isScreenReaderRunning == " + status.getString("isScreenReaderRunning") +
"\nMobileAccessibility.isClosedCaptioningEnabled == " + status.getString("isClosedCaptioningEnabled") +
"\nMobileAccessibility.isTouchExplorationEnabled == " + status.getString("isTouchExplorationEnabled") );
//Log.i("MobileAccessibility", "MobileAccessibility.isScreenReaderRunning == " + status.getString("isScreenReaderRunning") +
// "\nMobileAccessibility.isClosedCaptioningEnabled == " + status.getString("isClosedCaptioningEnabled") +
// "\nMobileAccessibility.isTouchExplorationEnabled == " + status.getString("isTouchExplorationEnabled") );
} catch (JSONException e) {
e.printStackTrace();
}
@ -223,14 +275,14 @@ public class MobileAccessibility extends CordovaPlugin {
}
protected void start(CallbackContext callbackContext) {
Log.i("MobileAccessibility", "MobileAccessibility.start");
//Log.i("MobileAccessibility", "MobileAccessibility.start");
mCallbackContext = callbackContext;
mMobileAccessibilityHelper.addStateChangeListeners();
sendMobileAccessibilityStatusChangedCallback();
}
protected void stop() {
Log.i("MobileAccessibility", "MobileAccessibility.stop");
//Log.i("MobileAccessibility", "MobileAccessibility.stop");
if (mCallbackContext != null) {
sendMobileAccessibilityStatusChangedCallback();
mMobileAccessibilityHelper.removeStateChangeListeners();

View File

@ -33,6 +33,7 @@ var MobileAccessibility = function() {
this._isInvertColorsEnabled = false;
this._isMonoAudioEnabled = false;
this._isTouchExplorationEnabled = false;
this._usePreferredTextZoom = false;
// Create new event handlers on the window (returns a channel instance)
this.channels = {
screenreaderstatuschanged:cordova.addWindowEventHandler("screenreaderstatuschanged"),
@ -109,6 +110,22 @@ MobileAccessibility.prototype.activateOrDeactivateChromeVox = function(bool) {
console.error(err);
}
}
if (bool) {
if (!mobileAccessibility.hasOrientationChangeListener) {
window.addEventListener("orientationchange", mobileAccessibility.onOrientationChange);
mobileAccessibility.hasOrientationChangeListener = true;
}
} else if(mobileAccessibility.hasOrientationChangeListener) {
window.removeEventListener("orientationchange", mobileAccessibility.onOrientationChange);
mobileAccessibility.hasOrientationChangeListener = false;
}
};
MobileAccessibility.prototype.hasOrientationChangeListener = false;
MobileAccessibility.prototype.onOrientationChange = function(event) {
if (!mobileAccessibility.isChromeVoxActive()) return;
cvox.ChromeVox.navigationManager.updateIndicator();
};
MobileAccessibility.prototype.scriptInjected = false;
@ -176,6 +193,42 @@ MobileAccessibility.prototype.isTouchExplorationEnabled = function(callback) {
exec(callback, null, "MobileAccessibility", "isTouchExplorationEnabled", []);
};
MobileAccessibility.prototype.getTextZoom = function(callback) {
exec(callback, null, "MobileAccessibility", "getTextZoom", []);
};
MobileAccessibility.prototype.setTextZoom = function(textZoom, callback) {
exec(callback, null, "MobileAccessibility", "setTextZoom", [textZoom]);
};
MobileAccessibility.prototype.updateTextZoom = function() {
exec(null, null, "MobileAccessibility", "updateTextZoom", []);
};
MobileAccessibility.prototype.usePreferredTextZoom = function(bool) {
var currentValue = window.localStorage.getItem("MobileAccessibility.usePreferredTextZoom") === "true";
if (arguments.length === 0) {
return currentValue;
}
if (currentValue != bool) {
window.localStorage.setItem("MobileAccessibility.usePreferredTextZoom", bool);
}
document.removeEventListener("resume", mobileAccessibility.updateTextZoom);
if (bool) {
// console.log("We should update the text zoom at this point: " + bool)
document.addEventListener("resume", mobileAccessibility.updateTextZoom, false);
mobileAccessibility.updateTextZoom();
} else {
mobileAccessibility.setTextZoom(100);
}
return Boolean(bool);
};
MobileAccessibility.prototype.MobileAccessibilityNotifications = {
SCREEN_CHANGED : 1000,
LAYOUT_CHANGED : 1001,