blob: 5fb9440e014ba6d2ec94321460336b4fbf428250 [file] [log] [blame]
/*
* 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.view.View;
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
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);
boolean result = false;
if (action == R.id.action_drag_move_up) {
if (position > 0) {
mAdapter.onItemMove(position, position - 1);
result = true;
}
} else if (action == R.id.action_drag_move_down) {
if (position + 1 < itemCount) {
mAdapter.onItemMove(position, position + 1);
result = true;
}
} else if (action == R.id.action_drag_move_top) {
if (position != 0) {
mAdapter.onItemMove(position, 0);
result = true;
}
} else if (action == R.id.action_drag_move_bottom) {
if (position != itemCount - 1) {
mAdapter.onItemMove(position, itemCount - 1);
result = true;
}
} else if (action == R.id.action_drag_remove) {
if (itemCount > 1) {
mAdapter.removeItem(position);
result = true;
}
} else {
return super.performAccessibilityActionForItem(recycler, state, host, action, args);
}
if (result) {
mAdapter.doTheUpdate();
}
return result;
}
}