packages/apps/Launcher3
Revisión | 8af16760dcb367dc7568ae3736b797cd2c8406c1 (tree) |
---|---|
Tiempo | 2017-05-18 10:06:46 |
Autor | Tony Wickham <twickham@goog...> |
Commiter | Android (Google) Code Review |
Merge "Update accessibility for popup" into ub-launcher3-dorval
@@ -133,4 +133,5 @@ | ||
133 | 133 | <item type="id" name="action_move_screen_forwards" /> |
134 | 134 | <item type="id" name="action_resize" /> |
135 | 135 | <item type="id" name="action_deep_shortcuts" /> |
136 | + <item type="id" name="action_dismiss_notification" /> | |
136 | 137 | </resources> |
@@ -292,5 +292,13 @@ | ||
292 | 292 | |
293 | 293 | <!-- Accessibility description for the shortcuts menu shown for an app. --> |
294 | 294 | <string name="shortcuts_menu_description"><xliff:g id="number_of_shortcuts" example="3">%1$d</xliff:g> shortcuts for <xliff:g id="app_name" example="Messenger">%2$s</xliff:g></string> |
295 | + <!-- Accessibility description when the shortcuts menu has notifications as well as shortcuts. --> | |
296 | + <string name="shortcuts_menu_with_notifications_description"><xliff:g id="number_of_shortcuts" example="3">%1$d</xliff:g> shortcuts and <xliff:g id="number_of_notifications" example="3">%2$d</xliff:g> notifications for <xliff:g id="app_name" example="Messenger">%3$s</xliff:g></string> | |
297 | + | |
298 | + <!-- Accessibility action to dismiss a notification in the shortcuts menu for an icon. [CHAR_LIMIT=30] --> | |
299 | + <string name="action_dismiss_notification">Dismiss</string> | |
300 | + | |
301 | + <!-- Accessibility confirmation for notification being dismissed. --> | |
302 | + <string name="notification_dismissed">Notification dismissed</string> | |
295 | 303 | |
296 | 304 | </resources> |
@@ -660,14 +660,6 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver { | ||
660 | 660 | } |
661 | 661 | |
662 | 662 | /** |
663 | - * Returns true if the view can show custom shortcuts. | |
664 | - */ | |
665 | - public boolean hasDeepShortcuts() { | |
666 | - return !mLauncher.getPopupDataProvider().getShortcutIdsForItem((ItemInfo) getTag()) | |
667 | - .isEmpty(); | |
668 | - } | |
669 | - | |
670 | - /** | |
671 | 663 | * Interface to be implemented by the grand parent to allow click shadow effect. |
672 | 664 | */ |
673 | 665 | public interface BubbleTextShadowHandler { |
@@ -4061,8 +4061,8 @@ public class Launcher extends BaseActivity | ||
4061 | 4061 | shortcutInfos.add(new KeyboardShortcutInfo(getString(R.string.custom_actions), |
4062 | 4062 | KeyEvent.KEYCODE_O, KeyEvent.META_CTRL_ON)); |
4063 | 4063 | } |
4064 | - if (currentFocus instanceof BubbleTextView && | |
4065 | - ((BubbleTextView) currentFocus).hasDeepShortcuts()) { | |
4064 | + if (currentFocus.getTag() instanceof ItemInfo | |
4065 | + && DeepShortcutManager.supportsShortcuts((ItemInfo) currentFocus.getTag())) { | |
4066 | 4066 | shortcutInfos.add(new KeyboardShortcutInfo(getString(R.string.action_deep_shortcut), |
4067 | 4067 | KeyEvent.KEYCODE_S, KeyEvent.META_CTRL_ON)); |
4068 | 4068 | } |
@@ -37,6 +37,7 @@ import com.android.launcher3.Workspace; | ||
37 | 37 | import com.android.launcher3.dragndrop.DragController.DragListener; |
38 | 38 | import com.android.launcher3.dragndrop.DragOptions; |
39 | 39 | import com.android.launcher3.folder.Folder; |
40 | +import com.android.launcher3.shortcuts.DeepShortcutManager; | |
40 | 41 | import com.android.launcher3.util.Thunk; |
41 | 42 | |
42 | 43 | import java.util.ArrayList; |
@@ -104,8 +105,7 @@ public class LauncherAccessibilityDelegate extends AccessibilityDelegate impleme | ||
104 | 105 | |
105 | 106 | // If the request came from keyboard, do not add custom shortcuts as that is already |
106 | 107 | // exposed as a direct shortcut |
107 | - if (!fromKeyboard && host instanceof BubbleTextView | |
108 | - && ((BubbleTextView) host).hasDeepShortcuts()) { | |
108 | + if (!fromKeyboard && DeepShortcutManager.supportsShortcuts(item)) { | |
109 | 109 | info.addAction(mActions.get(DEEP_SHORTCUTS)); |
110 | 110 | } |
111 | 111 |
@@ -18,14 +18,15 @@ package com.android.launcher3.accessibility; | ||
18 | 18 | |
19 | 19 | import android.view.View; |
20 | 20 | import android.view.accessibility.AccessibilityNodeInfo; |
21 | +import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; | |
21 | 22 | |
22 | 23 | import com.android.launcher3.AbstractFloatingView; |
23 | 24 | import com.android.launcher3.ItemInfo; |
24 | 25 | import com.android.launcher3.Launcher; |
25 | -import com.android.launcher3.LauncherModel; | |
26 | 26 | import com.android.launcher3.LauncherSettings; |
27 | 27 | import com.android.launcher3.R; |
28 | 28 | import com.android.launcher3.ShortcutInfo; |
29 | +import com.android.launcher3.notification.NotificationMainView; | |
29 | 30 | import com.android.launcher3.shortcuts.DeepShortcutView; |
30 | 31 | |
31 | 32 | import java.util.ArrayList; |
@@ -36,14 +37,23 @@ import java.util.ArrayList; | ||
36 | 37 | */ |
37 | 38 | public class ShortcutMenuAccessibilityDelegate extends LauncherAccessibilityDelegate { |
38 | 39 | |
40 | + private static final int DISMISS_NOTIFICATION = R.id.action_dismiss_notification; | |
41 | + | |
39 | 42 | public ShortcutMenuAccessibilityDelegate(Launcher launcher) { |
40 | 43 | super(launcher); |
44 | + mActions.put(DISMISS_NOTIFICATION, new AccessibilityAction(DISMISS_NOTIFICATION, | |
45 | + launcher.getText(R.string.action_dismiss_notification))); | |
41 | 46 | } |
42 | 47 | |
43 | 48 | @Override |
44 | 49 | public void addSupportedActions(View host, AccessibilityNodeInfo info, boolean fromKeyboard) { |
45 | 50 | if ((host.getParent() instanceof DeepShortcutView)) { |
46 | 51 | info.addAction(mActions.get(ADD_TO_WORKSPACE)); |
52 | + } else if (host instanceof NotificationMainView) { | |
53 | + NotificationMainView notificationView = (NotificationMainView) host; | |
54 | + if (notificationView.canChildBeDismissed(notificationView)) { | |
55 | + info.addAction(mActions.get(DISMISS_NOTIFICATION)); | |
56 | + } | |
47 | 57 | } |
48 | 58 | } |
49 | 59 |
@@ -74,6 +84,14 @@ public class ShortcutMenuAccessibilityDelegate extends LauncherAccessibilityDele | ||
74 | 84 | onComplete.run(); |
75 | 85 | } |
76 | 86 | return true; |
87 | + } else if (action == DISMISS_NOTIFICATION) { | |
88 | + if (!(host instanceof NotificationMainView)) { | |
89 | + return false; | |
90 | + } | |
91 | + NotificationMainView notificationView = (NotificationMainView) host; | |
92 | + notificationView.onChildDismissed(notificationView); | |
93 | + announceConfirmation(R.string.notification_dismissed); | |
94 | + return true; | |
77 | 95 | } |
78 | 96 | return false; |
79 | 97 | } |
@@ -141,6 +141,7 @@ public class NotificationFooterLayout extends FrameLayout { | ||
141 | 141 | icon.setBackground(info.getIconForBackground(getContext(), mBackgroundColor)); |
142 | 142 | icon.setOnClickListener(info); |
143 | 143 | icon.setTag(info); |
144 | + icon.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO); | |
144 | 145 | mIconRow.addView(icon, 0, mIconLayoutParams); |
145 | 146 | return icon; |
146 | 147 | } |
@@ -77,6 +77,10 @@ public class NotificationItemView extends PopupItemView implements LogContainerP | ||
77 | 77 | mSwipeHelper.setDisableHardwareLayers(true); |
78 | 78 | } |
79 | 79 | |
80 | + public NotificationMainView getMainView() { | |
81 | + return mMainView; | |
82 | + } | |
83 | + | |
80 | 84 | public int getHeightMinusFooter() { |
81 | 85 | int footerHeight = mFooter.getParent() == null ? 0 : mFooter.getHeight(); |
82 | 86 | return getHeight() - footerHeight; |
@@ -122,7 +122,7 @@ public class NotificationMainView extends FrameLayout implements SwipeHelper.Cal | ||
122 | 122 | |
123 | 123 | @Override |
124 | 124 | public boolean canChildBeDismissed(View v) { |
125 | - return mNotificationInfo.dismissable; | |
125 | + return mNotificationInfo != null && mNotificationInfo.dismissable; | |
126 | 126 | } |
127 | 127 | |
128 | 128 | @Override |
@@ -114,7 +114,6 @@ public class PopupContainerWithArrow extends AbstractFloatingView implements Dra | ||
114 | 114 | |
115 | 115 | mStartDragThreshold = getResources().getDimensionPixelSize( |
116 | 116 | R.dimen.deep_shortcuts_start_drag_threshold); |
117 | - // TODO: make sure the delegate works for all items, not just shortcuts. | |
118 | 117 | mAccessibilityDelegate = new ShortcutMenuAccessibilityDelegate(mLauncher); |
119 | 118 | mIsRtl = Utilities.isRtl(getResources()); |
120 | 119 | } |
@@ -176,7 +175,7 @@ public class PopupContainerWithArrow extends AbstractFloatingView implements Dra | ||
176 | 175 | // Add dummy views first, and populate with real info when ready. |
177 | 176 | PopupPopulator.Item[] itemsToPopulate = PopupPopulator |
178 | 177 | .getItemsToPopulate(shortcutIds, notificationKeys, systemShortcuts); |
179 | - addDummyViews(originalIcon, itemsToPopulate, notificationKeys.size() > 1); | |
178 | + addDummyViews(itemsToPopulate, notificationKeys.size() > 1); | |
180 | 179 | |
181 | 180 | measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED); |
182 | 181 | orientAboutIcon(originalIcon, arrowHeight + arrowVerticalOffset); |
@@ -187,7 +186,7 @@ public class PopupContainerWithArrow extends AbstractFloatingView implements Dra | ||
187 | 186 | mNotificationItemView = null; |
188 | 187 | mShortcutsItemView = null; |
189 | 188 | itemsToPopulate = PopupPopulator.reverseItems(itemsToPopulate); |
190 | - addDummyViews(originalIcon, itemsToPopulate, notificationKeys.size() > 1); | |
189 | + addDummyViews(itemsToPopulate, notificationKeys.size() > 1); | |
191 | 190 | |
192 | 191 | measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED); |
193 | 192 | orientAboutIcon(originalIcon, arrowHeight + arrowVerticalOffset); |
@@ -204,6 +203,17 @@ public class PopupContainerWithArrow extends AbstractFloatingView implements Dra | ||
204 | 203 | updateNotificationHeader(); |
205 | 204 | } |
206 | 205 | |
206 | + int numShortcuts = shortcutViews.size() + systemShortcutViews.size(); | |
207 | + int numNotifications = notificationKeys.size(); | |
208 | + if (numNotifications == 0) { | |
209 | + setContentDescription(getContext().getString(R.string.shortcuts_menu_description, | |
210 | + numShortcuts, originalIcon.getContentDescription().toString())); | |
211 | + } else { | |
212 | + setContentDescription(getContext().getString( | |
213 | + R.string.shortcuts_menu_with_notifications_description, numShortcuts, | |
214 | + numNotifications, originalIcon.getContentDescription().toString())); | |
215 | + } | |
216 | + | |
207 | 217 | // Add the arrow. |
208 | 218 | final int arrowHorizontalOffset = resources.getDimensionPixelSize(isAlignedWithStart() ? |
209 | 219 | R.dimen.popup_arrow_horizontal_offset_start : |
@@ -225,8 +235,8 @@ public class PopupContainerWithArrow extends AbstractFloatingView implements Dra | ||
225 | 235 | systemShortcuts, systemShortcutViews)); |
226 | 236 | } |
227 | 237 | |
228 | - private void addDummyViews(BubbleTextView originalIcon, | |
229 | - PopupPopulator.Item[] itemTypesToPopulate, boolean notificationFooterHasIcons) { | |
238 | + private void addDummyViews(PopupPopulator.Item[] itemTypesToPopulate, | |
239 | + boolean notificationFooterHasIcons) { | |
230 | 240 | final Resources res = getResources(); |
231 | 241 | final int spacing = res.getDimensionPixelSize(R.dimen.popup_items_spacing); |
232 | 242 | final LayoutInflater inflater = mLauncher.getLayoutInflater(); |
@@ -243,12 +253,14 @@ public class PopupContainerWithArrow extends AbstractFloatingView implements Dra | ||
243 | 253 | int footerHeight = notificationFooterHasIcons ? |
244 | 254 | res.getDimensionPixelSize(R.dimen.notification_footer_height) : 0; |
245 | 255 | item.findViewById(R.id.footer).getLayoutParams().height = footerHeight; |
256 | + mNotificationItemView.getMainView().setAccessibilityDelegate(mAccessibilityDelegate); | |
257 | + } else if (itemTypeToPopulate == PopupPopulator.Item.SHORTCUT) { | |
258 | + item.setAccessibilityDelegate(mAccessibilityDelegate); | |
246 | 259 | } |
247 | 260 | |
248 | 261 | boolean shouldAddBottomMargin = nextItemTypeToPopulate != null |
249 | 262 | && itemTypeToPopulate.isShortcut ^ nextItemTypeToPopulate.isShortcut; |
250 | 263 | |
251 | - item.setAccessibilityDelegate(mAccessibilityDelegate); | |
252 | 264 | if (itemTypeToPopulate.isShortcut) { |
253 | 265 | if (mShortcutsItemView == null) { |
254 | 266 | mShortcutsItemView = (ShortcutsItemView) inflater.inflate( |
@@ -266,9 +278,6 @@ public class PopupContainerWithArrow extends AbstractFloatingView implements Dra | ||
266 | 278 | } |
267 | 279 | } |
268 | 280 | } |
269 | - // TODO: update this, since not all items are shortcuts | |
270 | - setContentDescription(getContext().getString(R.string.shortcuts_menu_description, | |
271 | - numItems, originalIcon.getContentDescription().toString())); | |
272 | 281 | } |
273 | 282 | |
274 | 283 | protected PopupItemView getItemViewAt(int index) { |