Merge "FloatingToolbar: Rules for ordering menu items." into oc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
6d149bc953
@@ -146,7 +146,7 @@ public class Editor {
|
||||
private static final String UNDO_OWNER_TAG = "Editor";
|
||||
|
||||
// Ordering constants used to place the Action Mode or context menu items in their menu.
|
||||
private static final int MENU_ITEM_ORDER_ASSIST = 1;
|
||||
private static final int MENU_ITEM_ORDER_ASSIST = 0;
|
||||
private static final int MENU_ITEM_ORDER_UNDO = 2;
|
||||
private static final int MENU_ITEM_ORDER_REDO = 3;
|
||||
private static final int MENU_ITEM_ORDER_CUT = 4;
|
||||
@@ -156,8 +156,8 @@ public class Editor {
|
||||
private static final int MENU_ITEM_ORDER_PASTE_AS_PLAIN_TEXT = 8;
|
||||
private static final int MENU_ITEM_ORDER_SELECT_ALL = 9;
|
||||
private static final int MENU_ITEM_ORDER_REPLACE = 10;
|
||||
private static final int MENU_ITEM_ORDER_PROCESS_TEXT_INTENT_ACTIONS_START = 11;
|
||||
private static final int MENU_ITEM_ORDER_AUTOFILL = 12;
|
||||
private static final int MENU_ITEM_ORDER_AUTOFILL = 11;
|
||||
private static final int MENU_ITEM_ORDER_PROCESS_TEXT_INTENT_ACTIONS_START = 100;
|
||||
|
||||
// Each Editor manages its own undo stack.
|
||||
private final UndoManager mUndoManager = new UndoManager();
|
||||
@@ -6322,9 +6322,10 @@ public class Editor {
|
||||
* Adds "PROCESS_TEXT" menu items to the specified menu.
|
||||
*/
|
||||
public void onInitializeMenu(Menu menu) {
|
||||
int i = 0;
|
||||
final int size = mSupportedActivities.size();
|
||||
loadSupportedActivities();
|
||||
for (ResolveInfo resolveInfo : mSupportedActivities) {
|
||||
for (int i = 0; i < size; i++) {
|
||||
final ResolveInfo resolveInfo = mSupportedActivities.get(i);
|
||||
menu.add(Menu.NONE, Menu.NONE,
|
||||
Editor.MENU_ITEM_ORDER_PROCESS_TEXT_INTENT_ACTIONS_START + i++,
|
||||
getLabel(resolveInfo))
|
||||
|
||||
@@ -233,6 +233,7 @@ public final class FloatingToolbar {
|
||||
|
||||
private void doShow() {
|
||||
List<MenuItem> menuItems = getVisibleAndEnabledMenuItems(mMenu);
|
||||
tidy(menuItems);
|
||||
if (!isCurrentlyShowing(menuItems) || mWidthChanged) {
|
||||
mPopup.dismiss();
|
||||
mPopup.layoutMenuItems(menuItems, mMenuItemClickListener, mSuggestedWidth);
|
||||
@@ -274,6 +275,36 @@ public final class FloatingToolbar {
|
||||
return menuItems;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the list of menu items to conform to certain requirements.
|
||||
*/
|
||||
private void tidy(List<MenuItem> menuItems) {
|
||||
int assistItemIndex = -1;
|
||||
Drawable assistItemDrawable = null;
|
||||
|
||||
final int size = menuItems.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
final MenuItem menuItem = menuItems.get(i);
|
||||
|
||||
if (menuItem.getItemId() == android.R.id.textAssist) {
|
||||
assistItemIndex = i;
|
||||
assistItemDrawable = menuItem.getIcon();
|
||||
}
|
||||
|
||||
// Remove icons for all menu items with text.
|
||||
if (!TextUtils.isEmpty(menuItem.getTitle())) {
|
||||
menuItem.setIcon(null);
|
||||
}
|
||||
}
|
||||
if (assistItemIndex > -1) {
|
||||
final MenuItem assistMenuItem = menuItems.remove(assistItemIndex);
|
||||
// Ensure the assist menu item preserves its icon.
|
||||
assistMenuItem.setIcon(assistItemDrawable);
|
||||
// Ensure the assist menu item is always the first item.
|
||||
menuItems.add(0, assistMenuItem);
|
||||
}
|
||||
}
|
||||
|
||||
private List<Object> getShowingMenuItemsReferences(List<MenuItem> menuItems) {
|
||||
List<Object> references = new ArrayList<Object>();
|
||||
for (MenuItem menuItem : menuItems) {
|
||||
|
||||
@@ -28,6 +28,7 @@ import static android.widget.espresso.TextViewActions.longPressAndDragOnText;
|
||||
import static android.widget.espresso.TextViewActions.longPressOnTextAtIndex;
|
||||
import static android.widget.espresso.TextViewAssertions.hasInsertionPointerAtIndex;
|
||||
import static android.widget.espresso.TextViewAssertions.hasSelection;
|
||||
import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarItemIndex;
|
||||
import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarIsDisplayed;
|
||||
import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarIsNotDisplayed;
|
||||
import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarContainsItem;
|
||||
@@ -46,6 +47,11 @@ import static android.support.test.espresso.matcher.ViewMatchers.withText;
|
||||
import static org.hamcrest.Matchers.anyOf;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
||||
import android.view.ActionMode;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.textclassifier.TextClassificationManager;
|
||||
import android.view.textclassifier.TextClassifier;
|
||||
import android.widget.espresso.CustomViewActions.RelativeCoordinatesProvider;
|
||||
|
||||
import android.support.test.espresso.action.EspressoKey;
|
||||
@@ -71,7 +77,8 @@ public class TextViewActivityTest extends ActivityInstrumentationTestCase2<TextV
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
getActivity();
|
||||
getActivity().getSystemService(TextClassificationManager.class)
|
||||
.setTextClassifier(TextClassifier.NO_OP);
|
||||
}
|
||||
|
||||
public void testTypedTextIsOnScreen() throws Exception {
|
||||
@@ -676,4 +683,38 @@ public class TextViewActivityTest extends ActivityInstrumentationTestCase2<TextV
|
||||
// hasTransientState should return false when selection is created by API.
|
||||
assertFalse(textView.hasTransientState());
|
||||
}
|
||||
|
||||
public void testAssistItemIsAtIndexZero() throws Exception {
|
||||
getActivity().getSystemService(TextClassificationManager.class).setTextClassifier(null);
|
||||
final TextView textView = (TextView) getActivity().findViewById(R.id.textview);
|
||||
textView.post(() -> textView.setCustomSelectionActionModeCallback(
|
||||
new ActionMode.Callback() {
|
||||
@Override
|
||||
public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
|
||||
// Create another item at order position 0 to confirm that it will never be
|
||||
// placed before the textAssist item.
|
||||
menu.add(Menu.NONE, 0 /* id */, 0 /* order */, "Test");
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyActionMode(ActionMode actionMode) {}
|
||||
}));
|
||||
final String text = "droid@android.com";
|
||||
|
||||
onView(withId(R.id.textview)).perform(replaceText(text));
|
||||
onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf('@')));
|
||||
sleepForFloatingToolbarPopup();
|
||||
assertFloatingToolbarItemIndex(android.R.id.textAssist, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,13 @@ import static android.support.test.espresso.matcher.ViewMatchers.withText;
|
||||
import static org.hamcrest.Matchers.allOf;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
||||
import android.view.MenuItem;
|
||||
import android.view.ViewGroup;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.hamcrest.Description;
|
||||
import org.hamcrest.Matcher;
|
||||
import org.hamcrest.TypeSafeMatcher;
|
||||
|
||||
import android.support.test.espresso.NoMatchingRootException;
|
||||
import android.support.test.espresso.NoMatchingViewException;
|
||||
@@ -122,6 +128,39 @@ public class FloatingToolbarEspressoUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the floating toolbar contains a specified item at a specified index.
|
||||
*
|
||||
* @param menuItemId id of the menu item
|
||||
* @param index expected index of the menu item in the floating toolbar
|
||||
* @throws AssertionError if the assertion fails
|
||||
*/
|
||||
public static void assertFloatingToolbarItemIndex(final int menuItemId, final int index) {
|
||||
onFloatingToolBar().check(matches(new TypeSafeMatcher<View>() {
|
||||
private List<Integer> menuItemIds = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public boolean matchesSafely(View view) {
|
||||
collectMenuItemIds(view);
|
||||
return menuItemIds.size() > index && menuItemIds.get(index) == menuItemId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeTo(Description description) {}
|
||||
|
||||
private void collectMenuItemIds(View view) {
|
||||
if (view.getTag() instanceof MenuItem) {
|
||||
menuItemIds.add(((MenuItem) view.getTag()).getItemId());
|
||||
} else if (view instanceof ViewGroup) {
|
||||
ViewGroup viewGroup = (ViewGroup) view;
|
||||
for (int i = 0; i < viewGroup.getChildCount(); i++) {
|
||||
collectMenuItemIds(viewGroup.getChildAt(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the floating toolbar doesn't contain the specified item.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user