Нет ничего более раздражающего, чем пытаться перемещаться по плохо спроектированному пользовательскому интерфейсу в мобильном приложении. То, как ваше приложение ведет себя с точки зрения навигации по экрану, может означать разницу между счастливым пользователем и тем, кто разжигает вас в Android Market. Сегодня мы фокусируемся на фокусе, а именно: на фокусе управления и на том, как его настроить в ваших пользовательских интерфейсах.
Способы ввода в Android-устройства становятся довольно разнообразными: направляющие, трекболы, сенсорные экраны, клавиатуры и многое другое. Некоторые устройства, такие как планшеты, в первую очередь ориентированы на прикосновение. Другие, такие как Google TV, не имеют сенсорного экрана и используют устройства ввода, такие как устройства с направленной панелью (d-pad).
Разработчики Android должны понимать, как пользователи перемещаются по элементам управления на экране, как и в каком порядке эти элементы управления экранами усиливаются и теряют фокус, а также как настраивать порядок фокусировки элементов управления для своих приложений, чтобы пользователи не испытывали разочарования.
Понимание Порядка Фокуса Управления
Платформа Android делает все возможное, чтобы определить соответствующий порядок управления для данного типа макета. Во многих случаях порядок фокусировки по умолчанию имеет смысл. Тем не менее, это не всегда так. Какой элемент управления должен получить фокус следующий, определяется путем нахождения ближайшего соседа текущего элемента управления в заданном направлении (вверх / вниз / влево / вправо). Когда есть несколько элементов управления, которые соответствуют этому описанию, платформа сканирует слева направо, сверху вниз, почти так же, как можно было бы прочитать книгу на английском языке.
Это имеет некоторые последствия. По умолчанию верхнему элементу управления на экране будет нечего сосредоточиться, если пользователь нажмет «Вверх», и ничего не произойдет, если пользователь нажмет «Вниз» из нижнего элемента управления на экране. Точно так же ничего не произойдет, если пользователь попытается переместиться «влево» из крайнего левого элемента управления или «вправо» из крайнего правого элемента управления. По умолчанию «обтекание» фокуса отсутствует.
Теперь давайте рассмотрим пример того, как вы можете изменить стандартное поведение фокуса на экране и заставить его работать для вас и ваших пользователей. Например, допустим, вы хотите, чтобы ваш порядок фокусировки циклически оборачивался вокруг набора элементов управления, составляющих циферблат часов.
Шаг 0: Начало работы
Мы предоставляем полный исходный код для примера приложения, обсуждаемого в этом руководстве. Вы можете скачать образец исходного кода, который мы предоставляем для ознакомления здесь.
Шаг 1. Определите макет с помощью элементов управления
Сначала создайте или отредактируйте файл ресурсов макета, используемый вашим классом Activity, например /res/layout/main.xml. Например, следующий макет определяет своего рода «циферблат» элементов управления Button с использованием RelativeLayout.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
|
<?xml version=»1.0″ encoding=»utf-8″?>
<RelativeLayout
xmlns:android=»http://schemas.android.com/apk/res/android»
android:layout_width=»fill_parent»
android:layout_height=»fill_parent»>
<Button
style=»@style/clockFaceNum»
android:text=»12″
android:id=»@+id/button12″
android:layout_alignParentTop=»true»
android:layout_centerHorizontal=»true»>
</Button>
<Button
style=»@style/clockFaceNum»
android:text=»11″
android:id=»@+id/button11″
android:layout_below=»@+id/button12″
android:layout_toLeftOf=»@+id/button12″>
</Button>
<Button
style=»@style/clockFaceNum»
android:text=»1″
android:id=»@+id/button1″
android:layout_below=»@+id/button12″
android:layout_toRightOf=»@+id/button12″>
</Button>
<Button
style=»@style/clockFaceNum»
android:text=»10″
android:id=»@+id/button10″
android:layout_below=»@+id/button11″
android:layout_toLeftOf=»@+id/button11″>
</Button>
<Button
style=»@style/clockFaceNum»
android:text=»2″
android:id=»@+id/button2″
android:layout_below=»@+id/button1″
android:layout_toRightOf=»@+id/button1″>
</Button>
<Button
style=»@style/clockFaceNum»
android:text=»9″
android:id=»@+id/button9″
android:layout_below=»@+id/button10″
android:layout_toLeftOf=»@+id/button10″>
</Button>
<Button
style=»@style/clockFaceNum»
android:text=»3″
android:id=»@+id/button3″
android:layout_below=»@+id/button2″
android:layout_toRightOf=»@+id/button2″>
</Button>
<Button
style=»@style/clockFaceNum»
android:text=»8″
android:id=»@+id/button8″
android:layout_below=»@+id/button9″
android:layout_toRightOf=»@+id/button9″>
</Button>
<Button
style=»@style/clockFaceNum»
android:text=»4″
android:id=»@+id/button4″
android:layout_below=»@+id/button3″
android:layout_toLeftOf=»@+id/button3″>
</Button>
<Button
style=»@style/clockFaceNum»
android:text=»7″
android:id=»@+id/button7″
android:layout_below=»@+id/button8″
android:layout_toRightOf=»@+id/button8″>
</Button>
<Button
style=»@style/clockFaceNum»
android:text=»5″
android:id=»@+id/button5″
android:layout_below=»@+id/button4″
android:layout_toLeftOf=»@+id/button4″>
</Button>
<Button
style=»@style/clockFaceNum»
android:text=»6″
android:id=»@+id/button6″
android:layout_below=»@+id/button5″
android:layout_centerHorizontal=»true»>
</Button>
</RelativeLayout>
|
Стиль с именем clockFaceNum определен в файле /res/values/styles.xml следующим образом:
<? xml version = "1.0" encoding = "utf-8"?> <ресурсы> <стиль имя = "clockFaceNum"> <пункт имя = "андроид: layout_width"> 38dp </ элемент> <пункт имя = "Android: layout_height"> 38dp </ пункт> <пункт имя = "андроид: OnClick"> numClicked </ элемент> <пункт имя = "андроид: TextSize"> 9sp </ элемент> </ Стиль> </ Ресурсы>
Получившийся экран выглядит так:
Шаг 2. Просмотр порядка фокусировки по умолчанию
Давайте рассмотрим порядок фокусировки по умолчанию для элементов управления Button на циферблате в этом RelativeLayout. Если пользователь сфокусирован на кнопке 12 и нажимает «вниз» на клавиатуре направления, следующим элементом управления для фокусировки будет кнопка 11, затем кнопка 10 и т. Д.
Путь «вниз» по умолчанию показан здесь:
Шаг 3. Предоставление пользовательского элемента управления порядком фокусировки
Допустим, мы хотим, чтобы пользователь мог перемещаться по элементам управления циферблатом только по часовой стрелке или против часовой стрелки, а не по умолчанию, как показано:
Мы можем определить это поведение, указав для каждой кнопки, какой элемент управления должен получить следующий фокус. Существует четыре атрибута XML, которые вы можете установить в любом элементе управления View для определения порядка фокусировки. Эти атрибуты:
- android: nextFocusUp-Этот атрибут определяет элемент управления, который должен получить фокус, если пользователь перемещается вверх
- android: nextFocusDown-Этот атрибут определяет элемент управления, который должен получить фокус, если пользователь перемещается вниз
- android: nextFocusLeft-Этот атрибут определяет элемент управления, который должен получить фокус, если пользователь перемещается влево
- android: nextFocusRight-Этот атрибут определяет элемент управления, который должен получить фокус, если пользователь перемещается вправо
Допустим, мы хотим, чтобы вся навигация «Вниз» и «Вправо» позволяла пользователю перемещаться по часовой стрелке, а элементы управления «Кнопка» — по часовой стрелке, а вся навигация «Вверх» и «Влево» позволяла пользователю перемещаться по элементам управления в противоположную сторону. по часовой стрелке Затем мы должны были бы определить эти четыре атрибута для каждого элемента управления. Например, если вы переместили «Вниз» или «Вправо» из 12 кнопок, вы бы достигли 1 кнопки. Точно так же, если вы переместились «вверх» или «влево» от кнопки 12, вы бы достигли кнопки 11.
Полное определение этого нового расположения циферблата выглядит следующим образом:
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
|
<?xml version=»1.0″ encoding=»utf-8″?>
<RelativeLayout
xmlns:android=»http://schemas.android.com/apk/res/android»
android:layout_width=»fill_parent»
android:layout_height=»fill_parent»>
<Button
style=»@style/clockFaceNum»
android:text=»12″
android:id=»@+id/button12″
android:layout_alignParentTop=»true»
android:layout_centerHorizontal=»true»
android:nextFocusUp=»@+id/button11″
android:nextFocusLeft=»@+id/button11″
android:nextFocusRight=»@+id/button1″
android:nextFocusDown=»@+id/button1″>
</Button>
<Button
style=»@style/clockFaceNum»
android:text=»11″
android:id=»@+id/button11″
android:layout_below=»@+id/button12″
android:layout_toLeftOf=»@+id/button12″
android:nextFocusUp=»@+id/button10″
android:nextFocusLeft=»@+id/button10″
android:nextFocusRight=»@+id/button12″
android:nextFocusDown=»@+id/button12″>
</Button>
<Button
style=»@style/clockFaceNum»
android:text=»1″
android:id=»@+id/button1″
android:layout_below=»@+id/button12″
android:layout_toRightOf=»@+id/button12″
android:nextFocusUp=»@+id/button12″
android:nextFocusLeft=»@+id/button12″
android:nextFocusRight=»@+id/button2″
android:nextFocusDown=»@+id/button2″>
</Button>
<Button
style=»@style/clockFaceNum»
android:text=»10″
android:id=»@+id/button10″
android:layout_below=»@+id/button11″
android:layout_toLeftOf=»@+id/button11″
android:nextFocusUp=»@+id/button9″
android:nextFocusLeft=»@+id/button9″
android:nextFocusRight=»@+id/button11″
android:nextFocusDown=»@+id/button11″>
</Button>
<Button
style=»@style/clockFaceNum»
android:text=»2″
android:id=»@+id/button2″
android:layout_below=»@+id/button1″
android:layout_toRightOf=»@+id/button1″
android:nextFocusUp=»@+id/button1″
android:nextFocusLeft=»@+id/button1″
android:nextFocusRight=»@+id/button3″
android:nextFocusDown=»@+id/button3″>
</Button>
<Button
style=»@style/clockFaceNum»
android:text=»9″
android:id=»@+id/button9″
android:layout_below=»@+id/button10″
android:layout_toLeftOf=»@+id/button10″
android:nextFocusUp=»@+id/button8″
android:nextFocusLeft=»@+id/button8″
android:nextFocusRight=»@+id/button10″
android:nextFocusDown=»@+id/button10″>
</Button>
<Button
style=»@style/clockFaceNum»
android:text=»3″
android:id=»@+id/button3″
android:layout_below=»@+id/button2″
android:layout_toRightOf=»@+id/button2″
android:nextFocusUp=»@+id/button2″
android:nextFocusLeft=»@+id/button2″
android:nextFocusRight=»@+id/button4″
android:nextFocusDown=»@+id/button4″>
</Button>
<Button
style=»@style/clockFaceNum»
android:text=»8″
android:id=»@+id/button8″
android:layout_below=»@+id/button9″
android:layout_toRightOf=»@+id/button9″
android:nextFocusUp=»@+id/button7″
android:nextFocusLeft=»@+id/button7″
android:nextFocusRight=»@+id/button9″
android:nextFocusDown=»@+id/button9″>
</Button>
<Button
style=»@style/clockFaceNum»
android:text=»4″
android:id=»@+id/button4″
android:layout_below=»@+id/button3″
android:layout_toLeftOf=»@+id/button3″
android:nextFocusUp=»@+id/button3″
android:nextFocusLeft=»@+id/button3″
android:nextFocusRight=»@+id/button5″
android:nextFocusDown=»@+id/button5″>
</Button>
<Button
style=»@style/clockFaceNum»
android:text=»7″
android:id=»@+id/button7″
android:layout_below=»@+id/button8″
android:layout_toRightOf=»@+id/button8″
android:nextFocusUp=»@+id/button6″
android:nextFocusLeft=»@+id/button6″
android:nextFocusRight=»@+id/button8″
android:nextFocusDown=»@+id/button8″>
</Button>
<Button
style=»@style/clockFaceNum»
android:text=»5″
android:id=»@+id/button5″
android:layout_below=»@+id/button4″
android:layout_toLeftOf=»@+id/button4″
android:nextFocusUp=»@+id/button4″
android:nextFocusLeft=»@+id/button4″
android:nextFocusRight=»@+id/button6″
android:nextFocusDown=»@+id/button6″>
</Button>
<Button
style=»@style/clockFaceNum»
android:text=»6″
android:id=»@+id/button6″
android:layout_below=»@+id/button5″
android:layout_centerHorizontal=»true»
android:nextFocusUp=»@+id/button5″
android:nextFocusLeft=»@+id/button5″
android:nextFocusRight=»@+id/button7″
android:nextFocusDown=»@+id/button7″>
</Button>
</RelativeLayout>
|
Поэтому наш новый путь «вниз», начинающийся с 12-й кнопки, теперь выглядит следующим образом:
Шаг 4: Установка начального контрольного фокуса
Наконец, вот трюк для установки элемента управления по умолчанию, чтобы получить фокус на заданном экране из вашего файла макета. Вы можете сделать это только для одного элемента управления View в каждом файле.
Используйте тег в элементе управления View, чтобы установить начальный фокус на экране. Например, мы могли бы хотеть обновить 12 Кнопок, чтобы получить начальный фокус, как это:
01
02
03
04
05
06
07
08
09
10
11
12
|
<Button
style=»@style/clockFaceNum»
android:text=»12″
android:id=»@+id/button12″
android:layout_alignParentTop=»true»
android:layout_centerHorizontal=»true»
android:nextFocusUp=»@+id/button11″
android:nextFocusLeft=»@+id/button11″
android:nextFocusRight=»@+id/button1″
android:nextFocusDown=»@+id/button1″>
<requestFocus />
</Button>
|
Конечно, вы также можете использовать программный метод для установки фокуса управления, используя метод класса View, называемый requestFocus ().
Вывод
Разработчики Android должны помнить, что разные пользователи будут перемещаться по пользовательскому интерфейсу приложения, используя разные методы ввода. Некоторые методы позволяют легко переключаться между элементами управления экрана, в то время как другие могут усложнять навигацию. Разработчики могут предоставить индивидуальные заказы на фокусировку, которые могут значительно улучшить взаимодействие пользователя с приложением. Пожалуйста, не забывайте о пользователях клавиатуры. ☺
Об авторах
Разработчики мобильных приложений Лорен Дарси и Шейн Кондер являются соавторами нескольких книг по разработке Android: углубленная книга по программированию под названием « Разработка беспроводных приложений для Android, второе издание» и « Самс научи себя разработке приложений для Android за 24 часа, второе издание» . Когда они не пишут, они тратят свое время на разработку мобильного программного обеспечения в своей компании и оказание консультационных услуг. С ними можно связаться по электронной почте [email protected] , через их блог на androidbook.blogspot.com и в Twitter @androidwireless .