• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1page.title=События ввода
2parent.title=Пользовательский интерфейс
3parent.link=index.html
4@jd:body
5
6<div id="qv-wrapper">
7<div id="qv">
8  <h2>Содержание документа</h2>
9  <ol>
10    <li><a href="#EventListeners">Приемники событий</a></li>
11    <li><a href="#EventHandlers">Обработчики событий</a></li>
12    <li><a href="#TouchMode">Режим касания</a></li>
13    <li><a href="#HandlingFocus">Фокус обработки</a></li>
14  </ol>
15
16</div>
17</div>
18
19<p>В системе Android предусмотрено несколько способов перехвата событий взаимодействия пользователя с вашим приложением.
20Что касается событий в пользовательском интерфейсе, подход состоит в том, чтобы захватывать события из
21определенного представления объекта, с которым взаимодействует пользователь. Класс отображаемых объектов (View) содержит средства, позволяющие делать это.</p>
22
23<p>В различных классах View, которые вы будете использовать для создания макета, вы заметите несколько общедоступных методов обратного вызова,
24полезных для работы с событиями пользовательского интерфейса. Эти методы вызываются платформой Android, когда
25с этим объектом выполняется соответствующее действие. Например, когда пользователь касается отображаемого объекта (кнопки),
26вызывается метод <code>onTouchEvent()</code> этого объекта. Однако для перехвата этого события вы должны
27наследовать класс и переопределить метод. Однако наследование каждого отображаемого объекта
28для обработки такого события было бы неудобно. Именно поэтому класс View также содержит
29набор вложенных интерфейсов с обратными вызовами, которые можно задать значительно проще. Эти интерфейсы,
30которые называются <a href="#EventListeners">приемниками событий</a>, и служат перехватчиками действий пользователя с вашим пользовательским интерфейсом.</p>
31
32<p>Несмотря на то, что вы будете чаще использовать приемники событий для перехвата действий пользователя, может
33наступить момент, когда вам не захочется наследовать класс View, чтобы создать нестандартный компонент.
34Возможно, вы захотите наследовать класс {@link android.widget.Button},
35чтобы сделать нечто более необычное. В этом случае вы сможете определить поведение события по умолчанию для своего
36класса с помощью <a href="#EventHandlers">обработчиков событий</a> класса.</p>
37
38
39<h2 id="EventListeners">Приемники событий</h2>
40
41<p>Приемник событий — это интерфейс в классе {@link android.view.View}, который содержит один
42метод обратного вызова. Эти методы будут вызываться платформой Android, когда в результате взаимодействия пользователя с объектом
43пользовательского интерфейса срабатывает отображаемый объект View, в котором зарегистрирован приемник.</p>
44
45<p>Интерфейсы, включенные в приемник события, представляют собой следующие методы обратного вызова:</p>
46
47<dl>
48  <dt><code>onClick()</code></dt>
49    <dd>Из объекта {@link android.view.View.OnClickListener}.
50 Этот метод вызывается, когда пользователь касается элемента
51 (в режиме касания), или переводит фокус на элемент с помощью клавиш перемещения или трекбола и
52нажимает соответствующую клавишу «ввода» или нажимает на трекбол.</dd>
53  <dt><code>onLongClick()</code></dt>
54    <dd>Из объекта {@link android.view.View.OnLongClickListener}.
55 Этот метод вызывается, когда пользователь касается элемента и удерживает его (в режиме касания),
56или переводит фокус на элемент с помощью клавиш перемещения или трекбола и
57нажимает и удерживает соответствующую клавишу «ввода» или трекбол (в течение одной секунды).</dd>
58  <dt><code>onFocusChange()</code></dt>
59    <dd>Из объекта {@link android.view.View.OnFocusChangeListener}.
60 Этот метод вызывается, когда пользователь перемещается в элемент или из него с помощью клавиш перемещения или трекбола.</dd>
61  <dt><code>onKey()</code></dt>
62    <dd>Из объекта {@link android.view.View.OnKeyListener}.
63 Этот метод вызывается, когда пользователь переносит фокус на элемент и нажимает или отпускает аппаратную клавишу на устройстве.</dd>
64  <dt><code>onTouch()</code></dt>
65    <dd>Из объекта {@link android.view.View.OnTouchListener}.
66 Этот метод вызывается, когда пользователь выполняет действие, считающееся событием касания, например, нажимает, отпускает
67или выполняет любой жест на экране (в пределах границ элемента).</dd>
68  <dt><code>onCreateContextMenu()</code></dt>
69    <dd>Из объекта {@link android.view.View.OnCreateContextMenuListener}.
70Этот метод вызывается, когда создается контекстное меню (в результате длительного «длительного нажатия»). См. обсуждение
71контекстных меню в руководстве
72для разработчиков <a href="{@docRoot}guide/topics/ui/menus.html#context-menu">Меню</a>.</dd>
73</dl>
74
75<p>Эти методы являются единственными составными частями соответствующих интерфейсов. Чтобы определить один из этих методов
76и обрабатывать события, реализуйте вложенный интерфейс в вашем процесс или определите его, как анонимный класс.
77Затем передайте экземпляр реализации
78в соответствующий метод <code>View.set...Listener()</code>. (Например, вызовите
79<code>{@link android.view.View#setOnClickListener(View.OnClickListener) setOnClickListener()}</code>
80и передайте ему свою реализацию {@link android.view.View.OnClickListener OnClickListener}.)</p>
81
82<p>В следующем примере показано, как зарегистрировать приемник события «по клику» (on-click) для кнопки. </p>
83
84<pre>
85// Create an anonymous implementation of OnClickListener
86private OnClickListener mCorkyListener = new OnClickListener() {
87    public void onClick(View v) {
88      // do something when the button is clicked
89    }
90};
91
92protected void onCreate(Bundle savedValues) {
93    ...
94    // Capture our button from layout
95    Button button = (Button)findViewById(R.id.corky);
96    // Register the onClick listener with the implementation above
97    button.setOnClickListener(mCorkyListener);
98    ...
99}
100</pre>
101
102<p>Возможно, еще удобнее реализовать OnClickListener как часть вашей операции.
103При этом исключается дополнительная нагрузка класса и выделение объекта. Например:</p>
104<pre>
105public class ExampleActivity extends Activity implements OnClickListener {
106    protected void onCreate(Bundle savedValues) {
107        ...
108        Button button = (Button)findViewById(R.id.corky);
109        button.setOnClickListener(this);
110    }
111
112    // Implement the OnClickListener callback
113    public void onClick(View v) {
114      // do something when the button is clicked
115    }
116    ...
117}
118</pre>
119
120<p>Обратите внимание, что обратный вызов <code>onClick()</code> в примере выше не
121содержит возвращаемого значения, но некоторые другие методы приемника события должны возвращать логическое значение. Причина
122зависит от события. Для некоторых методов, которые возвращают значения, причина описана ниже:</p>
123<ul>
124  <li><code>{@link android.view.View.OnLongClickListener#onLongClick(View) onLongClick()}</code> —
125этот метод возвращает логическое значение, указывающее, что вы обработали это событие и его более не следует хранить.
126А именно, верните значение <em>true</em>, чтобы указать, что вы обработали событие и его следует остановить;
127верните значение <em>false</em>, если вы не обработали его и/или событие должно продолжаться для любых других
128приемников события on-click.</li>
129  <li><code>{@link android.view.View.OnKeyListener#onKey(View,int,KeyEvent) onKey()}</code> —
130этот метод возвращает логическое значение, указывающее, что вы обработали это событие и его более не следует хранить.
131    А именно, верните значение <em>true</em>, чтобы указать, что вы обработали событие и его следует остановить;
132верните значение <em>false</em>, если вы не обработали его и/или событие должно продолжаться для любых других
133приемников события on-click.</li>
134  <li><code>{@link android.view.View.OnTouchListener#onTouch(View,MotionEvent) onTouch()}</code> —
135этот метод возвращает логическое значение, указывающее, обработал ли ваш приемник это событие. Важно, что
136это событие может повлечь несколько действий, следующих друг за другом. Поэтому, если вы возвращаете <em>ложь</em> при приеме
137 события нажатия, вы указываете, что вы не обработали событие и не
138интересуетесь последующими действиями в результате этого события. Соответственно, этот метод не будет вызываться для любых других действий
139в рамках этого события, таких как жесты или возможное действие отпускания.</li>
140</ul>
141
142<p>Помните, что события аппаратных клавиш всегда попадают в отображаемый объект View, который находится в фокусе. Они отправляются, начиная с верха
143в иерархии отображаемых объектов, затем ниже, пока не достигнут соответствующего назначения. Если ваш отображаемый объект (или дочерний объект вашего отображаемого объекта)
144находится в фокусе, вы можете видеть, как событие перемещается сквозь метод <code>{@link android.view.View#dispatchKeyEvent(KeyEvent)
145dispatchKeyEvent()}</code>. В качестве альтернативы к перехвату событий клавиш через отображаемый объект View можно также получать
146все события внутри вашей операции с помощью методов <code>{@link android.app.Activity#onKeyDown(int,KeyEvent) onKeyDown()}</code>
147и <code>{@link android.app.Activity#onKeyUp(int,KeyEvent) onKeyUp()}</code>.</p>
148
149<p>Кроме того, размышляя о вводе текста для приложения, помните, что многие устройства поддерживают только программные методы
150ввода. Такие методы не обязательно основаны на нажатиях клавиш. Некоторые могут использовать голосовой ввод, рукописный ввод и т. д. Даже если
151метод ввода представлен интерфейсом, подобным клавиатуре, он обычно <strong>не</strong> приводит к запуску семейства
152событий<code>{@link android.app.Activity#onKeyDown(int,KeyEvent) onKeyDown()}</code>. Не следует создавать
153пользовательский интерфейс, для управления которым требуется нажимать определенные клавиши, кроме случаев, когда вы хотите ограничить использование приложения только устройствами
154с аппаратной клавиатурой. В частности, не полагайтесь на эти методы для подтверждения ввода, когда пользователь нажимает
155клавишу «Ввод». Вместо этого используйте такие действия, как {@link android.view.inputmethod.EditorInfo#IME_ACTION_DONE}, чтобы подать методу ввода сигнал
156о том, какой реакции ожидает приложение, чтобы он мог соответственно изменить свой пользовательский интерфейс. Избегайте предположений
157о работе программного метода ввода и доверьте ему ввод уже отформатированного текста в ваше приложение.</p>
158
159<p class="note"><strong>Примечание.</strong> Система Android сначала будет вызывать обработчики событий, а затем соответствующие обработчики по умолчанию
160из определения класса. Поэтому возврат значения <em>истина</em> из этих приемников событий будет останавливать
161передачу события остальным приемникам событий, а также будет блокировать обратный вызов
162обработчика событий по умолчанию в отображаемом объекте. Поэтому проверьте, что вы хотите прервать событие, когда вы возвращаете значение <em>true</em>.</p>
163
164
165<h2 id="EventHandlers">Обработчики событий</h2>
166
167<p>Если вы создаете нестандартный компонент из отображаемого объекта, вы сможете определить несколько методов обратного вызова,
168используемых как обработчики события по умолчанию.
169В документе <a href="{@docRoot}guide/topics/ui/custom-components.html">Нестандартные
170компоненты</a> можно узнать о некоторых общих обратных вызовах, используемых для обработки событий,
171включая следующие:</p>
172<ul>
173  <li><code>{@link  android.view.View#onKeyDown}</code> — вызывается при возникновении нового события клавиши.</li>
174  <li><code>{@link  android.view.View#onKeyUp}</code> — вызывается при возникновении события отпускания клавиши.</li>
175  <li><code>{@link  android.view.View#onTrackballEvent}</code> — вызывается при возникновении события перемещения трекбола.</li>
176  <li><code>{@link  android.view.View#onTouchEvent}</code> — вызывается при возникновении события жеста на сенсорном экране.</li>
177  <li><code>{@link  android.view.View#onFocusChanged}</code> — вызывается, когда отображаемый объект получает или теряет фокус.</li>
178</ul>
179<p>Существует несколько других методов, о которых следует знать и которые не являются частью класса View,
180но могут напрямую влиять на доступные вам способы обработки событий. Поэтому, управляя более сложными событиями внутри
181макета, учитывайте и другие методы:</p>
182<ul>
183  <li><code>{@link  android.app.Activity#dispatchTouchEvent(MotionEvent)
184    Activity.dispatchTouchEvent(MotionEvent)}</code> — этот метод позволяет вашей операции {@link
185    android.app.Activity} перехватывать все события касаний перед их отправкой в окно.</li>
186  <li><code>{@link  android.view.ViewGroup#onInterceptTouchEvent(MotionEvent)
187    ViewGroup.onInterceptTouchEvent(MotionEvent)}</code> — этот метод позволяет объекту {@link
188    android.view.ViewGroup} просматривать события перед их отправкой в дочерние отображаемые объекты.</li>
189  <li><code>{@link  android.view.ViewParent#requestDisallowInterceptTouchEvent(boolean)
190    ViewParent.requestDisallowInterceptTouchEvent(boolean)}</code> — вызовите этот метод
191в родительском отображаемом объекте, чтобы указать ему, что он не должен перехватывать события касания с помощью <code>{@link
192    android.view.ViewGroup#onInterceptTouchEvent(MotionEvent)}</code>.</li>
193</ul>
194
195<h2 id="TouchMode">Режим касания</h2>
196<p>
197Когда пользователь перемещается по пользовательскому интерфейсу с помощью клавиш перемещения или трекбола, необходимо
198передавать фокус действующим элементам (таким как кнопки), чтобы пользователь мог видеть,
199какой элемент будет принимать ввод.  Однако, если устройство поддерживает сенсорный ввод, и пользователь
200начинает взаимодействовать с интерфейсом, прикасаясь к его элементам, исчезает необходимость
201выделять элементы или передавать фокус определенному отображаемому объекту.  Следовательно, существует режим
202взаимодействия, который называется «режимом касания».
203</p>
204<p>
205Как только пользователь касается экрана, устройство, поддерживающее сенсорный ввод,
206переходит в режим касания.  Начиная с этого момента, фокус передается только тем отображаемым объектам, для которых
207{@link android.view.View#isFocusableInTouchMode} имеет значение true, таким как виджеты редактирования текста.
208Другие отображаемые объекты, которых можно коснуться, например, кнопки, не будут получать фокус при касании. Нажатие будет
209просто запускать их приемники событий on-click.
210</p>
211<p>
212В любой момент, когда пользователь нажимает клавишу перемещения или выполняет прокрутку трекболом, устройство
213выходит из режима касания и находит отображаемый объект, которому передается фокус. Теперь пользователь может возобновить взаимодействие
214с пользовательским интерфейсом без касания экрана.
215</p>
216<p>
217Состояние режима касания поддерживается во всей системе (для всех окон и операций).
218Чтобы узнать текущее состояние, можно вызвать
219{@link android.view.View#isInTouchMode} и посмотреть, находится ли устройство в режиме касания.
220</p>
221
222
223<h2 id="HandlingFocus">Фокус обработки</h2>
224
225<p>В ответ на пользовательский ввод система обрабатывает обычное перемещение фокуса.
226Сюда относится изменение фокуса, когда отображаемые объекты удаляются или скрываются, а также когда становятся доступными
227новые отображаемые объекты. Отображаемые объекты сообщают о своей готовности получить фокус
228с помощью метода <code>{@link android.view.View#isFocusable()}</code>. Чтобы изменить способность объекта View получать
229фокус, вызовите <code>{@link android.view.View#setFocusable(boolean) setFocusable()}</code>.  В режиме касания
230можно узнать способность отображаемого объекта View получать фокус с помощью метода <code>{@link android.view.View#isFocusableInTouchMode()}</code>.
231Для изменения вызовите <code>{@link android.view.View#setFocusableInTouchMode(boolean) setFocusableInTouchMode()}</code>.
232</p>
233
234<p>Перемещение фокуса основано на алгоритме, который находит ближайший элемент
235в заданном направлении. В редких случаях алгоритм по умолчанию может не совпадать
236с поведением, которое предполагает разработчик. В этих ситуациях можно задать
237явное переопределение с помощью следующих атрибутов XML в файле макета:
238<var>nextFocusDown</var>, <var>nextFocusLeft</var>, <var>nextFocusRight</var>и
239<var>nextFocusUp</var>. Добавьте один из этих атрибутов в отображаемый объект View, <em>из</em> которого
240выходит фокус. Задайте значение атрибута для идентификатора объекта View,
241<em>в</em> который следует передать фокус. Например:</p>
242<pre>
243&lt;LinearLayout
244    android:orientation="vertical"
245    ... >
246  &lt;Button android:id="@+id/top"
247          android:nextFocusUp="@+id/bottom"
248          ... />
249  &lt;Button android:id="@+id/bottom"
250          android:nextFocusDown="@+id/top"
251          ... />
252&lt;/LinearLayout>
253</pre>
254
255<p>Обычно в этом вертикальном макете перемещение вверх из первой кнопки не должно приводить к перемещению,
256как и перемещение вниз из второй кнопки. Теперь, когда верхняя кнопка
257задает для нижней кнопки атрибут <var>nextFocusUp</var> (и наоборот), фокус будет перемещаться
258циклически сверху вниз и снизу вверх.</p>
259
260<p>Если вы хотите объявить, что отображаемый объект в вашем пользовательском интерфейсе способен получать фокус (тогда как обычно он не может получать фокус),
261добавьте XML-атрибут <code>android:focusable</code> в объект View в объявлении макета.
262Установите для него значение <var>true</var>. Можно также объявить объект View,
263способным получать фокус в режиме касания с помощью <code>android:focusableInTouchMode</code>.</p>
264<p>Чтобы запросить передачу фокуса определенному отображаемому объекту, вызовите <code>{@link android.view.View#requestFocus()}</code>.</p>
265<p>Чтобы перехватывать события фокуса (получать уведомления, когда отображаемый объект получает или теряет фокус), используйте метод
266<code>{@link android.view.View.OnFocusChangeListener#onFocusChange(View,boolean) onFocusChange()}</code>,
267который обсуждается в разделе <a href="#EventListeners">Приемники событий</a> выше.</p>
268
269
270
271<!--
272<h2 is="EventCycle">Event Cycle</h2>
273   <p>The basic cycle of a View is as follows:</p>
274   <ol>
275    <li>An event comes in and is dispatched to the appropriate View. The View
276    handles the event and notifies any listeners.</li>
277    <li>If, in the course of processing the event, the View's bounds may need
278    to be changed, the View will call {@link android.view.View#requestLayout()}.</li>
279    <li>Similarly, if in the course of processing the event the View's appearance
280    may need to be changed, the View will call {@link android.view.View#invalidate()}.</li>
281    <li>If either {@link android.view.View#requestLayout()} or {@link android.view.View#invalidate()} were called,
282    the framework will take care of measuring, laying out, and drawing the tree
283    as appropriate.</li>
284   </ol>
285
286   <p class="note"><strong>Note:</strong> The entire View tree is single threaded. You must always be on
287   the UI thread when calling any method on any View.
288   If you are doing work on other threads and want to update the state of a View
289   from that thread, you should use a {@link android.os.Handler}.
290   </p>
291-->
292