- Клавиатура и аппаратные кнопки
- Аппаратные и клавиатурные клавиши
- Кнопка Back: Вы уверены, что хотите выйти из программы?
- Двойное нажатие на кнопку Back
- Кнопка Home
- Обработка кнопки Menu
- Другие кнопки
- Прячем клавиатуру
- Изменить вид клавиатуры для EditText
- Переопределяем кнопку Enter
- Интерфейс OnKeyListener
- Сдвигаем активность
- Узнать выбранный язык на клавиатуре
- Кнопка возврата назад в компоненте навигации Android
- 17 ответов
- Последнее обновление — 25 апреля 2019 г.
- Старые обновления
- Android отслеживание кнопки назад
- Комментарии RSS по email OK
Клавиатура и аппаратные кнопки
Аппаратные и клавиатурные клавиши
Обработка аппаратных клавиш и клавиатуры имеет следующие методы
- onKeyDown() — вызывается при нажатии любой аппаратной клавиши;
- onKeyUp() — вызывается при отпускании любой аппаратной клавиши;
Кроме клавиш, есть ещё другие методы обработки пользовательского ввода (здесь не рассматриваются):
- onTrackballEvent() — срабатывает при движениях трекбола;
- onTouchEvent() — обработчик событий сенсорного экрана, срабатывает при касании, убирания пальца и при перетаскивании.
Чтобы ваши компоненты и активности реагировали на нажатия клавиш, переопределите обработчики событий onKeyUp() и onKeyDown():
Параметр keyCode содержит код клавиши, которая была нажата; сравнивайте его со статическими кодами клавиш, хранящимися в классе KeyEvent, чтобы выполнять соответствующую обработку.
Параметр KeyEvent также включает в себя несколько методов: isAltPressed(), isShiftPressed() и isSymPressed(), определяющих, были ли нажаты функциональные клавиши, такие как Alt, Shift или Sym. Статический метод isModifierKey() принимает keyCode и определяет, является ли нажатая клавиша модификатором.
Кнопка Back: Вы уверены, что хотите выйти из программы?
Кнопка Back (Назад) закрывает приложение, точнее текущую активность, но если приложение состоит из одной активности, то это равносильно закрытию всего приложения. В большинстве случаев вам нет никакого дела до неуклюжего пользователя, который по ошибке нажал на кнопку «Back» вместо кнопки Подарить разработчику миллион. Но, если ваша программа, будучи запущенной на телефоне пользователя, потихоньку списывает деньги клиента в счёт Фонда голодных котов, то нужно дать ему шанс задуматься и вывести диалоговое окно с вопросом: «А действительно ли вы хотите выйти из программы?»
Чтобы реализовать такую задачу, нужно переопределить поведение кнопки «Back» через метод активности onBackPressed() следующим образом:
Данный метод появился в Android 2.0. Для более ранних версий использовался стандартный код обработки onKeyDown():
Двойное нажатие на кнопку Back
Другой вариант — выход из приложения при двойном нажатии на кнопку «Back». Удобно в тех случаях, когда считаете, что пользователь может случайно нажать на кнопку, например, во время активной игры. Приложение закроется, если пользователь дважды нажмёт на кнопку в течение двух секунд.
Кнопка Home
Можно отследить нажатие кнопки Home через метод активности onUserLeaveHint():
Обработка кнопки Menu
У телефона, кроме кнопки «Back», есть ещё кнопка «Menu» для вызова команд меню (на старых устройствах). Если необходимо обрабатывать нажатия этой кнопки (например, управление в игре), то используйте следующий код (обычное и долгое нажатие):
Должен заметить, что длинное нажатие трудно уловить, так как обычное нажатие постоянно подавляет это событие.
Другие кнопки
Ну на самом деле можно отслеживать не только нажатие кнопки Меню, но и кнопку Поиска и кнопки увеличения громкости.
Обратите внимание, что для кнопки громкости возвращаем false, т.е. мы не переопределяем поведение кнопки, а оставляем её на усмотрение системы.
Пример работы с кнопками громкости можно посмотреть в статье Рингтоны. Управление громкостью
По такому же принципу работает метод onKeyUp(). Метод onKeyLongPress() можно использовать, если в методе onKeyDown() был задействован метод event.startTracking(), отслеживающий поведение кнопки. В нашем примере мы отслеживали кнопку Volume_Up.
Прячем клавиатуру
Бывает так, что при запуске активности сразу выскакивает клавиатура. Если такое поведение не нравится, то пропишите в манифесте нужное значение у атрибута android:windowSoftInputMode (см. ниже).
В некоторых случаях хочется убрать клавиатуру с экрана, не нажимая кнопку «Back», а программно. В одном моём приложении, где было много текстовых полей, я воспользовался следующим кодом при щелчке кнопки:
Код так выглядит, если писать его в Activity. Если расположить его в другом классе, экземпляр Activity нужно передать туда как параметр и вызывать методы как activity.getApplicationContext(), где activity — экземпляр Activity.
Можно избавить компонент от фокуса:
Чтобы принудительно показать клавиатуру, используйте следующий код:
Кстати, повторный вызов метода закроет клавиатуру. Указанный способ не требует наличия элементов View.
Если продолжить тему показа клавиатуры, то может возникнуть следующая ситуация. Допустим у вас есть DialogFragment с EditText. При выводе диалогового окна вам нужно установить фокус на EditText и показать клавиатуру:
Либо используйте тег для нужного EditText.
Изменить вид клавиатуры для EditText
Когда элемент EditText получает фокус, то появляется клавиатура. Можно установить нужный вид клавиатуры через атрибут InputType или программно через метод setInputType():
TYPE_CLASS_DATETIME — дата и время
TYPE_CLASS_NUMBER — цифры
TYPE_CLASS_TEXT — буквы
Переопределяем кнопку Enter
Кроме атрибута InputType можно также использовать атрибут android:imeOptions в компоненте EditText, который позволяет заменить кнопку Enter на клавиатуре на другие кнопки, например, Next, Go, Search и др. Возможны следующие значения:
- actionUnspecified: Используется по умолчанию. Система сама выбирает нужный вид кнопки (IME_NULL)
- actionGo: Выводит надпись Go. Действует как клавиша Enter при наборе адреса в адресной строке браузера (IME_ACTION_GO)
- actionSearch: Выводит значок поиска (IME_ACTION_SEARCH)
- actionSend: Выводит надпись Send (IME_ACTION_SEND)
- actionNext: Выводит надпись Next (IME_ACTION_NEXT)
- actionDone: Выводи надпись Done (IME_ACTION_DONE)
Чтобы увидеть все варианты воочию, можете создать несколько текстовых полей и переключаться между ними:
Чтобы реагировать на нажатия разных состояний кнопки Enter, необходимо реализовать интерфейс TextView.OnEditorActionListener. Небольшой пример:
В нашем примере если пользователь ищет что-то, не связанное с котом, то кнопка поиска не будет выполнять желание владельца устройства.
Также можно поменять текст на кнопке с помощью атрибута android:imeActionLabel:
Текст на кнопке поменялся, но вот обработка Enter из предыдущего примера у меня перестала работать. Мой неработающий код на память.
Upd: Читатель Максим Г. предложил следующее решение проблемы. Убираем атрибуты imeOptions, imeActionId, imeActionLabel и установим их программно.
По желанию можете отслеживать только у нужного поля. Поставьте дополнительное условие после первого блока if:
Интерфейс OnKeyListener
Чтобы среагировать на нажатие клавиши внутри существующего представления из активности, реализуйте интерфейс OnKeyListener и назначьте его для объекта View, используя метод setOnKeyListener(). Вместо того, чтобы реализовывать отдельные методы для событий нажатия и отпускания клавиш, OnKeyListener использует единое событие onKey().
Используйте параметр keyCode для получения клавиши, которая была нажата. Параметр KeyEvent нужен для распознавания типа события (нажатие представлено константой ACTION_DOWN, а отпускание — ACTION_UP).
Сдвигаем активность
Чтобы всплывающая клавиатура не заслоняла элемент интерфейса, который получил фокус, а сдвигала активность вверх, можно в манифесте для нужной активности прописать атрибут android:windowSoftInputMode с параметром adjustPan:
Также доступны и другие параметры:
- stateUnspecified — настройка по умолчанию. Система сама выбирает подходящее поведение клавиатуры.
- stateUnchanged — клавиатура сохраняет своё последнее состояние (видимое или невидимое), когда активность с текстовым полем получает фокус.
- stateHidden — клавиатура скрыта, когда открывается активность. Клавиатура появится при наборе текста. Если пользователь переключится на другую активность, то клавиатура будут скрыта, но при возвращении назад клавиатура останется на экране, если она была видима при закрытии активности.
- stateAlwaysHidden — клавиатура всегда скрывается, если активность получает фокус.
- stateVisible — клавиатура видима.
- stateAlwaysVisible — клавиатура становится видимой, когда пользователь открывает активность.
- adjustResize — размеры компонентов в окне активности могут изменяться, чтобы освободить место для экранной клавиатуры.
- adjustPan — окно активности и его компоненты не изменяются, а сдвигаются таким образом, чтобы текстовое поле с фокусом не было закрыто клавиатурой.
- adjustUnspecified — настройка по умолчанию. Система сама выбирает нужный режим.
Параметры с префиксом state можно комбинировать с настройками с префиксом adjust:
Например, чтобы показать клавиатуру при старте активности, используйте stateVisible.
Данные настройки доступны и программно. Например, код для adjustResize:
Кстати, этот код не сработает в полноэкранном режиме (флаг FLAG_FULLSCREEN). Сверяйтесь с документацией.
Узнать выбранный язык на клавиатуре
Для определения текущего языка на клавиатуре можно использовать следующий код.
Следует быть осторожным с примером. На эмуляторе с Android 6.0 пример работал корректно. На реальных устройствах у меня корректно определялся русский язык, но при переключении на английский язык выдавал пустую строку или значение «zz». В этом случае можно прибегнуть к условиям if и проверять ожидаемое значение.
Источник
Кнопка возврата назад в компоненте навигации Android
Я хотел бы знать, как правильно обрабатывать действия кнопки возврата системы с помощью контроллера навигации. В моем приложении у меня есть два фрагмента (например, фрагмент1 и фрагмент2), и у меня есть действие в фрагменте 1 с назначением для фрагмента2. Все работает хорошо, кроме одного — когда пользователь нажимает кнопку возврата системы во фрагменте 2, я хочу показать диалог (например, с помощью DialogFragment) для подтверждения выхода. Каков наилучший способ реализовать это поведение? Если я использую app:defaultNavHost=»true» в своем фрагменте хоста, он автоматически возвращается к игнорированию моих правил. И, кроме того, для чего этот компонент?
Должен ли я использовать «поп к» может быть?
17 ответов
Последнее обновление — 25 апреля 2019 г.
Новая версия androidx.activity ver. 1.0.0-alpha07 приносит некоторые изменения
Более подробные объяснения в официальном руководстве Android: Обеспечить пользовательскую обратную навигацию
Старые обновления
UPD: 3 апреля 2019 года
Теперь это упрощено. Подробнее здесь
Устаревший (с версии 1.0.0-alpha06 3 апреля 2019 г.):
Поскольку это, его можно реализовать, просто используя реализация JetPack OnBackPressedCallback в вашем фрагменте и добавьте его в активность: getActivity().addOnBackPressedCallback(getViewLifecycleOwner(),this);
Ваш фрагмент должен выглядеть так:
UPD : Ваша активность должна быть расширена AppCompatActivity или FragmentActivity и в файле Gradle:
Если вы используете BaseFragment для своего приложения, вы можете добавить onBackPressedDispatcher к вашему базовому фрагменту.
Переопределите onBackPressed () в вашем фрагменте, расширяя базовый фрагмент
Итак, я создал интерфейс
И реализовано это всеми фрагментами, которые нужно обработать кнопкой назад. В основной деятельности я переопределил метод onBackPressed() :
Итак, если верхний фрагмент моего хоста Navigation реализует интерфейс OnBackPressedListener , я вызываю его метод onBackPressed() , в другом месте я просто возвращаю стек назад и закрываю приложение, если задний стек пуст.
Вы можете предоставить свою собственную обратную навигацию, используя OnBackPressedDispatcher
Вот мое решение
Используйте androidx.appcompat.app.AppCompatActivity для действия, которое содержит фрагмент NavHostFragment .
Определите следующий интерфейс и внедрите его во все фрагменты назначения навигации
В вашей активности переопределите onSupportNavigateUp и onBackPressed :
Преимущество этого решения заключается в том, что фрагментам назначения навигации не нужно беспокоиться о том, что их слушатели не будут зарегистрированы, как только они отсоединятся.
В зависимости от вашей логики, если вы хотите закрыть только текущий фрагмент, вы должны передать viewLifecycleOwner, код показан ниже:
Однако, если вы хотите закрыть приложение на backPressed независимо от того, из какого фрагмента (вероятно, вы этого не захотите!), Не передавайте viewLifecycleOwner. Также, если вы хотите отключить кнопку возврата, не делайте ничего внутри handleOnBackPressed (), см. Ниже:
Если вы используете Navigation Component, следуйте приведенным ниже кодам в вашем методе onCreateView () (в этом примере я хочу просто закрыть свое приложение этим фрагментом)
Немного опоздал на вечеринку, но с последним выпуском Navigation Component 1.0.0-alpha09 теперь у нас есть AppBarConfiguration.OnNavigateUpListener.
Это 2 строки кода, которые можно прослушивать при нажатии на кнопку, от фрагментов [TESTED and WORKING]
рекомендуемый подход заключается в добавлении OnBackPressedCallback на OnBackPressedDispatcher действия.
Рекомендованный метод работал для меня, но после обновления моей реализации библиотеки ‘androidx.appcompat: appcompat: 1.1.0’
Реализуйте как ниже
Попробуй это. Я думаю, что это поможет вам.
Я попробовал решение Jurij Pitulja, но я просто не смог найти getOnBackPressedDispatcher или addOnBackPressedCallback, также используя решение Кирилла Ткача, не смог найти текущий фрагмент, так что вот мой:
Таким образом, вы можете во фрагменте решить, должно ли действие взять контроль над нажатой спиной или нет.
Кроме того, у вас есть BaseActivity для всех ваших действий, вы можете реализовать так
Если вы хотите обрабатывать обратную печать только в текущем фрагменте
Источник
Android отслеживание кнопки назад
28 октября 2014
В Android-приложениях иногда требуется особым образом обработать нажатие кнопки back. Если у вас не используются фрагменты, всё просто. Перекрываем метод onBackPressed у Activity и делаем что нам нужно. Если же используются фрагменты и по нажатию back необходимо что-то поменять в фрагменте, обработку хочется сделать именно в нём.
Посмотрев ответы на эту тему на StackOverflow я был несколько удивлён. Предлагается либо ненадёжный способ через OnKeyListener , либо жёсткий хардкод. Попробуем сделать это более красиво и удобно.
Начнём с интерфейса для фрагментов. Готового в фреймворке нет, сделаем свой:
Далее перекроем метод onBackPressed в нашем FragmentActivity :
Вытаскиваем все фрагменты, которые у нас есть. Ищем первый попавшийся, который реализует наш интерфейс OnBackPressedListener . Тут можно было придумать что-то, чтобы работать с несколькими обработчиками, но чаще всего он один. Если есть фрагмент, который реализует OnBackPressedListener , вызываем его единственный метод. Если нет — обрабатываем back как обычно.
Ну и, наконец, сам фрагмент:
Плюс данного подхода в том, что можно, например, отнаследовать все наши activity от MyActivity и использовать OnBackPressedListener без каких-либо изменений в коде MyActivity .
Комментарии RSS по email OK
Александр, смотрю ты уже на Android перешел. Мобильная разработка всех поглощает? Или это просто хобби 🙂
Я не ограничиваю себя какой-то одной технологией или языком. В случае андройда это не хобби. Коммерческий проект.
Согласен. Я то в моб. разработке дальше ionicframework(cordova) не пошел пока.
Спасибо за ваш вариант. На основе вашего у меня родилось следующее решение:
Я новечек важно ваше мнение. Конструкция вроде работает. Но могут ли быть с ней проблемы?
Могут. Как минимум, стоит учитывать, что использоваться может более одного фрагмента в одном activity.
В ListActivity это выглядит примерно так:
А как такое сделать в ListFragment и обычном Activity?
Sam, а почему вы пишете «андроЙд»? Или вы с такой же ошибкой пишите слова «плазмоЙд», «гиперболоЙд», «стероЙд» и «планетоЙд»? Домашнее задание: попробуйте произнести вслух эти слова так, как они написаны — с буквой «Й». Постарайтесь при этом не завязать язык в узел.
Капитан О., описочка вышла. Кстати, произнести с «й» вполне получается и при этом ничего в узел не завязывается. Это сочетание звуков вполне характерно для английского.
Спасибо за статью! Очень наглядный пример как ловить onBackPressed в фрагментах)
Источник