Merge "Add accessibility actions to the drag-and-drop locale list" into nyc-dev
This commit is contained in:
@@ -38,7 +38,6 @@ import com.android.settings.R;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
@@ -184,12 +183,14 @@ class LocaleDragAndDropAdapter
|
||||
return itemCount;
|
||||
}
|
||||
|
||||
private void onItemMove(int fromPosition, int toPosition) {
|
||||
void onItemMove(int fromPosition, int toPosition) {
|
||||
if (fromPosition >= 0 && toPosition >= 0) {
|
||||
Collections.swap(mFeedItemList, fromPosition, toPosition);
|
||||
final LocaleStore.LocaleInfo saved = mFeedItemList.get(fromPosition);
|
||||
mFeedItemList.remove(fromPosition);
|
||||
mFeedItemList.add(toPosition, saved);
|
||||
} else {
|
||||
// TODO: It looks like sometimes the RecycleView tries to swap item -1
|
||||
// Investigate and file a bug.
|
||||
// I did not see it in a while, but if it happens, investigate and file a bug.
|
||||
Log.e(TAG, String.format(Locale.US,
|
||||
"Negative position in onItemMove %d -> %d", fromPosition, toPosition));
|
||||
}
|
||||
@@ -207,6 +208,23 @@ class LocaleDragAndDropAdapter
|
||||
}
|
||||
}
|
||||
|
||||
boolean isRemoveMode() {
|
||||
return mRemoveMode;
|
||||
}
|
||||
|
||||
void removeItem(int position) {
|
||||
int itemCount = mFeedItemList.size();
|
||||
if (itemCount <= 1) {
|
||||
return;
|
||||
}
|
||||
if (position < 0 || position >= itemCount) {
|
||||
return;
|
||||
}
|
||||
mFeedItemList.remove(position);
|
||||
notifyDataSetChanged();
|
||||
doTheUpdate();
|
||||
}
|
||||
|
||||
void removeChecked() {
|
||||
int itemCount = mFeedItemList.size();
|
||||
for (int i = itemCount - 1; i >= 0; i--) {
|
||||
|
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Copyright (C) 2016 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.settings.localepicker;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.settings.R;
|
||||
|
||||
/**
|
||||
* Add accessibility actions to the drag-and-drop locale list
|
||||
*
|
||||
* <p>Dragging is not supported neither by TalkBack or the accessibility
|
||||
* framework at the moment. So we need custom actions to be able
|
||||
* to change the order of the locales.</p>
|
||||
*
|
||||
* <p>Also, the remove functionality is difficult to discover and use
|
||||
* with TalkBack only, so we are also adding a "remove" action.</p>
|
||||
*
|
||||
* <p>It only removes one locale at the time, but most users don't
|
||||
* really add many locales "by mistake", so there is no real need
|
||||
* to delete a lot of locales at once.</p>
|
||||
*/
|
||||
public class LocaleLinearLayoutManager extends LinearLayoutManager {
|
||||
private final LocaleDragAndDropAdapter mAdapter;
|
||||
private final Context mContext;
|
||||
|
||||
private final AccessibilityNodeInfoCompat.AccessibilityActionCompat mActionMoveUp;
|
||||
private final AccessibilityNodeInfoCompat.AccessibilityActionCompat mActionMoveDown;
|
||||
private final AccessibilityNodeInfoCompat.AccessibilityActionCompat mActionMoveTop;
|
||||
private final AccessibilityNodeInfoCompat.AccessibilityActionCompat mActionMoveBottom;
|
||||
private final AccessibilityNodeInfoCompat.AccessibilityActionCompat mActionRemove;
|
||||
|
||||
public LocaleLinearLayoutManager(Context context, LocaleDragAndDropAdapter adapter) {
|
||||
super(context);
|
||||
this.mContext = context;
|
||||
this.mAdapter = adapter;
|
||||
|
||||
this.mActionMoveUp = new AccessibilityNodeInfoCompat.AccessibilityActionCompat(
|
||||
R.id.action_drag_move_up,
|
||||
mContext.getString(R.string.action_drag_label_move_up));
|
||||
this.mActionMoveDown = new AccessibilityNodeInfoCompat.AccessibilityActionCompat(
|
||||
R.id.action_drag_move_down,
|
||||
mContext.getString(R.string.action_drag_label_move_down));
|
||||
this.mActionMoveTop = new AccessibilityNodeInfoCompat.AccessibilityActionCompat(
|
||||
R.id.action_drag_move_top,
|
||||
mContext.getString(R.string.action_drag_label_move_top));
|
||||
this.mActionMoveBottom = new AccessibilityNodeInfoCompat.AccessibilityActionCompat(
|
||||
R.id.action_drag_move_bottom,
|
||||
mContext.getString(R.string.action_drag_label_move_bottom));
|
||||
this.mActionRemove = new AccessibilityNodeInfoCompat.AccessibilityActionCompat(
|
||||
R.id.action_drag_remove,
|
||||
mContext.getString(R.string.action_drag_label_remove));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInitializeAccessibilityNodeInfoForItem(RecyclerView.Recycler recycler,
|
||||
RecyclerView.State state, View host, AccessibilityNodeInfoCompat info) {
|
||||
|
||||
super.onInitializeAccessibilityNodeInfoForItem(recycler, state, host, info);
|
||||
|
||||
final int itemCount = this.getItemCount();
|
||||
final int position = this.getPosition(host);
|
||||
final LocaleDragCell dragCell = (LocaleDragCell) host;
|
||||
|
||||
// We want the description to be something not localizable, so that any TTS engine for
|
||||
// any language can handle it. And we want the position to be part of it.
|
||||
// So we use something like "2, French (France)"
|
||||
final String description =
|
||||
(position + 1) + ", " + dragCell.getCheckbox().getContentDescription();
|
||||
info.setContentDescription(description);
|
||||
|
||||
if (mAdapter.isRemoveMode()) { // We don't move things around in remove mode
|
||||
return;
|
||||
}
|
||||
|
||||
// The order in which we add the actions is important for the circular selection menu.
|
||||
// With the current order the "up" action will be (more or less) up, and "down" more
|
||||
// or less down ("more or less" because we have 5 actions)
|
||||
if (position > 0) { // it is not the first one
|
||||
info.addAction(mActionMoveUp);
|
||||
info.addAction(mActionMoveTop);
|
||||
}
|
||||
if (position + 1 < itemCount) { // it is not the last one
|
||||
info.addAction(mActionMoveDown);
|
||||
info.addAction(mActionMoveBottom);
|
||||
}
|
||||
if (itemCount > 1) {
|
||||
info.addAction(mActionRemove);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean performAccessibilityActionForItem(RecyclerView.Recycler recycler,
|
||||
RecyclerView.State state, View host, int action, Bundle args) {
|
||||
|
||||
final int itemCount = this.getItemCount();
|
||||
final int position = this.getPosition(host);
|
||||
|
||||
switch (action) {
|
||||
case R.id.action_drag_move_up:
|
||||
if (position > 0) {
|
||||
mAdapter.onItemMove(position, position - 1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case R.id.action_drag_move_down:
|
||||
if (position + 1 < itemCount) {
|
||||
mAdapter.onItemMove(position, position + 1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case R.id.action_drag_move_top:
|
||||
if (position != 0) {
|
||||
mAdapter.onItemMove(position, 0);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case R.id.action_drag_move_bottom:
|
||||
if (position != itemCount - 1) {
|
||||
mAdapter.onItemMove(position, itemCount - 1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case R.id.action_drag_remove:
|
||||
if (itemCount > 1) {
|
||||
mAdapter.removeItem(position);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
default:
|
||||
return super.performAccessibilityActionForItem(recycler, state, host, action, args);
|
||||
}
|
||||
}
|
||||
}
|
@@ -21,7 +21,6 @@ import android.app.FragmentTransaction;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.util.LocaleList;
|
||||
import android.view.LayoutInflater;
|
||||
@@ -30,7 +29,6 @@ import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import com.android.internal.app.LocalePicker;
|
||||
import com.android.internal.app.LocalePickerWithRegion;
|
||||
@@ -76,9 +74,8 @@ public class LocaleListEditor extends SettingsPreferenceFragment
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstState) {
|
||||
View result = super.onCreateView(inflater, container, savedInstState);
|
||||
LinearLayout ll = (LinearLayout) result;
|
||||
View myLayout = inflater.inflate(R.layout.locale_order_list, ll);
|
||||
final View result = super.onCreateView(inflater, container, savedInstState);
|
||||
final View myLayout = inflater.inflate(R.layout.locale_order_list, (ViewGroup) result);
|
||||
|
||||
getActivity().setTitle(R.string.pref_title_lang_selection);
|
||||
|
||||
@@ -236,7 +233,7 @@ public class LocaleListEditor extends SettingsPreferenceFragment
|
||||
|
||||
private void configureDragAndDrop(View view) {
|
||||
final RecyclerView list = (RecyclerView) view.findViewById(R.id.dragList);
|
||||
final LinearLayoutManager llm = new LinearLayoutManager(this.getContext());
|
||||
final LocaleLinearLayoutManager llm = new LocaleLinearLayoutManager(getContext(), mAdapter);
|
||||
llm.setAutoMeasureEnabled(true);
|
||||
list.setLayoutManager(llm);
|
||||
|
||||
|
Reference in New Issue
Block a user