Accessibility fixes
1) Use a different content description for temporary new page 2) Use different accessibility description for add widget toast 3) Announce when an item is deleted 4) Announce when hovering over a drop target 5) Announce state during drag-n-drop and widget resize (similar to seekbar) Bug: 23573321, 24057944 Change-Id: Icabb317625e70c78e11c0b4f99b9339172d93594
This commit is contained in:
parent
2949fb5b16
commit
e78e3d734b
|
@ -50,6 +50,8 @@
|
|||
<!-- Widgets -->
|
||||
<!-- Message to tell the user to press and hold on a widget to add it [CHAR_LIMIT=50] -->
|
||||
<string name="long_press_widget_to_add">Touch & hold to pick up a widget.</string>
|
||||
<!-- Accessibility spoken hint message in widget picker, which allows user to add a widget. Custom action is the label for additional accessibility actions available in this mode [CHAR_LIMIT=100] -->
|
||||
<string name="long_accessible_way_to_add">Double-tap & hold to pick up a widget or use custom actions.</string>
|
||||
<!-- The format string for the dimensions of a widget in the drawer -->
|
||||
<!-- There is a special version of this format string for Farsi -->
|
||||
<string name="widget_dims_format">%1$d \u00d7 %2$d</string>
|
||||
|
@ -125,6 +127,8 @@
|
|||
<string name="default_scroll_format">Page %1$d of %2$d</string>
|
||||
<!-- The format string for Workspace page scroll text [CHAR_LIMIT=none] -->
|
||||
<string name="workspace_scroll_format">Home screen %1$d of %2$d</string>
|
||||
<!-- Description for a new page on homescreen[CHAR_LIMIT=none] -->
|
||||
<string name="workspace_new_page">New home screen page</string>
|
||||
|
||||
<!-- Clings -->
|
||||
<!-- The title text for the workspace cling [CHAR_LIMIT=30] -->
|
||||
|
|
|
@ -14,6 +14,8 @@ import android.view.Gravity;
|
|||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.android.launcher3.accessibility.DragViewStateAnnouncer;
|
||||
|
||||
public class AppWidgetResizeFrame extends FrameLayout {
|
||||
private static final int SNAP_DURATION = 150;
|
||||
private static final float DIMMED_HANDLE_ALPHA = 0f;
|
||||
|
@ -40,6 +42,8 @@ public class AppWidgetResizeFrame extends FrameLayout {
|
|||
private final int[] mLastDirectionVector = new int[2];
|
||||
private final int[] mTmpPt = new int[2];
|
||||
|
||||
private final DragViewStateAnnouncer mStateAnnouncer;
|
||||
|
||||
private boolean mLeftBorderActive;
|
||||
private boolean mRightBorderActive;
|
||||
private boolean mTopBorderActive;
|
||||
|
@ -78,6 +82,8 @@ public class AppWidgetResizeFrame extends FrameLayout {
|
|||
mMinHSpan = info.minSpanX;
|
||||
mMinVSpan = info.minSpanY;
|
||||
|
||||
mStateAnnouncer = DragViewStateAnnouncer.createFor(this);
|
||||
|
||||
setBackgroundResource(R.drawable.widget_resize_shadow);
|
||||
setForeground(getResources().getDrawable(R.drawable.widget_resize_frame));
|
||||
setPadding(0, 0, 0, 0);
|
||||
|
@ -320,12 +326,18 @@ public class AppWidgetResizeFrame extends FrameLayout {
|
|||
|
||||
if (mCellLayout.createAreaForResize(cellX, cellY, spanX, spanY, mWidgetView,
|
||||
mDirectionVector, onDismiss)) {
|
||||
if (mStateAnnouncer != null && (lp.cellHSpan != spanX || lp.cellVSpan != spanY) ) {
|
||||
mStateAnnouncer.announce(
|
||||
mLauncher.getString(R.string.widget_resized, spanX, spanY));
|
||||
}
|
||||
|
||||
lp.tmpCellX = cellX;
|
||||
lp.tmpCellY = cellY;
|
||||
lp.cellHSpan = spanX;
|
||||
lp.cellVSpan = spanY;
|
||||
mRunningVInc += vSpanDelta;
|
||||
mRunningHInc += hSpanDelta;
|
||||
|
||||
if (!onDismiss) {
|
||||
updateWidgetSizeRanges(mWidgetView, mLauncher, spanX, spanY);
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ import android.util.AttributeSet;
|
|||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.view.animation.DecelerateInterpolator;
|
||||
import android.view.animation.LinearInterpolator;
|
||||
import android.widget.TextView;
|
||||
|
@ -123,6 +124,7 @@ public abstract class ButtonDropTarget extends TextView
|
|||
mDrawable.setColorFilter(new ColorMatrixColorFilter(mCurrentFilter));
|
||||
setTextColor(mHoverColor);
|
||||
}
|
||||
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1021,7 +1021,7 @@ public class CellLayout extends ViewGroup implements BubbleTextShadowHandler {
|
|||
}
|
||||
|
||||
void visualizeDropLocation(View v, Bitmap dragOutline, int originX, int originY, int cellX,
|
||||
int cellY, int spanX, int spanY, boolean resize, Point dragOffset, Rect dragRegion) {
|
||||
int cellY, int spanX, int spanY, boolean resize, DropTarget.DragObject dragObject) {
|
||||
final int oldDragCellX = mDragCell[0];
|
||||
final int oldDragCellY = mDragCell[1];
|
||||
|
||||
|
@ -1030,6 +1030,9 @@ public class CellLayout extends ViewGroup implements BubbleTextShadowHandler {
|
|||
}
|
||||
|
||||
if (cellX != oldDragCellX || cellY != oldDragCellY) {
|
||||
Point dragOffset = dragObject.dragView.getDragVisualizeOffset();
|
||||
Rect dragRegion = dragObject.dragView.getDragRegion();
|
||||
|
||||
mDragCell[0] = cellX;
|
||||
mDragCell[1] = cellY;
|
||||
// Find the top left corner of the rect the object will occupy
|
||||
|
@ -1081,6 +1084,18 @@ public class CellLayout extends ViewGroup implements BubbleTextShadowHandler {
|
|||
|
||||
mDragOutlineAnims[mDragOutlineCurrent].setTag(dragOutline);
|
||||
mDragOutlineAnims[mDragOutlineCurrent].animateIn();
|
||||
|
||||
if (dragObject.stateAnnouncer != null) {
|
||||
String msg;
|
||||
if (isHotseat()) {
|
||||
msg = getContext().getString(R.string.move_to_hotseat_position,
|
||||
Math.max(cellX, cellY) + 1);
|
||||
} else {
|
||||
msg = getContext().getString(R.string.move_to_empty_cell,
|
||||
cellY + 1, cellX + 1);
|
||||
}
|
||||
dragObject.stateAnnouncer.announce(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@ package com.android.launcher3;
|
|||
import android.animation.TimeInterpolator;
|
||||
import android.content.Context;
|
||||
import android.graphics.PointF;
|
||||
import android.os.AsyncTask;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.animation.AnimationUtils;
|
||||
|
@ -67,15 +66,14 @@ public class DeleteDropTarget extends ButtonDropTarget {
|
|||
|
||||
/**
|
||||
* Removes the item from the workspace. If the view is not null, it also removes the view.
|
||||
* @return true if the item was removed.
|
||||
*/
|
||||
public static boolean removeWorkspaceOrFolderItem(Launcher launcher, ItemInfo item, View view) {
|
||||
public static void removeWorkspaceOrFolderItem(Launcher launcher, ItemInfo item, View view) {
|
||||
// Remove the item from launcher and the db, we can ignore the containerInfo in this call
|
||||
// because we already remove the drag view from the folder (if the drag originated from
|
||||
// a folder) in Folder.beginDrag()
|
||||
launcher.removeItem(view, item, true /* deleteFromDb */);
|
||||
launcher.getWorkspace().stripEmptyScreens();
|
||||
return true;
|
||||
launcher.getDragLayer().announceForAccessibility(launcher.getString(R.string.item_removed));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -32,8 +32,10 @@ import android.view.MotionEvent;
|
|||
import android.view.VelocityTracker;
|
||||
import android.view.View;
|
||||
import android.view.ViewConfiguration;
|
||||
import android.view.accessibility.AccessibilityManager;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
|
||||
import com.android.launcher3.accessibility.DragViewStateAnnouncer;
|
||||
import com.android.launcher3.util.Thunk;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -145,8 +147,6 @@ public class DragController {
|
|||
|
||||
/**
|
||||
* Used to create a new DragLayer from XML.
|
||||
*
|
||||
* @param context The application's context.
|
||||
*/
|
||||
public DragController(Launcher launcher) {
|
||||
Resources r = launcher.getResources();
|
||||
|
@ -239,6 +239,9 @@ public class DragController {
|
|||
|
||||
mDragObject = new DropTarget.DragObject();
|
||||
|
||||
final DragView dragView = mDragObject.dragView = new DragView(mLauncher, b, registrationX,
|
||||
registrationY, 0, 0, b.getWidth(), b.getHeight(), initialDragViewScale);
|
||||
|
||||
mDragObject.dragComplete = false;
|
||||
if (mIsAccessibleDrag) {
|
||||
// For an accessible drag, we assume the view is being dragged from the center.
|
||||
|
@ -248,14 +251,12 @@ public class DragController {
|
|||
} else {
|
||||
mDragObject.xOffset = mMotionDownX - (dragLayerX + dragRegionLeft);
|
||||
mDragObject.yOffset = mMotionDownY - (dragLayerY + dragRegionTop);
|
||||
mDragObject.stateAnnouncer = DragViewStateAnnouncer.createFor(dragView);
|
||||
}
|
||||
|
||||
mDragObject.dragSource = source;
|
||||
mDragObject.dragInfo = dragInfo;
|
||||
|
||||
final DragView dragView = mDragObject.dragView = new DragView(mLauncher, b, registrationX,
|
||||
registrationY, 0, 0, b.getWidth(), b.getHeight(), initialDragViewScale);
|
||||
|
||||
if (dragOffset != null) {
|
||||
dragView.setDragVisualizeOffset(new Point(dragOffset));
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@ package com.android.launcher3;
|
|||
import android.graphics.PointF;
|
||||
import android.graphics.Rect;
|
||||
|
||||
import com.android.launcher3.accessibility.DragViewStateAnnouncer;
|
||||
|
||||
/**
|
||||
* Interface defining an object that can receive a drag.
|
||||
*
|
||||
|
@ -64,6 +66,8 @@ public interface DropTarget {
|
|||
/** Defers removing the DragView from the DragLayer until after the drop animation. */
|
||||
public boolean deferDragViewCleanupPostAnimation = true;
|
||||
|
||||
public DragViewStateAnnouncer stateAnnouncer;
|
||||
|
||||
public DragObject() {
|
||||
}
|
||||
|
||||
|
|
|
@ -706,6 +706,11 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
|
|||
mReorderAlarm.setOnAlarmListener(mReorderAlarmListener);
|
||||
mReorderAlarm.setAlarm(REORDER_DELAY);
|
||||
mPrevTargetRank = mTargetRank;
|
||||
|
||||
if (d.stateAnnouncer != null) {
|
||||
d.stateAnnouncer.announce(getContext().getString(R.string.move_to_position,
|
||||
mTargetRank + 1));
|
||||
}
|
||||
}
|
||||
|
||||
float x = r[0];
|
||||
|
|
|
@ -47,7 +47,10 @@ import android.graphics.drawable.PaintDrawable;
|
|||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Process;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableString;
|
||||
import android.text.TextUtils;
|
||||
import android.text.style.TtsSpan;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
|
@ -726,4 +729,22 @@ public final class Utilities {
|
|||
public static String createDbSelectionQuery(String columnName, Iterable<?> values) {
|
||||
return String.format(Locale.ENGLISH, "%s IN (%s)", columnName, TextUtils.join(", ", values));
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps a message with a TTS span, so that a different message is spoken than
|
||||
* what is getting displayed.
|
||||
* @param msg original message
|
||||
* @param ttsMsg message to be spoken
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
public static CharSequence wrapForTts(CharSequence msg, String ttsMsg) {
|
||||
if (Utilities.ATLEAST_LOLLIPOP) {
|
||||
SpannableString spanned = new SpannableString(msg);
|
||||
spanned.setSpan(new TtsSpan.TextBuilder(ttsMsg).build(),
|
||||
0, spanned.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
|
||||
return spanned;
|
||||
} else {
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,6 +67,7 @@ import com.android.launcher3.UninstallDropTarget.UninstallSource;
|
|||
import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
|
||||
import com.android.launcher3.accessibility.LauncherAccessibilityDelegate.AccessibilityDragSource;
|
||||
import com.android.launcher3.accessibility.OverviewScreenAccessibilityDelegate;
|
||||
import com.android.launcher3.accessibility.WorkspaceAccessibilityHelper;
|
||||
import com.android.launcher3.compat.UserHandleCompat;
|
||||
import com.android.launcher3.util.LongArrayMap;
|
||||
import com.android.launcher3.util.Thunk;
|
||||
|
@ -2024,7 +2025,7 @@ public class Workspace extends PagedView
|
|||
}
|
||||
setImportantForAccessibility((mState == State.NORMAL || mState == State.OVERVIEW)
|
||||
? IMPORTANT_FOR_ACCESSIBILITY_AUTO
|
||||
: IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
|
||||
: IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
|
||||
} else {
|
||||
int accessible = mState == State.NORMAL ?
|
||||
IMPORTANT_FOR_ACCESSIBILITY_AUTO :
|
||||
|
@ -2473,11 +2474,14 @@ public class Workspace extends PagedView
|
|||
return true;
|
||||
}
|
||||
|
||||
boolean willCreateUserFolder(ItemInfo info, CellLayout target, int[] targetCell, float
|
||||
distance, boolean considerTimeout) {
|
||||
boolean willCreateUserFolder(ItemInfo info, CellLayout target, int[] targetCell,
|
||||
float distance, boolean considerTimeout) {
|
||||
if (distance > mMaxDistanceForFolderCreation) return false;
|
||||
View dropOverView = target.getChildAt(targetCell[0], targetCell[1]);
|
||||
return willCreateUserFolder(info, dropOverView, considerTimeout);
|
||||
}
|
||||
|
||||
boolean willCreateUserFolder(ItemInfo info, View dropOverView, boolean considerTimeout) {
|
||||
if (dropOverView != null) {
|
||||
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) dropOverView.getLayoutParams();
|
||||
if (lp.useTmpCoords && (lp.tmpCellX != lp.cellX || lp.tmpCellY != lp.tmpCellY)) {
|
||||
|
@ -2497,7 +2501,7 @@ public class Workspace extends PagedView
|
|||
boolean aboveShortcut = (dropOverView.getTag() instanceof ShortcutInfo);
|
||||
boolean willBecomeShortcut =
|
||||
(info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
|
||||
info.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT);
|
||||
info.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT);
|
||||
|
||||
return (aboveShortcut && willBecomeShortcut);
|
||||
}
|
||||
|
@ -2506,7 +2510,10 @@ public class Workspace extends PagedView
|
|||
float distance) {
|
||||
if (distance > mMaxDistanceForFolderCreation) return false;
|
||||
View dropOverView = target.getChildAt(targetCell[0], targetCell[1]);
|
||||
return willAddToExistingUserFolder(dragInfo, dropOverView);
|
||||
|
||||
}
|
||||
boolean willAddToExistingUserFolder(Object dragInfo, View dropOverView) {
|
||||
if (dropOverView != null) {
|
||||
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) dropOverView.getLayoutParams();
|
||||
if (lp.useTmpCoords && (lp.tmpCellX != lp.cellX || lp.tmpCellY != lp.tmpCellY)) {
|
||||
|
@ -3209,8 +3216,6 @@ public class Workspace extends PagedView
|
|||
mapPointFromSelfToChild(mDragTargetLayout, mDragViewVisualCenter, null);
|
||||
}
|
||||
|
||||
ItemInfo info = (ItemInfo) d.dragInfo;
|
||||
|
||||
int minSpanX = item.spanX;
|
||||
int minSpanY = item.spanY;
|
||||
if (item.minSpanX > 0 && item.minSpanY > 0) {
|
||||
|
@ -3229,11 +3234,7 @@ public class Workspace extends PagedView
|
|||
float targetCellDistance = mDragTargetLayout.getDistanceFromCell(
|
||||
mDragViewVisualCenter[0], mDragViewVisualCenter[1], mTargetCell);
|
||||
|
||||
final View dragOverView = mDragTargetLayout.getChildAt(mTargetCell[0],
|
||||
mTargetCell[1]);
|
||||
|
||||
manageFolderFeedback(info, mDragTargetLayout, mTargetCell,
|
||||
targetCellDistance, dragOverView, d.accessibleDrag);
|
||||
manageFolderFeedback(mDragTargetLayout, mTargetCell, targetCellDistance, d);
|
||||
|
||||
boolean nearestDropOccupied = mDragTargetLayout.isNearestDropLocationOccupied((int)
|
||||
mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1], item.spanX,
|
||||
|
@ -3242,8 +3243,7 @@ public class Workspace extends PagedView
|
|||
if (!nearestDropOccupied) {
|
||||
mDragTargetLayout.visualizeDropLocation(child, mDragOutline,
|
||||
(int) mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1],
|
||||
mTargetCell[0], mTargetCell[1], item.spanX, item.spanY, false,
|
||||
d.dragView.getDragVisualizeOffset(), d.dragView.getDragRegion());
|
||||
mTargetCell[0], mTargetCell[1], item.spanX, item.spanY, false, d);
|
||||
} else if ((mDragMode == DRAG_MODE_NONE || mDragMode == DRAG_MODE_REORDER)
|
||||
&& !mReorderAlarm.alarmPending() && (mLastReorderX != reorderX ||
|
||||
mLastReorderY != reorderY)) {
|
||||
|
@ -3256,7 +3256,7 @@ public class Workspace extends PagedView
|
|||
// Otherwise, if we aren't adding to or creating a folder and there's no pending
|
||||
// reorder, then we schedule a reorder
|
||||
ReorderAlarmListener listener = new ReorderAlarmListener(mDragViewVisualCenter,
|
||||
minSpanX, minSpanY, item.spanX, item.spanY, d.dragView, child);
|
||||
minSpanX, minSpanY, item.spanX, item.spanY, d, child);
|
||||
mReorderAlarm.setOnAlarmListener(listener);
|
||||
mReorderAlarm.setAlarm(REORDER_TIMEOUT);
|
||||
}
|
||||
|
@ -3270,28 +3270,34 @@ public class Workspace extends PagedView
|
|||
}
|
||||
}
|
||||
|
||||
private void manageFolderFeedback(ItemInfo info, CellLayout targetLayout,
|
||||
int[] targetCell, float distance, View dragOverView, boolean accessibleDrag) {
|
||||
boolean userFolderPending = willCreateUserFolder(info, targetLayout, targetCell, distance,
|
||||
false);
|
||||
private void manageFolderFeedback(CellLayout targetLayout,
|
||||
int[] targetCell, float distance, DragObject dragObject) {
|
||||
if (distance > mMaxDistanceForFolderCreation) return;
|
||||
|
||||
final View dragOverView = mDragTargetLayout.getChildAt(mTargetCell[0], mTargetCell[1]);
|
||||
ItemInfo info = (ItemInfo) dragObject.dragInfo;
|
||||
boolean userFolderPending = willCreateUserFolder(info, dragOverView, false);
|
||||
if (mDragMode == DRAG_MODE_NONE && userFolderPending &&
|
||||
!mFolderCreationAlarm.alarmPending()) {
|
||||
|
||||
FolderCreationAlarmListener listener = new
|
||||
FolderCreationAlarmListener(targetLayout, targetCell[0], targetCell[1]);
|
||||
|
||||
if (!accessibleDrag) {
|
||||
if (!dragObject.accessibleDrag) {
|
||||
mFolderCreationAlarm.setOnAlarmListener(listener);
|
||||
mFolderCreationAlarm.setAlarm(FOLDER_CREATION_TIMEOUT);
|
||||
} else {
|
||||
listener.onAlarm(mFolderCreationAlarm);
|
||||
}
|
||||
|
||||
if (dragObject.stateAnnouncer != null) {
|
||||
dragObject.stateAnnouncer.announce(WorkspaceAccessibilityHelper
|
||||
.getDescriptionForDropOver(dragOverView, getContext()));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
boolean willAddToFolder =
|
||||
willAddToExistingUserFolder(info, targetLayout, targetCell, distance);
|
||||
|
||||
boolean willAddToFolder = willAddToExistingUserFolder(info, dragOverView);
|
||||
if (willAddToFolder && mDragMode == DRAG_MODE_NONE) {
|
||||
mDragOverFolderIcon = ((FolderIcon) dragOverView);
|
||||
mDragOverFolderIcon.onDragEnter(info);
|
||||
|
@ -3299,6 +3305,11 @@ public class Workspace extends PagedView
|
|||
targetLayout.clearDragOutlines();
|
||||
}
|
||||
setDragMode(DRAG_MODE_ADD_TO_FOLDER);
|
||||
|
||||
if (dragObject.stateAnnouncer != null) {
|
||||
dragObject.stateAnnouncer.announce(WorkspaceAccessibilityHelper
|
||||
.getDescriptionForDropOver(dragOverView, getContext()));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -3308,8 +3319,6 @@ public class Workspace extends PagedView
|
|||
if (mDragMode == DRAG_MODE_CREATE_FOLDER && !userFolderPending) {
|
||||
setDragMode(DRAG_MODE_NONE);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
class FolderCreationAlarmListener implements OnAlarmListener {
|
||||
|
@ -3341,18 +3350,18 @@ public class Workspace extends PagedView
|
|||
class ReorderAlarmListener implements OnAlarmListener {
|
||||
float[] dragViewCenter;
|
||||
int minSpanX, minSpanY, spanX, spanY;
|
||||
DragView dragView;
|
||||
DragObject dragObject;
|
||||
View child;
|
||||
|
||||
public ReorderAlarmListener(float[] dragViewCenter, int minSpanX, int minSpanY, int spanX,
|
||||
int spanY, DragView dragView, View child) {
|
||||
int spanY, DragObject dragObject, View child) {
|
||||
this.dragViewCenter = dragViewCenter;
|
||||
this.minSpanX = minSpanX;
|
||||
this.minSpanY = minSpanY;
|
||||
this.spanX = spanX;
|
||||
this.spanY = spanY;
|
||||
this.child = child;
|
||||
this.dragView = dragView;
|
||||
this.dragObject = dragObject;
|
||||
}
|
||||
|
||||
public void onAlarm(Alarm alarm) {
|
||||
|
@ -3376,8 +3385,7 @@ public class Workspace extends PagedView
|
|||
boolean resize = resultSpan[0] != spanX || resultSpan[1] != spanY;
|
||||
mDragTargetLayout.visualizeDropLocation(child, mDragOutline,
|
||||
(int) mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1],
|
||||
mTargetCell[0], mTargetCell[1], resultSpan[0], resultSpan[1], resize,
|
||||
dragView.getDragVisualizeOffset(), dragView.getDragRegion());
|
||||
mTargetCell[0], mTargetCell[1], resultSpan[0], resultSpan[1], resize, dragObject);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4472,8 +4480,17 @@ public class Workspace extends PagedView
|
|||
|
||||
private String getPageDescription(int page) {
|
||||
int delta = numCustomPages();
|
||||
int nScreens = getChildCount() - delta;
|
||||
int extraScreenId = mScreenOrder.indexOf(EXTRA_EMPTY_SCREEN_ID);
|
||||
if (extraScreenId >= 0 && nScreens > 1) {
|
||||
if (page == extraScreenId) {
|
||||
return getContext().getString(R.string.workspace_new_page);
|
||||
}
|
||||
nScreens--;
|
||||
}
|
||||
return String.format(getContext().getString(R.string.workspace_scroll_format),
|
||||
page + 1 - delta, getChildCount() - delta);
|
||||
page + 1 - delta, nScreens);
|
||||
|
||||
}
|
||||
|
||||
public void getLocationInDragLayer(int[] loc) {
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.launcher3.accessibility;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.view.accessibility.AccessibilityManager;
|
||||
|
||||
/**
|
||||
* Periodically sends accessibility events to announce ongoing state changed. Based on the
|
||||
* implementation in ProgressBar.
|
||||
*/
|
||||
public class DragViewStateAnnouncer implements Runnable {
|
||||
|
||||
private static final int TIMEOUT_SEND_ACCESSIBILITY_EVENT = 200;
|
||||
|
||||
private final View mTargetView;
|
||||
|
||||
private DragViewStateAnnouncer(View view) {
|
||||
mTargetView = view;
|
||||
}
|
||||
|
||||
public void announce(CharSequence msg) {
|
||||
mTargetView.setContentDescription(msg);
|
||||
mTargetView.removeCallbacks(this);
|
||||
mTargetView.postDelayed(this, TIMEOUT_SEND_ACCESSIBILITY_EVENT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
mTargetView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
|
||||
}
|
||||
|
||||
public static DragViewStateAnnouncer createFor(View v) {
|
||||
if (((AccessibilityManager) v.getContext().getSystemService(Context.ACCESSIBILITY_SERVICE))
|
||||
.isEnabled()) {
|
||||
return new DragViewStateAnnouncer(v);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -134,11 +134,8 @@ public class LauncherAccessibilityDelegate extends AccessibilityDelegate impleme
|
|||
|
||||
public boolean performAction(final View host, final ItemInfo item, int action) {
|
||||
if (action == REMOVE) {
|
||||
if (DeleteDropTarget.removeWorkspaceOrFolderItem(mLauncher, item, host)) {
|
||||
announceConfirmation(R.string.item_removed);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
DeleteDropTarget.removeWorkspaceOrFolderItem(mLauncher, item, host);
|
||||
return true;
|
||||
} else if (action == INFO) {
|
||||
InfoDropTarget.startDetailsActivityForInfo(item, mLauncher);
|
||||
return true;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package com.android.launcher3.accessibility;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
|
||||
|
@ -140,26 +141,30 @@ public class WorkspaceAccessibilityHelper extends DragAndDropAccessibilityDelega
|
|||
return mContext.getString(R.string.move_to_empty_cell, y + 1, x + 1);
|
||||
}
|
||||
} else {
|
||||
ItemInfo info = (ItemInfo) child.getTag();
|
||||
if (info instanceof ShortcutInfo) {
|
||||
return mContext.getString(R.string.create_folder_with, info.title);
|
||||
} else if (info instanceof FolderInfo) {
|
||||
if (TextUtils.isEmpty(info.title)) {
|
||||
// Find the first item in the folder.
|
||||
FolderInfo folder = (FolderInfo) info;
|
||||
ShortcutInfo firstItem = null;
|
||||
for (ShortcutInfo shortcut : folder.contents) {
|
||||
if (firstItem == null || firstItem.rank > shortcut.rank) {
|
||||
firstItem = shortcut;
|
||||
}
|
||||
}
|
||||
return getDescriptionForDropOver(child, mContext);
|
||||
}
|
||||
}
|
||||
|
||||
if (firstItem != null) {
|
||||
return mContext.getString(R.string.add_to_folder_with_app, firstItem.title);
|
||||
public static String getDescriptionForDropOver(View overChild, Context context) {
|
||||
ItemInfo info = (ItemInfo) overChild.getTag();
|
||||
if (info instanceof ShortcutInfo) {
|
||||
return context.getString(R.string.create_folder_with, info.title);
|
||||
} else if (info instanceof FolderInfo) {
|
||||
if (TextUtils.isEmpty(info.title)) {
|
||||
// Find the first item in the folder.
|
||||
FolderInfo folder = (FolderInfo) info;
|
||||
ShortcutInfo firstItem = null;
|
||||
for (ShortcutInfo shortcut : folder.contents) {
|
||||
if (firstItem == null || firstItem.rank > shortcut.rank) {
|
||||
firstItem = shortcut;
|
||||
}
|
||||
}
|
||||
return mContext.getString(R.string.add_to_folder, info.title);
|
||||
|
||||
if (firstItem != null) {
|
||||
return context.getString(R.string.add_to_folder_with_app, firstItem.title);
|
||||
}
|
||||
}
|
||||
return context.getString(R.string.add_to_folder, info.title);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
|
|
@ -148,8 +148,11 @@ public class WidgetsContainerView extends BaseContainerView
|
|||
if (mWidgetInstructionToast != null) {
|
||||
mWidgetInstructionToast.cancel();
|
||||
}
|
||||
mWidgetInstructionToast = Toast.makeText(getContext(),R.string.long_press_widget_to_add,
|
||||
Toast.LENGTH_SHORT);
|
||||
|
||||
CharSequence msg = Utilities.wrapForTts(
|
||||
getContext().getText(R.string.long_press_widget_to_add),
|
||||
getContext().getString(R.string.long_accessible_way_to_add));
|
||||
mWidgetInstructionToast = Toast.makeText(getContext(), msg, Toast.LENGTH_SHORT);
|
||||
mWidgetInstructionToast.show();
|
||||
}
|
||||
|
||||
|
@ -164,7 +167,6 @@ public class WidgetsContainerView extends BaseContainerView
|
|||
if (!mLauncher.isWidgetsViewVisible() ||
|
||||
mLauncher.getWorkspace().isSwitchingState()) return false;
|
||||
// Return if global dragging is not enabled
|
||||
Log.d(TAG, String.format("onLonglick dragging enabled?.", v));
|
||||
if (!mLauncher.isDraggingEnabled()) return false;
|
||||
|
||||
boolean status = beginDragging(v);
|
||||
|
|
Loading…
Reference in New Issue