Keyboard shortcuts: icons for shortcut items
Introduces the ability to display a shortcut item as
an image (if it has a resource attached). Also added
vector drawables for: up, down, left, right, enter, meta
and backspace.
Note that accessibilty wise the drawables dynamically scale
to the height of the text items (which have the text size
set in sp).
Bug: 27455410
Change-Id: I49739313d83cf661bea9378108a1fa3d6c51bd2e
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
index 2b365dc..71e97a7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
@@ -21,6 +21,9 @@
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
import android.hardware.input.InputManager;
import android.os.Handler;
import android.os.Looper;
@@ -37,6 +40,7 @@
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager.KeyboardShortcutsReceiver;
+import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
@@ -52,13 +56,15 @@
/**
* Contains functionality for handling keyboard shortcuts.
*/
-public class KeyboardShortcuts {
+public final class KeyboardShortcuts {
private static final String TAG = KeyboardShortcuts.class.getSimpleName();
-
private static final SparseArray<String> SPECIAL_CHARACTER_NAMES = new SparseArray<>();
+ private static final SparseArray<Drawable> SPECIAL_CHARACTER_DRAWABLES = new SparseArray<>();
private static final SparseArray<String> MODIFIER_NAMES = new SparseArray<>();
+ private static final SparseArray<Drawable> MODIFIER_DRAWABLES = new SparseArray<>();
+ private static boolean resourcesLoaded = false;
- private static void loadSpecialCharacterNames(Context context) {
+ private static void loadResources(Context context) {
SPECIAL_CHARACTER_NAMES.put(
KeyEvent.KEYCODE_HOME, context.getString(R.string.keyboard_key_home));
SPECIAL_CHARACTER_NAMES.put(
@@ -197,12 +203,30 @@
SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_HENKAN, "変換");
SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_KATAKANA_HIRAGANA, "かな");
+ SPECIAL_CHARACTER_DRAWABLES.put(
+ KeyEvent.KEYCODE_DEL, context.getDrawable(R.drawable.ic_ksh_key_backspace));
+ SPECIAL_CHARACTER_DRAWABLES.put(
+ KeyEvent.KEYCODE_ENTER, context.getDrawable(R.drawable.ic_ksh_key_enter));
+ SPECIAL_CHARACTER_DRAWABLES.put(
+ KeyEvent.KEYCODE_DPAD_UP, context.getDrawable(R.drawable.ic_ksh_key_up));
+ SPECIAL_CHARACTER_DRAWABLES.put(
+ KeyEvent.KEYCODE_DPAD_RIGHT, context.getDrawable(R.drawable.ic_ksh_key_right));
+ SPECIAL_CHARACTER_DRAWABLES.put(
+ KeyEvent.KEYCODE_DPAD_DOWN, context.getDrawable(R.drawable.ic_ksh_key_down));
+ SPECIAL_CHARACTER_DRAWABLES.put(
+ KeyEvent.KEYCODE_DPAD_LEFT, context.getDrawable(R.drawable.ic_ksh_key_left));
+
MODIFIER_NAMES.put(KeyEvent.META_META_ON, "Meta");
MODIFIER_NAMES.put(KeyEvent.META_CTRL_ON, "Ctrl");
MODIFIER_NAMES.put(KeyEvent.META_ALT_ON, "Alt");
MODIFIER_NAMES.put(KeyEvent.META_SHIFT_ON, "Shift");
MODIFIER_NAMES.put(KeyEvent.META_SYM_ON, "Sym");
MODIFIER_NAMES.put(KeyEvent.META_FUNCTION_ON, "Fn");
+
+ MODIFIER_DRAWABLES.put(
+ KeyEvent.META_META_ON, context.getDrawable(R.drawable.ic_ksh_key_meta));
+
+ resourcesLoaded = true;
}
private final Handler mHandler = new Handler(Looper.getMainLooper());
@@ -218,8 +242,8 @@
public KeyboardShortcuts(Context context) {
this.mContext = new ContextThemeWrapper(context, android.R.style.Theme_Material_Light);
- if (SPECIAL_CHARACTER_NAMES.size() == 0) {
- loadSpecialCharacterNames(context);
+ if (!resourcesLoaded) {
+ loadResources(context);
}
}
@@ -343,6 +367,8 @@
List<KeyboardShortcutGroup> keyboardShortcutGroups) {
LayoutInflater inflater = LayoutInflater.from(mContext);
final int keyboardShortcutGroupsSize = keyboardShortcutGroups.size();
+ // Needed to be able to scale the image items to the same height as the text items.
+ final int shortcutTextItemHeight = getShortcutTextItemHeight(inflater);
for (int i = 0; i < keyboardShortcutGroupsSize; i++) {
KeyboardShortcutGroup group = keyboardShortcutGroups.get(i);
TextView categoryTitle = (TextView) inflater.inflate(
@@ -364,7 +390,7 @@
Log.w(TAG, "Keyboard Shortcut contains key not on device, skipping.");
continue;
}
- List<String> shortcutKeys = getHumanReadableShortcutKeys(info);
+ List<StringOrDrawable> shortcutKeys = getHumanReadableShortcutKeys(info);
if (shortcutKeys == null) {
// Ignore shortcuts we can't display keys for.
Log.w(TAG, "Keyboard Shortcut contains unsupported keys, skipping.");
@@ -380,11 +406,26 @@
.findViewById(R.id.keyboard_shortcuts_item_container);
final int shortcutKeysSize = shortcutKeys.size();
for (int k = 0; k < shortcutKeysSize; k++) {
- String shortcutKey = shortcutKeys.get(k);
- TextView shortcutKeyView = (TextView) inflater.inflate(
- R.layout.keyboard_shortcuts_key_view, shortcutItemsContainer, false);
- shortcutKeyView.setText(shortcutKey);
- shortcutItemsContainer.addView(shortcutKeyView);
+ StringOrDrawable shortcutRepresentation = shortcutKeys.get(k);
+ if (shortcutRepresentation.drawable != null) {
+ ImageView shortcutKeyIconView = (ImageView) inflater.inflate(
+ R.layout.keyboard_shortcuts_key_icon_view, shortcutItemsContainer,
+ false);
+ Bitmap bitmap = Bitmap.createBitmap(shortcutTextItemHeight,
+ shortcutTextItemHeight, Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(bitmap);
+ shortcutRepresentation.drawable.setBounds(0, 0, canvas.getWidth(),
+ canvas.getHeight());
+ shortcutRepresentation.drawable.draw(canvas);
+ shortcutKeyIconView.setImageBitmap(bitmap);
+ shortcutItemsContainer.addView(shortcutKeyIconView);
+ } else if (shortcutRepresentation.string != null) {
+ TextView shortcutKeyTextView = (TextView) inflater.inflate(
+ R.layout.keyboard_shortcuts_key_view, shortcutItemsContainer,
+ false);
+ shortcutKeyTextView.setText(shortcutRepresentation.string);
+ shortcutItemsContainer.addView(shortcutKeyTextView);
+ }
}
shortcutContainer.addView(shortcutView);
}
@@ -398,14 +439,27 @@
}
}
- private List<String> getHumanReadableShortcutKeys(KeyboardShortcutInfo info) {
- List<String> shortcutKeys = getHumanReadableModifiers(info);
+ private int getShortcutTextItemHeight(LayoutInflater inflater) {
+ TextView shortcutKeyTextView = (TextView) inflater.inflate(
+ R.layout.keyboard_shortcuts_key_view, null, false);
+ shortcutKeyTextView.measure(
+ View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
+ return shortcutKeyTextView.getMeasuredHeight()
+ - shortcutKeyTextView.getPaddingTop()
+ - shortcutKeyTextView.getPaddingBottom();
+ }
+
+ private List<StringOrDrawable> getHumanReadableShortcutKeys(KeyboardShortcutInfo info) {
+ List<StringOrDrawable> shortcutKeys = getHumanReadableModifiers(info);
if (shortcutKeys == null) {
return null;
}
- String displayLabelString;
+ String displayLabelString = null;
+ Drawable displayLabelDrawable = null;
if (info.getBaseCharacter() > Character.MIN_VALUE) {
displayLabelString = String.valueOf(info.getBaseCharacter());
+ } else if (SPECIAL_CHARACTER_DRAWABLES.get(info.getKeycode()) != null) {
+ displayLabelDrawable = SPECIAL_CHARACTER_DRAWABLES.get(info.getKeycode());
} else if (SPECIAL_CHARACTER_NAMES.get(info.getKeycode()) != null) {
displayLabelString = SPECIAL_CHARACTER_NAMES.get(info.getKeycode());
} else {
@@ -422,12 +476,17 @@
return null;
}
}
- shortcutKeys.add(displayLabelString.toUpperCase());
+
+ if (displayLabelDrawable != null) {
+ shortcutKeys.add(new StringOrDrawable(displayLabelDrawable));
+ } else if (displayLabelString != null) {
+ shortcutKeys.add(new StringOrDrawable(displayLabelString.toUpperCase()));
+ }
return shortcutKeys;
}
- private List<String> getHumanReadableModifiers(KeyboardShortcutInfo info) {
- final List<String> shortcutKeys = new ArrayList<>();
+ private List<StringOrDrawable> getHumanReadableModifiers(KeyboardShortcutInfo info) {
+ final List<StringOrDrawable> shortcutKeys = new ArrayList<>();
int modifiers = info.getModifiers();
if (modifiers == 0) {
return shortcutKeys;
@@ -435,7 +494,13 @@
for(int i = 0; i < MODIFIER_NAMES.size(); ++i) {
final int supportedModifier = MODIFIER_NAMES.keyAt(i);
if ((modifiers & supportedModifier) != 0) {
- shortcutKeys.add(MODIFIER_NAMES.get(supportedModifier).toUpperCase());
+ if (MODIFIER_DRAWABLES.get(supportedModifier) != null) {
+ shortcutKeys.add(new StringOrDrawable(
+ MODIFIER_DRAWABLES.get(supportedModifier)));
+ } else {
+ shortcutKeys.add(new StringOrDrawable(
+ MODIFIER_NAMES.get(supportedModifier).toUpperCase()));
+ }
modifiers &= ~supportedModifier;
}
}
@@ -445,4 +510,17 @@
}
return shortcutKeys;
}
+
+ private static final class StringOrDrawable {
+ public String string;
+ public Drawable drawable;
+
+ public StringOrDrawable(String string) {
+ this.string = string;
+ }
+
+ public StringOrDrawable(Drawable drawable) {
+ this.drawable = drawable;
+ }
+ }
}