Add custom actions to the reorderable list (#20108)

This commit is contained in:
David Shuckerow
2018-08-07 12:48:23 -07:00
committed by GitHub
parent 0630518b1b
commit 99d5ef903c
64 changed files with 1762 additions and 103 deletions

View File

@@ -27,10 +27,8 @@ import 'typography.dart';
// flutter_localizations package, you must first add it to the English
// translations (lib/src/l10n/material_en.arb), including a description, then
// you must add it to every other language (all the other *.arb files in that
// same directory), including a best guess as to the translation, e.g.
// obtained by optimistic use of Google Translate
// (https://translate.google.com/). After that you have to re-generate
// lib/src/l10n/localizations.dart by running
// same directory), listing the translation as `TBD`. After that you have to
// re-generate lib/src/l10n/localizations.dart by running
// `dart dev/tools/gen_localizations.dart --overwrite`. There is a README
// file with further information in the lib/src/l10n/ directory.
//
@@ -279,6 +277,30 @@ abstract class MaterialLocalizations {
/// shows the list of accounts.
String get showAccountsLabel;
/// The semantics label used for [ReorderableList] to reorder an item in the
/// list to the start of the list.
String get reorderItemToStart;
/// The semantics label used for [ReorderableList] to reorder an item in the
/// list to the end of the list.
String get reorderItemToEnd;
/// The semantics label used for [ReorderableList] to reorder an item in the
/// list one space up the list.
String get reorderItemUp;
/// The semantics label used for [ReorderableList] to reorder an item in the
/// list one space down the list.
String get reorderItemDown;
/// The semantics label used for [ReorderableList] to reorder an item in the
/// list one space left in the list.
String get reorderItemLeft;
/// The semantics label used for [ReorderableList] to reorder an item in the
/// list one space right in the list.
String get reorderItemRight;
/// The `MaterialLocalizations` from the closest [Localizations] instance
/// that encloses the given context.
///
@@ -641,6 +663,24 @@ class DefaultMaterialLocalizations implements MaterialLocalizations {
@override
String get showAccountsLabel => 'Show accounts';
@override
String get reorderItemUp => 'Move up';
@override
String get reorderItemDown => 'Move down';
@override
String get reorderItemLeft => 'Move left';
@override
String get reorderItemRight => 'Move right';
@override
String get reorderItemToEnd => 'Move to the end';
@override
String get reorderItemToStart => 'Move to the start';
/// Creates an object that provides US English resource values for the material
/// library widgets.
///

View File

@@ -8,6 +8,7 @@ import 'package:flutter/widgets.dart';
import 'package:flutter/rendering.dart';
import 'material.dart';
import 'material_localizations.dart';
/// The callback used by [ReorderableListView] to move an item to a new
/// position in a list.
@@ -310,13 +311,10 @@ class _ReorderableListContentState extends State<_ReorderableListContent> with T
// Handles up the logic for dragging and reordering items in the list.
Widget _wrap(Widget toWrap, int index, BoxConstraints constraints) {
assert(toWrap.key != null);
// We create a global key based on both the child key and index
// so that when we reorder the list, a key doesn't get created twice.
final GlobalObjectKey keyIndexGlobalKey = new GlobalObjectKey(toWrap.key);
// We pass the toWrapWithGlobalKey into the Draggable so that when a list
// item gets dragged, the accessibility framework can preserve the selected
// state of the dragging item.
final Widget toWrapWithGlobalKey = new KeyedSubtree(key: keyIndexGlobalKey, child: toWrap);
// Starts dragging toWrap.
void onDragStarted() {
@@ -330,11 +328,11 @@ class _ReorderableListContentState extends State<_ReorderableListContent> with T
});
}
// Drops toWrap into the last position it was hovering over.
void onDragEnded() {
// Places the value from startIndex one space before the element at endIndex.
void reorder(int startIndex, int endIndex) {
setState(() {
if (_dragStartIndex != _currentIndex)
widget.onReorder(_dragStartIndex, _currentIndex);
if (startIndex != endIndex)
widget.onReorder(startIndex, endIndex);
// Animates leftover space in the drop area closed.
// TODO(djshuckerow): bring the animation in line with the Material
// specifications.
@@ -344,7 +342,64 @@ class _ReorderableListContentState extends State<_ReorderableListContent> with T
});
}
// Drops toWrap into the last position it was hovering over.
void onDragEnded() {
reorder(_dragStartIndex, _currentIndex);
}
Widget wrapWithSemantics() {
// First, determine which semantics actions apply.
final Map<CustomSemanticsAction, VoidCallback> semanticsActions = <CustomSemanticsAction, VoidCallback>{};
// Create the appropriate semantics actions.
void moveToStart() => reorder(index, 0);
void moveToEnd() => reorder(index, widget.children.length);
void moveBefore() => reorder(index, index - 1);
// To move after, we go to index+2 because we are moving it to the space
// before index+2, which is after the space at index+1.
void moveAfter() => reorder(index, index + 2);
final MaterialLocalizations localizations = MaterialLocalizations.of(context);
// If the item can move to before its current position in the list.
if (index > 0) {
semanticsActions[new CustomSemanticsAction(label: localizations.reorderItemToStart)] = moveToStart;
String reorderItemBefore = localizations.reorderItemUp;
if (widget.scrollDirection == Axis.horizontal) {
reorderItemBefore = Directionality.of(context) == TextDirection.ltr
? localizations.reorderItemLeft
: localizations.reorderItemRight;
}
semanticsActions[new CustomSemanticsAction(label: reorderItemBefore)] = moveBefore;
}
// If the item can move to after its current position in the list.
if (index < widget.children.length - 1) {
String reorderItemAfter = localizations.reorderItemDown;
if (widget.scrollDirection == Axis.horizontal) {
reorderItemAfter = Directionality.of(context) == TextDirection.ltr
? localizations.reorderItemRight
: localizations.reorderItemLeft;
}
semanticsActions[new CustomSemanticsAction(label: reorderItemAfter)] = moveAfter;
semanticsActions[new CustomSemanticsAction(label: localizations.reorderItemToEnd)] = moveToEnd;
}
// We pass toWrap with a GlobalKey into the Draggable so that when a list
// item gets dragged, the accessibility framework can preserve the selected
// state of the dragging item.
//
// We also apply the relevant custom accessibility actions for moving the item
// up, down, to the start, and to the end of the list.
return new KeyedSubtree(key: keyIndexGlobalKey, child: new Semantics(
customSemanticsActions: semanticsActions,
child: toWrap,
));
}
Widget buildDragTarget(BuildContext context, List<Key> acceptedCandidates, List<dynamic> rejectedCandidates) {
final Widget toWrapWithSemantics = wrapWithSemantics();
// We build the draggable inside of a layout builder so that we can
// constrain the size of the feedback dragging widget.
Widget child = new LongPressDraggable<Key>(
@@ -358,10 +413,10 @@ class _ReorderableListContentState extends State<_ReorderableListContent> with T
constraints: constraints,
child: new Material(
elevation: 6.0,
child: toWrapWithGlobalKey,
child: toWrapWithSemantics,
),
),
child: _dragging == toWrap.key ? const SizedBox() : toWrapWithGlobalKey,
child: _dragging == toWrap.key ? const SizedBox() : toWrapWithSemantics,
childWhenDragging: const SizedBox(),
dragAnchor: DragAnchor.child,
onDragStarted: onDragStarted,
@@ -422,25 +477,22 @@ class _ReorderableListContentState extends State<_ReorderableListContent> with T
}
// We wrap the drag target in a Builder so that we can scroll to its specific context.
return new KeyedSubtree(
key: new Key('#$ReorderableListView|KeyedSubtree|${toWrap.key}'),
child:new Builder(builder: (BuildContext context) {
return new DragTarget<Key>(
builder: buildDragTarget,
onWillAccept: (Key toAccept) {
setState(() {
_nextIndex = index;
_requestAnimationToNextIndex();
});
_scrollTo(context);
// If the target is not the original starting point, then we will accept the drop.
return _dragging == toAccept && toAccept != toWrap.key;
},
onAccept: (Key accepted) {},
onLeave: (Key leaving) {},
);
}),
);
return new Builder(builder: (BuildContext context) {
return new DragTarget<Key>(
builder: buildDragTarget,
onWillAccept: (Key toAccept) {
setState(() {
_nextIndex = index;
_requestAnimationToNextIndex();
});
_scrollTo(context);
// If the target is not the original starting point, then we will accept the drop.
return _dragging == toAccept && toAccept != toWrap.key;
},
onAccept: (Key accepted) {},
onLeave: (Key leaving) {},
);
});
}
@override

View File

@@ -35,6 +35,12 @@ void main() {
expect(localizations.dialogLabel, isNotNull);
expect(localizations.alertDialogLabel, isNotNull);
expect(localizations.searchFieldLabel, isNotNull);
expect(localizations.reorderItemUp, isNotNull);
expect(localizations.reorderItemDown, isNotNull);
expect(localizations.reorderItemLeft, isNotNull);
expect(localizations.reorderItemRight, isNotNull);
expect(localizations.reorderItemToEnd, isNotNull);
expect(localizations.reorderItemToStart, isNotNull);
expect(localizations.aboutListTileTitle('FOO'), isNotNull);
expect(localizations.aboutListTileTitle('FOO'), contains('FOO'));

View File

@@ -3,6 +3,7 @@
// found in the LICENSE file.
import 'package:flutter/gestures.dart';
import 'package:flutter/semantics.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/material.dart';
@@ -29,16 +30,19 @@ void main() {
);
}
Widget build({Widget header, Axis scrollDirection = Axis.vertical}) {
Widget build({Widget header, Axis scrollDirection = Axis.vertical, TextDirection textDirection = TextDirection.ltr}) {
return new MaterialApp(
home: new SizedBox(
height: itemHeight * 10,
width: itemHeight * 10,
child: new ReorderableListView(
header: header,
children: listItems.map(listItemToWidget).toList(),
scrollDirection: scrollDirection,
onReorder: onReorder,
home: new Directionality(
textDirection: textDirection,
child: new SizedBox(
height: itemHeight * 10,
width: itemHeight * 10,
child: new ReorderableListView(
header: header,
children: listItems.map(listItemToWidget).toList(),
scrollDirection: scrollDirection,
onReorder: onReorder,
),
),
),
);
@@ -169,7 +173,6 @@ void main() {
await tester.pump(kLongPressTimeout + kPressTimeout);
await tester.pumpAndSettle();
expect(getContentElement().size.height, kDraggingListHeight);
// Move it
await drag.moveTo(tester.getCenter(find.text('Last item')));
await tester.pumpAndSettle();
@@ -220,6 +223,134 @@ void main() {
expect(findState(const Key('C')).checked, false);
expect(findState(const Key('A')).checked, true);
});
group('Accessibility (a11y/Semantics)', () {
Map<CustomSemanticsAction, VoidCallback> getSemanticsActions(int index) {
final Semantics semantics = find.ancestor(
of: find.byKey(new Key(listItems[index])),
matching: find.byType(Semantics),
).evaluate().first.widget;
return semantics.properties.customSemanticsActions;
}
const CustomSemanticsAction moveToStart = CustomSemanticsAction(label: 'Move to the start');
const CustomSemanticsAction moveToEnd = CustomSemanticsAction(label: 'Move to the end');
const CustomSemanticsAction moveUp = CustomSemanticsAction(label: 'Move up');
const CustomSemanticsAction moveDown = CustomSemanticsAction(label: 'Move down');
testWidgets('Provides the correct accessibility actions in LTR and RTL modes', (WidgetTester tester) async {
// The a11y actions for a vertical list are the same in LTR and RTL modes.
final SemanticsHandle handle = tester.ensureSemantics();
for (TextDirection direction in TextDirection.values) {
await tester.pumpWidget(build());
// The first item can be moved down or to the end.
final Map<CustomSemanticsAction, VoidCallback> firstSemanticsActions = getSemanticsActions(0);
expect(firstSemanticsActions.length, 2, reason: 'The first list item should have 2 custom actions with $direction.');
expect(firstSemanticsActions.containsKey(moveToStart), false, reason: 'The first item cannot `Move to the start` with $direction.');
expect(firstSemanticsActions.containsKey(moveUp), false, reason: 'The first item cannot `Move up` with $direction.');
expect(firstSemanticsActions.containsKey(moveDown), true, reason: 'The first item should be able to `Move down` with $direction.');
expect(firstSemanticsActions.containsKey(moveToEnd), true, reason: 'The first item should be able to `Move to the end` with $direction.');
// Items in the middle can be moved to the start, end, up or down.
for (int i = 1; i < listItems.length - 1; i += 1) {
final Map<CustomSemanticsAction, VoidCallback> ithSemanticsActions = getSemanticsActions(i);
expect(ithSemanticsActions.length, 4, reason: 'List item $i should have 4 custom actions with $direction.');
expect(ithSemanticsActions.containsKey(moveToStart), true, reason: 'List item $i should be able to `Move to the start` with $direction.');
expect(ithSemanticsActions.containsKey(moveUp), true, reason: 'List item $i should be able to `Move up` with $direction.');
expect(ithSemanticsActions.containsKey(moveDown), true, reason: 'List item $i should be able to `Move down` with $direction.');
expect(ithSemanticsActions.containsKey(moveToEnd), true, reason: 'List item $i should be able to `Move to the end` with $direction.');
}
// The last item can be moved up or to the start.
final Map<CustomSemanticsAction, VoidCallback> lastSemanticsActions = getSemanticsActions(listItems.length - 1);
expect(lastSemanticsActions.length, 2, reason: 'The last list item should have 2 custom actions with $direction.');
expect(lastSemanticsActions.containsKey(moveToStart), true, reason: 'The last item should be able to `Move to the start` with $direction.');
expect(lastSemanticsActions.containsKey(moveUp), true, reason: 'The last item should be able to `Move up` with $direction.');
expect(lastSemanticsActions.containsKey(moveDown), false, reason: 'The last item cannot `Move down` with $direction.');
expect(lastSemanticsActions.containsKey(moveToEnd), false, reason: 'The last item cannot `Move to the end` with $direction.');
}
handle.dispose();
});
testWidgets('First item accessibility (a11y) actions work', (WidgetTester tester) async {
final SemanticsHandle handle = tester.ensureSemantics();
expect(listItems, orderedEquals(originalListItems));
// Test out move to end: move Item 1 to the end of the list.
await tester.pumpWidget(build());
Map<CustomSemanticsAction, VoidCallback> firstSemanticsActions = getSemanticsActions(0);
firstSemanticsActions[moveToEnd]();
await tester.pumpAndSettle();
expect(listItems, orderedEquals(<String>['Item 2', 'Item 3', 'Item 4', 'Item 1']));
// Test out move after: move Item 2 (the current first item) one space down.
await tester.pumpWidget(build());
firstSemanticsActions = getSemanticsActions(0);
firstSemanticsActions[moveDown]();
await tester.pumpAndSettle();
expect(listItems, orderedEquals(<String>['Item 3', 'Item 2', 'Item 4', 'Item 1']));
handle.dispose();
});
testWidgets('Middle item accessibility (a11y) actions work', (WidgetTester tester) async {
final SemanticsHandle handle = tester.ensureSemantics();
expect(listItems, orderedEquals(originalListItems));
// Test out move to end: move Item 2 to the end of the list.
await tester.pumpWidget(build());
Map<CustomSemanticsAction, VoidCallback> middleSemanticsActions = getSemanticsActions(1);
middleSemanticsActions[moveToEnd]();
await tester.pumpAndSettle();
expect(listItems, orderedEquals(<String>['Item 1', 'Item 3', 'Item 4', 'Item 2']));
// Test out move after: move Item 3 (the current second item) one space down.
await tester.pumpWidget(build());
middleSemanticsActions = getSemanticsActions(1);
middleSemanticsActions[moveDown]();
await tester.pumpAndSettle();
expect(listItems, orderedEquals(<String>['Item 1', 'Item 4', 'Item 3', 'Item 2']));
// Test out move after: move Item 3 (the current third item) one space up.
await tester.pumpWidget(build());
middleSemanticsActions = getSemanticsActions(2);
middleSemanticsActions[moveUp]();
await tester.pumpAndSettle();
expect(listItems, orderedEquals(<String>['Item 1', 'Item 3', 'Item 4', 'Item 2']));
// Test out move to start: move Item 4 (the current third item) to the start of the list.
await tester.pumpWidget(build());
middleSemanticsActions = getSemanticsActions(2);
middleSemanticsActions[moveToStart]();
await tester.pumpAndSettle();
expect(listItems, orderedEquals(<String>['Item 4', 'Item 1', 'Item 3', 'Item 2']));
handle.dispose();
});
testWidgets('Last item accessibility (a11y) actions work', (WidgetTester tester) async {
final SemanticsHandle handle = tester.ensureSemantics();
expect(listItems, orderedEquals(originalListItems));
// Test out move to start: move Item 4 to the start of the list.
await tester.pumpWidget(build());
Map<CustomSemanticsAction, VoidCallback> lastSemanticsActions = getSemanticsActions(listItems.length - 1);
lastSemanticsActions[moveToStart]();
await tester.pumpAndSettle();
expect(listItems, orderedEquals(<String>['Item 4', 'Item 1', 'Item 2', 'Item 3']));
// Test out move up: move Item 3 (the current last item) one space up.
await tester.pumpWidget(build());
lastSemanticsActions = getSemanticsActions(listItems.length - 1);
lastSemanticsActions[moveUp]();
await tester.pumpAndSettle();
expect(listItems, orderedEquals(<String>['Item 4', 'Item 1', 'Item 3', 'Item 2']));
handle.dispose();
});
});
});
group('in horizontal mode', () {
@@ -268,7 +399,6 @@ void main() {
await tester.pumpAndSettle();
expect(find.text('Header Text'), findsOneWidget);
expect(listItems, orderedEquals(<String>['Item 2', 'Item 3', 'Item 4', 'Item 1']));
await tester.pumpWidget(build(header: const Text('Header Text'), scrollDirection: Axis.horizontal));
await longPressDrag(
tester,
@@ -340,7 +470,6 @@ void main() {
await tester.pump(kLongPressTimeout + kPressTimeout);
await tester.pumpAndSettle();
expect(getContentElement().size.width, kDraggingListWidth);
// Move it
await drag.moveTo(tester.getCenter(find.text('Last item')));
await tester.pumpAndSettle();
@@ -394,6 +523,250 @@ void main() {
expect(findState(const Key('C')).checked, false);
expect(findState(const Key('A')).checked, true);
});
group('Accessibility (a11y/Semantics)', () {
Map<CustomSemanticsAction, VoidCallback> getSemanticsActions(int index) {
final Semantics semantics = find.ancestor(
of: find.byKey(new Key(listItems[index])),
matching: find.byType(Semantics),
).evaluate().first.widget;
return semantics.properties.customSemanticsActions;
}
const CustomSemanticsAction moveToStart = CustomSemanticsAction(label: 'Move to the start');
const CustomSemanticsAction moveToEnd = CustomSemanticsAction(label: 'Move to the end');
const CustomSemanticsAction moveLeft = CustomSemanticsAction(label: 'Move left');
const CustomSemanticsAction moveRight = CustomSemanticsAction(label: 'Move right');
testWidgets('Provides the correct accessibility actions in LTR mode', (WidgetTester tester) async {
final SemanticsHandle handle = tester.ensureSemantics();
await tester.pumpWidget(build(scrollDirection: Axis.horizontal));
// The first item can be moved right or to the end.
final Map<CustomSemanticsAction, VoidCallback> firstSemanticsActions = getSemanticsActions(0);
expect(firstSemanticsActions.length, 2, reason: 'The first list item should have 2 custom actions.');
expect(firstSemanticsActions.containsKey(moveToStart), false, reason: 'The first item cannot `Move to the start`.');
expect(firstSemanticsActions.containsKey(moveLeft), false, reason: 'The first item cannot `Move left`.');
expect(firstSemanticsActions.containsKey(moveRight), true, reason: 'The first item should be able to `Move right`.');
expect(firstSemanticsActions.containsKey(moveToEnd), true, reason: 'The first item should be able to `Move to the end`.');
// Items in the middle can be moved to the start, end, left or right.
for (int i = 1; i < listItems.length - 1; i += 1) {
final Map<CustomSemanticsAction, VoidCallback> ithSemanticsActions = getSemanticsActions(i);
expect(ithSemanticsActions.length, 4, reason: 'List item $i should have 4 custom actions.');
expect(ithSemanticsActions.containsKey(moveToStart), true, reason: 'List item $i should be able to `Move to the start`.');
expect(ithSemanticsActions.containsKey(moveLeft), true, reason: 'List item $i should be able to `Move left`.');
expect(ithSemanticsActions.containsKey(moveRight), true, reason: 'List item $i should be able to `Move right`.');
expect(ithSemanticsActions.containsKey(moveToEnd), true, reason: 'List item $i should be able to `Move to the end`.');
}
// The last item can be moved left or to the start.
final Map<CustomSemanticsAction, VoidCallback> lastSemanticsActions = getSemanticsActions(listItems.length - 1);
expect(lastSemanticsActions.length, 2, reason: 'The last list item should have 2 custom actions.');
expect(lastSemanticsActions.containsKey(moveToStart), true, reason: 'The last item should be able to `Move to the start`.');
expect(lastSemanticsActions.containsKey(moveLeft), true, reason: 'The last item should be able to `Move left`.');
expect(lastSemanticsActions.containsKey(moveRight), false, reason: 'The last item cannot `Move right`.');
expect(lastSemanticsActions.containsKey(moveToEnd), false, reason: 'The last item cannot `Move to the end`.');
handle.dispose();
});
testWidgets('Provides the correct accessibility actions in Right-To-Left directionality', (WidgetTester tester) async {
// In RTL mode, the right is the start and the left is the end.
// The array representation is unchanged (LTR), but the direction of the motion actions is reversed.
final SemanticsHandle handle = tester.ensureSemantics();
await tester.pumpWidget(build(scrollDirection: Axis.horizontal, textDirection: TextDirection.rtl));
// The first item can be moved right or to the end.
final Map<CustomSemanticsAction, VoidCallback> firstSemanticsActions = getSemanticsActions(0);
expect(firstSemanticsActions.length, 2, reason: 'The first list item should have 2 custom actions.');
expect(firstSemanticsActions.containsKey(moveToStart), false, reason: 'The first item cannot `Move to the start`.');
expect(firstSemanticsActions.containsKey(moveRight), false, reason: 'The first item cannot `Move right`.');
expect(firstSemanticsActions.containsKey(moveLeft), true, reason: 'The first item should be able to `Move left`.');
expect(firstSemanticsActions.containsKey(moveToEnd), true, reason: 'The first item should be able to `Move to the end`.');
// Items in the middle can be moved to the start, end, left or right.
for (int i = 1; i < listItems.length - 1; i += 1) {
final Map<CustomSemanticsAction, VoidCallback> ithSemanticsActions = getSemanticsActions(i);
expect(ithSemanticsActions.length, 4, reason: 'List item $i should have 4 custom actions.');
expect(ithSemanticsActions.containsKey(moveToStart), true, reason: 'List item $i should be able to `Move to the start`.');
expect(ithSemanticsActions.containsKey(moveRight), true, reason: 'List item $i should be able to `Move right`.');
expect(ithSemanticsActions.containsKey(moveLeft), true, reason: 'List item $i should be able to `Move left`.');
expect(ithSemanticsActions.containsKey(moveToEnd), true, reason: 'List item $i should be able to `Move to the end`.');
}
// The last item can be moved left or to the start.
final Map<CustomSemanticsAction, VoidCallback> lastSemanticsActions = getSemanticsActions(listItems.length - 1);
expect(lastSemanticsActions.length, 2, reason: 'The last list item should have 2 custom actions.');
expect(lastSemanticsActions.containsKey(moveToStart), true, reason: 'The last item should be able to `Move to the start`.');
expect(lastSemanticsActions.containsKey(moveRight), true, reason: 'The last item should be able to `Move right`.');
expect(lastSemanticsActions.containsKey(moveLeft), false, reason: 'The last item cannot `Move left`.');
expect(lastSemanticsActions.containsKey(moveToEnd), false, reason: 'The last item cannot `Move to the end`.');
handle.dispose();
});
testWidgets('First item accessibility (a11y) actions work in LTR mode', (WidgetTester tester) async {
final SemanticsHandle handle = tester.ensureSemantics();
expect(listItems, orderedEquals(originalListItems));
// Test out move to end: move Item 1 to the end of the list.
await tester.pumpWidget(build(scrollDirection: Axis.horizontal));
Map<CustomSemanticsAction, VoidCallback> firstSemanticsActions = getSemanticsActions(0);
firstSemanticsActions[moveToEnd]();
await tester.pumpAndSettle();
expect(listItems, orderedEquals(<String>['Item 2', 'Item 3', 'Item 4', 'Item 1']));
// Test out move after: move Item 2 (the current first item) one space to the right.
await tester.pumpWidget(build(scrollDirection: Axis.horizontal));
firstSemanticsActions = getSemanticsActions(0);
firstSemanticsActions[moveRight]();
await tester.pumpAndSettle();
expect(listItems, orderedEquals(<String>['Item 3', 'Item 2', 'Item 4', 'Item 1']));
handle.dispose();
});
testWidgets('First item accessibility (a11y) actions work in Right-To-Left directionality', (WidgetTester tester) async {
// In RTL mode, the right is the start and the left is the end.
// The array representation is unchanged (LTR), but the direction of the motion actions is reversed.
final SemanticsHandle handle = tester.ensureSemantics();
expect(listItems, orderedEquals(originalListItems));
// Test out move to end: move Item 1 to the end of the list.
await tester.pumpWidget(build(scrollDirection: Axis.horizontal, textDirection: TextDirection.rtl));
Map<CustomSemanticsAction, VoidCallback> firstSemanticsActions = getSemanticsActions(0);
firstSemanticsActions[moveToEnd]();
await tester.pumpAndSettle();
expect(listItems, orderedEquals(<String>['Item 2', 'Item 3', 'Item 4', 'Item 1']));
// Test out move after: move Item 2 (the current first item) one space to the left.
await tester.pumpWidget(build(scrollDirection: Axis.horizontal, textDirection: TextDirection.rtl));
firstSemanticsActions = getSemanticsActions(0);
firstSemanticsActions[moveLeft]();
await tester.pumpAndSettle();
expect(listItems, orderedEquals(<String>['Item 3', 'Item 2', 'Item 4', 'Item 1']));
handle.dispose();
});
testWidgets('Middle item accessibility (a11y) actions work in LTR mode', (WidgetTester tester) async {
final SemanticsHandle handle = tester.ensureSemantics();
expect(listItems, orderedEquals(originalListItems));
// Test out move to end: move Item 2 to the end of the list.
await tester.pumpWidget(build(scrollDirection: Axis.horizontal));
Map<CustomSemanticsAction, VoidCallback> middleSemanticsActions = getSemanticsActions(1);
middleSemanticsActions[moveToEnd]();
await tester.pumpAndSettle();
expect(listItems, orderedEquals(<String>['Item 1', 'Item 3', 'Item 4', 'Item 2']));
// Test out move after: move Item 3 (the current second item) one space to the right.
await tester.pumpWidget(build(scrollDirection: Axis.horizontal));
middleSemanticsActions = getSemanticsActions(1);
middleSemanticsActions[moveRight]();
await tester.pumpAndSettle();
expect(listItems, orderedEquals(<String>['Item 1', 'Item 4', 'Item 3', 'Item 2']));
// Test out move after: move Item 3 (the current third item) one space to the left.
await tester.pumpWidget(build(scrollDirection: Axis.horizontal));
middleSemanticsActions = getSemanticsActions(2);
middleSemanticsActions[moveLeft]();
await tester.pumpAndSettle();
expect(listItems, orderedEquals(<String>['Item 1', 'Item 3', 'Item 4', 'Item 2']));
// Test out move to start: move Item 4 (the current third item) to the start of the list.
await tester.pumpWidget(build(scrollDirection: Axis.horizontal));
middleSemanticsActions = getSemanticsActions(2);
middleSemanticsActions[moveToStart]();
await tester.pumpAndSettle();
expect(listItems, orderedEquals(<String>['Item 4', 'Item 1', 'Item 3', 'Item 2']));
handle.dispose();
});
testWidgets('Middle item accessibility (a11y) actions work in Right-To-Left directionality', (WidgetTester tester) async {
// In RTL mode, the right is the start and the left is the end.
// The array representation is unchanged (LTR), but the direction of the motion actions is reversed.
final SemanticsHandle handle = tester.ensureSemantics();
expect(listItems, orderedEquals(originalListItems));
// Test out move to end: move Item 2 to the end of the list.
await tester.pumpWidget(build(scrollDirection: Axis.horizontal, textDirection: TextDirection.rtl));
Map<CustomSemanticsAction, VoidCallback> middleSemanticsActions = getSemanticsActions(1);
middleSemanticsActions[moveToEnd]();
await tester.pumpAndSettle();
expect(listItems, orderedEquals(<String>['Item 1', 'Item 3', 'Item 4', 'Item 2']));
// Test out move after: move Item 3 (the current second item) one space to the left.
await tester.pumpWidget(build(scrollDirection: Axis.horizontal, textDirection: TextDirection.rtl));
middleSemanticsActions = getSemanticsActions(1);
middleSemanticsActions[moveLeft]();
await tester.pumpAndSettle();
expect(listItems, orderedEquals(<String>['Item 1', 'Item 4', 'Item 3', 'Item 2']));
// Test out move after: move Item 3 (the current third item) one space to the right.
await tester.pumpWidget(build(scrollDirection: Axis.horizontal, textDirection: TextDirection.rtl));
middleSemanticsActions = getSemanticsActions(2);
middleSemanticsActions[moveRight]();
await tester.pumpAndSettle();
expect(listItems, orderedEquals(<String>['Item 1', 'Item 3', 'Item 4', 'Item 2']));
// Test out move to start: move Item 4 (the current third item) to the start of the list.
await tester.pumpWidget(build(scrollDirection: Axis.horizontal, textDirection: TextDirection.rtl));
middleSemanticsActions = getSemanticsActions(2);
middleSemanticsActions[moveToStart]();
await tester.pumpAndSettle();
expect(listItems, orderedEquals(<String>['Item 4', 'Item 1', 'Item 3', 'Item 2']));
handle.dispose();
});
testWidgets('Last item accessibility (a11y) actions work in LTR mode', (WidgetTester tester) async {
final SemanticsHandle handle = tester.ensureSemantics();
expect(listItems, orderedEquals(originalListItems));
// Test out move to start: move Item 4 to the start of the list.
await tester.pumpWidget(build(scrollDirection: Axis.horizontal));
Map<CustomSemanticsAction, VoidCallback> lastSemanticsActions = getSemanticsActions(listItems.length - 1);
lastSemanticsActions[moveToStart]();
await tester.pumpAndSettle();
expect(listItems, orderedEquals(<String>['Item 4', 'Item 1', 'Item 2', 'Item 3']));
// Test out move before: move Item 3 (the current last item) one space to the left.
await tester.pumpWidget(build(scrollDirection: Axis.horizontal));
lastSemanticsActions = getSemanticsActions(listItems.length - 1);
lastSemanticsActions[moveLeft]();
await tester.pumpAndSettle();
expect(listItems, orderedEquals(<String>['Item 4', 'Item 1', 'Item 3', 'Item 2']));
handle.dispose();
});
testWidgets('Last item accessibility (a11y) actions work in Right-To-Left directionality', (WidgetTester tester) async {
// In RTL mode, the right is the start and the left is the end.
// The array representation is unchanged (LTR), but the direction of the motion actions is reversed.
final SemanticsHandle handle = tester.ensureSemantics();
expect(listItems, orderedEquals(originalListItems));
// Test out move to start: move Item 4 to the start of the list.
await tester.pumpWidget(build(scrollDirection: Axis.horizontal, textDirection: TextDirection.rtl));
Map<CustomSemanticsAction, VoidCallback> lastSemanticsActions = getSemanticsActions(listItems.length - 1);
lastSemanticsActions[moveToStart]();
await tester.pumpAndSettle();
expect(listItems, orderedEquals(<String>['Item 4', 'Item 1', 'Item 2', 'Item 3']));
// Test out move before: move Item 3 (the current last item) one space to the right.
await tester.pumpWidget(build(scrollDirection: Axis.horizontal, textDirection: TextDirection.rtl));
lastSemanticsActions = getSemanticsActions(listItems.length - 1);
lastSemanticsActions[moveRight]();
await tester.pumpAndSettle();
expect(listItems, orderedEquals(<String>['Item 4', 'Item 1', 'Item 3', 'Item 2']));
handle.dispose();
});
});
});
// TODO(djshuckerow): figure out how to write a test for scrolling the list.

View File

@@ -43,5 +43,11 @@
"popupMenuLabel": "قائمة منبثقة",
"dialogLabel": "مربع حوار",
"alertDialogLabel": "مربع حوار التنبيه",
"searchFieldLabel": "بحث"
"searchFieldLabel": "بحث",
"reorderItemToStart": "TBD",
"reorderItemToEnd": "TBD",
"reorderItemUp": "TBD",
"reorderItemDown": "TBD",
"reorderItemLeft": "TBD",
"reorderItemRight": "TBD"
}

View File

@@ -39,5 +39,11 @@
"popupMenuLabel": "Изскачащо меню",
"dialogLabel": "Диалогов прозорец",
"alertDialogLabel": "TBD",
"searchFieldLabel": "TBD"
"searchFieldLabel": "TBD",
"reorderItemToStart": "TBD",
"reorderItemToEnd": "TBD",
"reorderItemUp": "TBD",
"reorderItemDown": "TBD",
"reorderItemLeft": "TBD",
"reorderItemRight": "TBD"
}

View File

@@ -40,5 +40,11 @@
"popupMenuLabel": "Skočni izbornik",
"dialogLabel": "Dijalog",
"alertDialogLabel": "TBD",
"searchFieldLabel": "TBD"
}
"searchFieldLabel": "TBD",
"reorderItemToStart": "TBD",
"reorderItemToEnd": "TBD",
"reorderItemUp": "TBD",
"reorderItemDown": "TBD",
"reorderItemLeft": "TBD",
"reorderItemRight": "TBD"
}

View File

@@ -39,5 +39,11 @@
"popupMenuLabel": "Menú emergent",
"dialogLabel": "Diàleg",
"alertDialogLabel": "TBD",
"searchFieldLabel": "TBD"
"searchFieldLabel": "TBD",
"reorderItemToStart": "TBD",
"reorderItemToEnd": "TBD",
"reorderItemUp": "TBD",
"reorderItemDown": "TBD",
"reorderItemLeft": "TBD",
"reorderItemRight": "TBD"
}

View File

@@ -41,5 +41,11 @@
"popupMenuLabel": "Vyskakovací nabídka",
"dialogLabel": "Dialogové okno",
"alertDialogLabel": "TBD",
"searchFieldLabel": "TBD"
"searchFieldLabel": "TBD",
"reorderItemToStart": "TBD",
"reorderItemToEnd": "TBD",
"reorderItemUp": "TBD",
"reorderItemDown": "TBD",
"reorderItemLeft": "TBD",
"reorderItemRight": "TBD"
}

View File

@@ -39,5 +39,11 @@
"popupMenuLabel": "Pop op-menu",
"dialogLabel": "Dialogboks",
"alertDialogLabel": "TBD",
"searchFieldLabel": "TBD"
"searchFieldLabel": "TBD",
"reorderItemToStart": "TBD",
"reorderItemToEnd": "TBD",
"reorderItemUp": "TBD",
"reorderItemDown": "TBD",
"reorderItemLeft": "TBD",
"reorderItemRight": "TBD"
}

View File

@@ -40,5 +40,11 @@
"popupMenuLabel": "Pop-up-Menü",
"dialogLabel": "Dialogfeld",
"alertDialogLabel": "Aufmerksam",
"searchFieldLabel": "Suchen"
"searchFieldLabel": "Suchen",
"reorderItemToStart": "TBD",
"reorderItemToEnd": "TBD",
"reorderItemUp": "TBD",
"reorderItemDown": "TBD",
"reorderItemLeft": "TBD",
"reorderItemRight": "TBD"
}

View File

@@ -39,5 +39,11 @@
"popupMenuLabel": "Pop-up-Menü",
"dialogLabel": "Dialogfeld",
"alertDialogLabel": "Aufmerksam",
"searchFieldLabel": "Suchen"
"searchFieldLabel": "Suchen",
"reorderItemToStart": "TBD",
"reorderItemToEnd": "TBD",
"reorderItemUp": "TBD",
"reorderItemDown": "TBD",
"reorderItemLeft": "TBD",
"reorderItemRight": "TBD"
}

View File

@@ -39,5 +39,11 @@
"popupMenuLabel": "Αναδυόμενο μενού",
"dialogLabel": "Παράθυρο διαλόγου",
"alertDialogLabel": "TBD",
"searchFieldLabel": "TBD"
"searchFieldLabel": "TBD",
"reorderItemToStart": "TBD",
"reorderItemToEnd": "TBD",
"reorderItemUp": "TBD",
"reorderItemDown": "TBD",
"reorderItemLeft": "TBD",
"reorderItemRight": "TBD"
}

View File

@@ -205,5 +205,35 @@
"searchFieldLabel": "Search",
"@searchFieldLabel": {
"description": "Label indicating that a text field is a search field. This will be used as a hint text in the text field."
},
"reorderItemToStart": "Move to the start",
"@reorderItemToStart": {
"description": "The audio announcement to move an item in a Reorderable List to the start of the list."
},
"reorderItemToEnd": "Move to the end",
"@reorderItemToEnd": {
"description": "The audio announcement to move an item in a Reorderable List to the end of the list."
},
"reorderItemUp": "Move up",
"@reorderItemUp": {
"description": "The audio announcement to move an item in a Reorderable List up in the list when it is oriented vertically."
},
"reorderItemDown": "Move down",
"@reorderItemDown": {
"description": "The audio announcement to move an item in a Reorderable List down in the list when it is oriented vertically."
},
"reorderItemLeft": "Move left",
"@reorderItemLeft": {
"description": "The audio announcement to move an item in a Reorderable List left in the list when it is oriented horizontally."
},
"reorderItemRight": "Move right",
"@reorderItemRight": {
"description": "The audio announcement to move an item in a Reorderable List right in the list when it is oriented horizontally."
}
}

View File

@@ -39,5 +39,11 @@
"popupMenuLabel": "Pop-up menu",
"dialogLabel": "Dialogue",
"alertDialogLabel": "Alert",
"searchFieldLabel": "Search"
"searchFieldLabel": "Search",
"reorderItemToStart": "Move to the start",
"reorderItemToEnd": "Move to the end",
"reorderItemUp": "Move up",
"reorderItemDown": "Move down",
"reorderItemLeft": "Move left",
"reorderItemRight": "Move right"
}

View File

@@ -39,5 +39,11 @@
"popupMenuLabel": "Pop-up menu",
"dialogLabel": "Dialogue",
"alertDialogLabel": "Alert",
"searchFieldLabel": "Search"
"searchFieldLabel": "Search",
"reorderItemToStart": "Move to the start",
"reorderItemToEnd": "Move to the end",
"reorderItemUp": "Move up",
"reorderItemDown": "Move down",
"reorderItemLeft": "Move left",
"reorderItemRight": "Move right"
}

View File

@@ -39,5 +39,11 @@
"popupMenuLabel": "Pop-up menu",
"dialogLabel": "Dialogue",
"alertDialogLabel": "Alert",
"searchFieldLabel": "Search"
"searchFieldLabel": "Search",
"reorderItemToStart": "Move to the start",
"reorderItemToEnd": "Move to the end",
"reorderItemUp": "Move up",
"reorderItemDown": "Move down",
"reorderItemLeft": "Move left",
"reorderItemRight": "Move right"
}

View File

@@ -39,5 +39,11 @@
"popupMenuLabel": "Pop-up menu",
"dialogLabel": "Dialogue",
"alertDialogLabel": "Alert",
"searchFieldLabel": "Search"
"searchFieldLabel": "Search",
"reorderItemToStart": "Move to the start",
"reorderItemToEnd": "Move to the end",
"reorderItemUp": "Move up",
"reorderItemDown": "Move down",
"reorderItemLeft": "Move left",
"reorderItemRight": "Move right"
}

View File

@@ -39,5 +39,11 @@
"popupMenuLabel": "Pop-up menu",
"dialogLabel": "Dialogue",
"alertDialogLabel": "Alert",
"searchFieldLabel": "Search"
"searchFieldLabel": "Search",
"reorderItemToStart": "Move to the start",
"reorderItemToEnd": "Move to the end",
"reorderItemUp": "Move up",
"reorderItemDown": "Move down",
"reorderItemLeft": "Move left",
"reorderItemRight": "Move right"
}

View File

@@ -39,5 +39,11 @@
"popupMenuLabel": "Pop-up menu",
"dialogLabel": "Dialogue",
"alertDialogLabel": "Alert",
"searchFieldLabel": "Search"
"searchFieldLabel": "Search",
"reorderItemToStart": "Move to the start",
"reorderItemToEnd": "Move to the end",
"reorderItemUp": "Move up",
"reorderItemDown": "Move down",
"reorderItemLeft": "Move left",
"reorderItemRight": "Move right"
}

View File

@@ -39,5 +39,11 @@
"popupMenuLabel": "Pop-up menu",
"dialogLabel": "Dialogue",
"alertDialogLabel": "Alert",
"searchFieldLabel": "Search"
"searchFieldLabel": "Search",
"reorderItemToStart": "Move to the start",
"reorderItemToEnd": "Move to the end",
"reorderItemUp": "Move up",
"reorderItemDown": "Move down",
"reorderItemLeft": "Move left",
"reorderItemRight": "Move right"
}

View File

@@ -40,5 +40,11 @@
"popupMenuLabel": "Menú emergente",
"dialogLabel": "Cuadro de diálogo",
"alertDialogLabel": "Alerta",
"searchFieldLabel": "Buscar"
"searchFieldLabel": "Buscar",
"reorderItemToStart": "TBD",
"reorderItemToEnd": "TBD",
"reorderItemUp": "TBD",
"reorderItemDown": "TBD",
"reorderItemLeft": "TBD",
"reorderItemRight": "TBD"
}

View File

@@ -39,5 +39,11 @@
"popupMenuLabel": "Menú emergente",
"dialogLabel": "Diálogo",
"alertDialogLabel": "Alerta",
"searchFieldLabel": "Buscar"
"searchFieldLabel": "Buscar",
"reorderItemToStart": "TBD",
"reorderItemToEnd": "TBD",
"reorderItemUp": "TBD",
"reorderItemDown": "TBD",
"reorderItemLeft": "TBD",
"reorderItemRight": "TBD"
}

View File

@@ -39,5 +39,11 @@
"popupMenuLabel": "Menú emergente",
"dialogLabel": "Diálogo",
"alertDialogLabel": "Alerta",
"searchFieldLabel": "Buscar"
"searchFieldLabel": "Buscar",
"reorderItemToStart": "TBD",
"reorderItemToEnd": "TBD",
"reorderItemUp": "TBD",
"reorderItemDown": "TBD",
"reorderItemLeft": "TBD",
"reorderItemRight": "TBD"
}

View File

@@ -39,5 +39,11 @@
"popupMenuLabel": "Hüpikmenüü",
"dialogLabel": "Dialoog",
"alertDialogLabel": "TBD",
"searchFieldLabel": "TBD"
"searchFieldLabel": "TBD",
"reorderItemToStart": "TBD",
"reorderItemToEnd": "TBD",
"reorderItemUp": "TBD",
"reorderItemDown": "TBD",
"reorderItemLeft": "TBD",
"reorderItemRight": "TBD"
}

View File

@@ -39,5 +39,11 @@
"popupMenuLabel": "منوی بازشو",
"dialogLabel": "کادر گفتگو",
"alertDialogLabel": "هشدار",
"searchFieldLabel": "جستجو کردن"
"searchFieldLabel": "جستجو کردن",
"reorderItemToStart": "TBD",
"reorderItemToEnd": "TBD",
"reorderItemUp": "TBD",
"reorderItemDown": "TBD",
"reorderItemLeft": "TBD",
"reorderItemRight": "TBD"
}

View File

@@ -39,5 +39,11 @@
"popupMenuLabel": "Ponnahdusvalikko",
"dialogLabel": "Valintaikkuna",
"alertDialogLabel": "TBD",
"searchFieldLabel": "TBD"
"searchFieldLabel": "TBD",
"reorderItemToStart": "TBD",
"reorderItemToEnd": "TBD",
"reorderItemUp": "TBD",
"reorderItemDown": "TBD",
"reorderItemLeft": "TBD",
"reorderItemRight": "TBD"
}

View File

@@ -39,5 +39,11 @@
"popupMenuLabel": "Popup na menu",
"dialogLabel": "Dialog",
"alertDialogLabel": "TBD",
"searchFieldLabel": "TBD"
"searchFieldLabel": "TBD",
"reorderItemToStart": "TBD",
"reorderItemToEnd": "TBD",
"reorderItemUp": "TBD",
"reorderItemDown": "TBD",
"reorderItemLeft": "TBD",
"reorderItemRight": "TBD"
}

View File

@@ -40,5 +40,11 @@
"popupMenuLabel": "Menu contextuel",
"dialogLabel": "Boîte de dialogue",
"alertDialogLabel": "Alerte",
"searchFieldLabel": "Chercher"
"searchFieldLabel": "Chercher",
"reorderItemToStart": "TBD",
"reorderItemToEnd": "TBD",
"reorderItemUp": "TBD",
"reorderItemDown": "TBD",
"reorderItemLeft": "TBD",
"reorderItemRight": "TBD"
}

View File

@@ -39,5 +39,11 @@
"popupMenuLabel": "Pop-up-Menü",
"dialogLabel": "Dialogfeld",
"alertDialogLabel": "Aufmerksam",
"searchFieldLabel": "Suchen"
"searchFieldLabel": "Suchen",
"reorderItemToStart": "TBD",
"reorderItemToEnd": "TBD",
"reorderItemUp": "TBD",
"reorderItemDown": "TBD",
"reorderItemLeft": "TBD",
"reorderItemRight": "TBD"
}

View File

@@ -41,5 +41,11 @@
"popupMenuLabel": "תפריט קופץ",
"dialogLabel": "תיבת דו-שיח",
"alertDialogLabel": "עֵרָנִי",
"searchFieldLabel": "לחפש"
"searchFieldLabel": "לחפש",
"reorderItemToStart": "TBD",
"reorderItemToEnd": "TBD",
"reorderItemUp": "TBD",
"reorderItemDown": "TBD",
"reorderItemLeft": "TBD",
"reorderItemRight": "TBD"
}

View File

@@ -39,5 +39,11 @@
"popupMenuLabel": "पॉपअप मेन्यू",
"dialogLabel": "संवाद",
"alertDialogLabel": "TBD",
"searchFieldLabel": "TBD"
"searchFieldLabel": "TBD",
"reorderItemToStart": "TBD",
"reorderItemToEnd": "TBD",
"reorderItemUp": "TBD",
"reorderItemDown": "TBD",
"reorderItemLeft": "TBD",
"reorderItemRight": "TBD"
}

View File

@@ -40,5 +40,11 @@
"popupMenuLabel": "Skočni izbornik",
"dialogLabel": "Dijalog",
"alertDialogLabel": "TBD",
"searchFieldLabel": "TBD"
"searchFieldLabel": "TBD",
"reorderItemToStart": "TBD",
"reorderItemToEnd": "TBD",
"reorderItemUp": "TBD",
"reorderItemDown": "TBD",
"reorderItemLeft": "TBD",
"reorderItemRight": "TBD"
}

View File

@@ -39,5 +39,11 @@
"popupMenuLabel": "Előugró menü",
"dialogLabel": "Párbeszédablak",
"alertDialogLabel": "TBD",
"searchFieldLabel": "TBD"
"searchFieldLabel": "TBD",
"reorderItemToStart": "TBD",
"reorderItemToEnd": "TBD",
"reorderItemUp": "TBD",
"reorderItemDown": "TBD",
"reorderItemLeft": "TBD",
"reorderItemRight": "TBD"
}

View File

@@ -39,5 +39,11 @@
"popupMenuLabel": "Menu pop-up",
"dialogLabel": "Dialog",
"alertDialogLabel": "Waspada",
"searchFieldLabel": "Pencarian"
"searchFieldLabel": "Pencarian",
"reorderItemToStart": "TBD",
"reorderItemToEnd": "TBD",
"reorderItemUp": "TBD",
"reorderItemDown": "TBD",
"reorderItemLeft": "TBD",
"reorderItemRight": "TBD"
}

View File

@@ -39,5 +39,11 @@
"popupMenuLabel": "Menu popup",
"dialogLabel": "Finestra di dialogo",
"alertDialogLabel": "Mettere in guardia",
"searchFieldLabel": "Ricerca"
"searchFieldLabel": "Ricerca",
"reorderItemToStart": "TBD",
"reorderItemToEnd": "TBD",
"reorderItemUp": "TBD",
"reorderItemDown": "TBD",
"reorderItemLeft": "TBD",
"reorderItemRight": "TBD"
}

View File

@@ -39,5 +39,11 @@
"popupMenuLabel": "ポップアップ メニュー",
"dialogLabel": "ダイアログ",
"alertDialogLabel": "アラート",
"searchFieldLabel": "サーチ"
"searchFieldLabel": "サーチ",
"reorderItemToStart": "TBD",
"reorderItemToEnd": "TBD",
"reorderItemUp": "TBD",
"reorderItemDown": "TBD",
"reorderItemLeft": "TBD",
"reorderItemRight": "TBD"
}

View File

@@ -39,5 +39,11 @@
"popupMenuLabel": "팝업 메뉴",
"dialogLabel": "대화상자",
"alertDialogLabel": "경보",
"searchFieldLabel": "수색"
"searchFieldLabel": "수색",
"reorderItemToStart": "TBD",
"reorderItemToEnd": "TBD",
"reorderItemUp": "TBD",
"reorderItemDown": "TBD",
"reorderItemLeft": "TBD",
"reorderItemRight": "TBD"
}

View File

@@ -41,5 +41,11 @@
"popupMenuLabel": "Iššokantysis meniu",
"dialogLabel": "Dialogo langas",
"alertDialogLabel": "TBD",
"searchFieldLabel": "TBD"
"searchFieldLabel": "TBD",
"reorderItemToStart": "TBD",
"reorderItemToEnd": "TBD",
"reorderItemUp": "TBD",
"reorderItemDown": "TBD",
"reorderItemLeft": "TBD",
"reorderItemRight": "TBD"
}

View File

@@ -40,5 +40,11 @@
"popupMenuLabel": "Uznirstošā izvēlne",
"dialogLabel": "Dialoglodziņš",
"alertDialogLabel": "TBD",
"searchFieldLabel": "TBD"
"searchFieldLabel": "TBD",
"reorderItemToStart": "TBD",
"reorderItemToEnd": "TBD",
"reorderItemUp": "TBD",
"reorderItemDown": "TBD",
"reorderItemLeft": "TBD",
"reorderItemRight": "TBD"
}

View File

@@ -40,5 +40,11 @@
"popupMenuLabel": "Menu pop timbul",
"dialogLabel": "Dialog",
"alertDialogLabel": "Amaran",
"searchFieldLabel": "Carian"
"searchFieldLabel": "Carian",
"reorderItemToStart": "TBD",
"reorderItemToEnd": "TBD",
"reorderItemUp": "TBD",
"reorderItemDown": "TBD",
"reorderItemLeft": "TBD",
"reorderItemRight": "TBD"
}

View File

@@ -39,5 +39,11 @@
"popupMenuLabel": "Forgrunnsmeny",
"dialogLabel": "Dialogboks",
"alertDialogLabel": "Varsling",
"searchFieldLabel": "Søke"
"searchFieldLabel": "Søke",
"reorderItemToStart": "TBD",
"reorderItemToEnd": "TBD",
"reorderItemUp": "TBD",
"reorderItemDown": "TBD",
"reorderItemLeft": "TBD",
"reorderItemRight": "TBD"
}

View File

@@ -39,5 +39,11 @@
"popupMenuLabel": "Pop-upmenu",
"dialogLabel": "Dialoogvenster",
"alertDialogLabel": "Alarm",
"searchFieldLabel": "Zoeken"
"searchFieldLabel": "Zoeken",
"reorderItemToStart": "TBD",
"reorderItemToEnd": "TBD",
"reorderItemUp": "TBD",
"reorderItemDown": "TBD",
"reorderItemLeft": "TBD",
"reorderItemRight": "TBD"
}

View File

@@ -41,5 +41,11 @@
"popupMenuLabel": "Wyskakujące menu",
"dialogLabel": "Okno dialogowe",
"alertDialogLabel": "Alarm",
"searchFieldLabel": "Szukaj"
"searchFieldLabel": "Szukaj",
"reorderItemToStart": "TBD",
"reorderItemToEnd": "TBD",
"reorderItemUp": "TBD",
"reorderItemDown": "TBD",
"reorderItemLeft": "TBD",
"reorderItemRight": "TBD"
}

View File

@@ -38,5 +38,11 @@
"popupMenuLabel": "د پاپ اپ مینو",
"dialogLabel": "خبرې اترې",
"alertDialogLabel": "خبرتیا",
"searchFieldLabel": "لټون"
"searchFieldLabel": "لټون",
"reorderItemToStart": "TBD",
"reorderItemToEnd": "TBD",
"reorderItemUp": "TBD",
"reorderItemDown": "TBD",
"reorderItemLeft": "TBD",
"reorderItemRight": "TBD"
}

View File

@@ -41,5 +41,11 @@
"popupMenuLabel": "Menu pop-up",
"dialogLabel": "Caixa de diálogo",
"alertDialogLabel": "Alerta",
"searchFieldLabel": "Pesquisa"
"searchFieldLabel": "Pesquisa",
"reorderItemToStart": "TBD",
"reorderItemToEnd": "TBD",
"reorderItemUp": "TBD",
"reorderItemDown": "TBD",
"reorderItemLeft": "TBD",
"reorderItemRight": "TBD"
}

View File

@@ -39,5 +39,11 @@
"popupMenuLabel": "Menu pop-up",
"dialogLabel": "Caixa de diálogo",
"alertDialogLabel": "Alerta",
"searchFieldLabel": "Pesquisa"
"searchFieldLabel": "Pesquisa",
"reorderItemToStart": "TBD",
"reorderItemToEnd": "TBD",
"reorderItemUp": "TBD",
"reorderItemDown": "TBD",
"reorderItemLeft": "TBD",
"reorderItemRight": "TBD"
}

View File

@@ -41,5 +41,11 @@
"popupMenuLabel": "Meniu pop-up",
"dialogLabel": "Casetă de dialog",
"alertDialogLabel": "Alerta",
"searchFieldLabel": "Căutare"
"searchFieldLabel": "Căutare",
"reorderItemToStart": "TBD",
"reorderItemToEnd": "TBD",
"reorderItemUp": "TBD",
"reorderItemDown": "TBD",
"reorderItemLeft": "TBD",
"reorderItemRight": "TBD"
}

View File

@@ -42,5 +42,11 @@
"popupMenuLabel": "Всплывающее меню",
"dialogLabel": "Диалоговое окно",
"alertDialogLabel": "бдительный",
"searchFieldLabel": "Поиск"
"searchFieldLabel": "Поиск",
"reorderItemToStart": "TBD",
"reorderItemToEnd": "TBD",
"reorderItemUp": "TBD",
"reorderItemDown": "TBD",
"reorderItemLeft": "TBD",
"reorderItemRight": "TBD"
}

View File

@@ -41,5 +41,11 @@
"popupMenuLabel": "Kontextová ponuka",
"dialogLabel": "Dialógové okno",
"alertDialogLabel": "TBD",
"searchFieldLabel": "TBD"
"searchFieldLabel": "TBD",
"reorderItemToStart": "TBD",
"reorderItemToEnd": "TBD",
"reorderItemUp": "TBD",
"reorderItemDown": "TBD",
"reorderItemLeft": "TBD",
"reorderItemRight": "TBD"
}

View File

@@ -41,5 +41,11 @@
"popupMenuLabel": "Pojavni meni",
"dialogLabel": "Pogovorno okno",
"alertDialogLabel": "TBD",
"searchFieldLabel": "TBD"
"searchFieldLabel": "TBD",
"reorderItemToStart": "TBD",
"reorderItemToEnd": "TBD",
"reorderItemUp": "TBD",
"reorderItemDown": "TBD",
"reorderItemLeft": "TBD",
"reorderItemRight": "TBD"
}

View File

@@ -40,5 +40,11 @@
"popupMenuLabel": "Искачући мени",
"dialogLabel": "Дијалог",
"alertDialogLabel": "TBD",
"searchFieldLabel": "TBD"
"searchFieldLabel": "TBD",
"reorderItemToStart": "TBD",
"reorderItemToEnd": "TBD",
"reorderItemUp": "TBD",
"reorderItemDown": "TBD",
"reorderItemLeft": "TBD",
"reorderItemRight": "TBD"
}

View File

@@ -40,5 +40,11 @@
"popupMenuLabel": "Iskačući meni",
"dialogLabel": "Dijalog",
"alertDialogLabel": "TBD",
"searchFieldLabel": "TBD"
"searchFieldLabel": "TBD",
"reorderItemToStart": "TBD",
"reorderItemToEnd": "TBD",
"reorderItemUp": "TBD",
"reorderItemDown": "TBD",
"reorderItemLeft": "TBD",
"reorderItemRight": "TBD"
}

View File

@@ -39,5 +39,11 @@
"popupMenuLabel": "Popup-meny",
"dialogLabel": "Dialogruta",
"alertDialogLabel": "TBD",
"searchFieldLabel": "TBD"
"searchFieldLabel": "TBD",
"reorderItemToStart": "TBD",
"reorderItemToEnd": "TBD",
"reorderItemUp": "TBD",
"reorderItemDown": "TBD",
"reorderItemLeft": "TBD",
"reorderItemRight": "TBD"
}

View File

@@ -39,5 +39,11 @@
"popupMenuLabel": "เมนูป๊อปอัป",
"dialogLabel": "กล่องโต้ตอบ",
"alertDialogLabel": "เตือนภัย",
"searchFieldLabel": "ค้นหา"
"searchFieldLabel": "ค้นหา",
"reorderItemToStart": "TBD",
"reorderItemToEnd": "TBD",
"reorderItemUp": "TBD",
"reorderItemDown": "TBD",
"reorderItemLeft": "TBD",
"reorderItemRight": "TBD"
}

View File

@@ -39,5 +39,11 @@
"popupMenuLabel": "Popup na menu",
"dialogLabel": "Dialog",
"alertDialogLabel": "TBD",
"searchFieldLabel": "TBD"
"searchFieldLabel": "TBD",
"reorderItemToStart": "TBD",
"reorderItemToEnd": "TBD",
"reorderItemUp": "TBD",
"reorderItemDown": "TBD",
"reorderItemLeft": "TBD",
"reorderItemRight": "TBD"
}

View File

@@ -39,5 +39,11 @@
"popupMenuLabel": "Popup menü",
"dialogLabel": "İletişim kutusu",
"alertDialogLabel": "Alarm",
"searchFieldLabel": "Arama"
"searchFieldLabel": "Arama",
"reorderItemToStart": "TBD",
"reorderItemToEnd": "TBD",
"reorderItemUp": "TBD",
"reorderItemDown": "TBD",
"reorderItemLeft": "TBD",
"reorderItemRight": "TBD"
}

View File

@@ -41,5 +41,11 @@
"popupMenuLabel": "Спливаюче меню",
"dialogLabel": "Вікно",
"alertDialogLabel": "TBD",
"searchFieldLabel": "TBD"
"searchFieldLabel": "TBD",
"reorderItemToStart": "TBD",
"reorderItemToEnd": "TBD",
"reorderItemUp": "TBD",
"reorderItemDown": "TBD",
"reorderItemLeft": "TBD",
"reorderItemRight": "TBD"
}

View File

@@ -39,5 +39,11 @@
"popupMenuLabel": "پاپ اپ مینو",
"dialogLabel": "ڈائلاگ",
"alertDialogLabel": "انتباہ",
"searchFieldLabel": "تلاش کریں"
"searchFieldLabel": "تلاش کریں",
"reorderItemToStart": "TBD",
"reorderItemToEnd": "TBD",
"reorderItemUp": "TBD",
"reorderItemDown": "TBD",
"reorderItemLeft": "TBD",
"reorderItemRight": "TBD"
}

View File

@@ -39,5 +39,11 @@
"popupMenuLabel": "Menu bật lên",
"dialogLabel": "Hộp thoại",
"alertDialogLabel": "Hộp thoại",
"searchFieldLabel": "Tìm kiếm"
"searchFieldLabel": "Tìm kiếm",
"reorderItemToStart": "TBD",
"reorderItemToEnd": "TBD",
"reorderItemUp": "TBD",
"reorderItemDown": "TBD",
"reorderItemLeft": "TBD",
"reorderItemRight": "TBD"
}

View File

@@ -39,5 +39,11 @@
"popupMenuLabel": "弹出菜单",
"dialogLabel": "对话框",
"alertDialogLabel": "警报",
"searchFieldLabel": "搜索"
"searchFieldLabel": "搜索",
"reorderItemToStart": "TBD",
"reorderItemToEnd": "TBD",
"reorderItemUp": "TBD",
"reorderItemDown": "TBD",
"reorderItemLeft": "TBD",
"reorderItemRight": "TBD"
}

View File

@@ -39,5 +39,11 @@
"popupMenuLabel": "彈出式選單",
"dialogLabel": "對話方塊",
"alertDialogLabel": "警报",
"searchFieldLabel": "搜索"
"searchFieldLabel": "搜索",
"reorderItemToStart": "TBD",
"reorderItemToEnd": "TBD",
"reorderItemUp": "TBD",
"reorderItemDown": "TBD",
"reorderItemLeft": "TBD",
"reorderItemRight": "TBD"
}

View File

@@ -39,5 +39,11 @@
"popupMenuLabel": "彈出式選單",
"dialogLabel": "對話方塊",
"alertDialogLabel": "警报",
"searchFieldLabel": "搜索"
"searchFieldLabel": "搜索",
"reorderItemToStart": "TBD",
"reorderItemToEnd": "TBD",
"reorderItemUp": "TBD",
"reorderItemDown": "TBD",
"reorderItemLeft": "TBD",
"reorderItemRight": "TBD"
}