Реализация Long Press Menu для Android-приложения

TRUETECH занимается разработкой, поддержкой и обслуживанием мобильных приложений iOS, Android, PWA. Имеем большой опыт и экспертизу для публикации мобильных приложений в популярные маркеты Google Play, App Store, Amazon, AppGallery и другие.
Разработка и поддержка любых видов мобильных приложений:
Информационные и развлекательные мобильные приложения
Новостные приложения, игры, справочники, онлайн-каталоги, погодные, фитнес и здоровье, туристические, образовательные, социальные сети и мессенджеры, квиз, блоги и подкасты, форумы, агрегаторы
Мобильные приложения электронной коммерции
Интернет-магазины, B2B-приложения, маркетплейсы, онлайн-обменники, кэшбэк-сервисы, биржи, дропшиппинг-платформы, программы лояльности, доставка еды и товаров, платежные системы
Мобильные приложения для управления бизнес-процессами
CRM-системы, ERP-системы, управление проектами, инструменты для команды продаж, учет финансов, управление производством, логистика и доставка, управление персоналом, системы мониторинга данных
Мобильные приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, платформы предоставления электронных услуг, платформы кешбека, видеохостинги, тематические порталы, платформы онлайн-бронирования и записи, платформы онлайн-торговли

Это лишь некоторые из типы мобильных приложений, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента.

Предлагаемые услуги
Показано 1 из 1 услугВсе 1735 услуг
Реализация Long Press Menu для Android-приложения
Простая
~1 рабочий день
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_mobile-applications_feedme_467_0.webp
    Разработка мобильного приложения для компании FEEDME
    756
  • image_mobile-applications_xoomer_471_0.webp
    Разработка мобильного приложения для компании XOOMER
    624
  • image_mobile-applications_rhl_428_0.webp
    Разработка мобильного приложения для компании RHL
    1052
  • image_mobile-applications_zippy_411_0.webp
    Разработка мобильного приложения для компании ZIPPY
    947
  • image_mobile-applications_affhome_429_0.webp
    Разработка мобильного приложения для компании Affhome
    862
  • image_mobile-applications_flavors_409_0.webp
    Разработка мобильного приложения для компании FLAVORS
    445

Реализация Long Press Menu для Android-приложения

Long press — это жест, который пользователи ожидают интуитивно: долгое нажатие на элемент списка открывает контекстные действия. На практике реализация разваливается в двух местах: некорректное распознавание жеста при быстром скролле RecyclerView и визуально невнятное отображение меню.

Варианты реализации

PopupMenu — самый простой путь для списков с фиксированными действиями. Прикрепляется к View через якорь, раздувается из XML-ресурса:

itemView.setOnLongClickListener { view ->
    val popup = PopupMenu(view.context, view)
    popup.menuInflater.inflate(R.menu.context_item_menu, popup.menu)
    popup.setOnMenuItemClickListener { menuItem ->
        when (menuItem.itemId) {
            R.id.action_delete -> { onDelete(item); true }
            R.id.action_share  -> { onShare(item); true }
            else -> false
        }
    }
    popup.show()
    true
}

Проблема: PopupMenu появляется в углу View без анимации позиции. На маленьких экранах или в нижней части списка меню уходит за границы видимой области. Начиная с API 28 setForceShowIcon(true) позволяет показывать иконки в PopupMenu — без этого флага иконки из menu.xml просто игнорируются.

ContextMenu через registerForContextMenu() — устаревший подход, привязан к Activity и плохо работает с RecyclerView.

BottomSheetDialog — предпочтительный выбор для современных приложений с Material Design 3. Визуально чище, не зависит от позиции элемента на экране, легко расширяется. Реализуется через MaterialAlertDialogBuilder или кастомный BottomSheetDialogFragment.

Проблема скролла и жеста

В RecyclerView OnLongClickListener конкурирует с ItemTouchHelper, если тот используется для свайпа. Если ItemTouchHelper поглощает событие раньше — onLongClick не вызывается. Решение: явно обрабатывать MotionEvent.ACTION_DOWN / ACTION_CANCEL в OnItemTouchListener и передавать управление по таймауту ViewConfiguration.getLongPressTimeout().

Другой случай: хаптик-фидбэк при долгом нажатии. view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS) — вызывается вручную внутри onLongClick, потому что система не гарантирует его автоматически для кастомных view.

Compose

В Jetpack Compose — combinedClickable:

Box(
    modifier = Modifier.combinedClickable(
        onClick = { onClick(item) },
        onLongClick = { showMenu = true }
    )
) {
    // контент элемента
    DropdownMenu(
        expanded = showMenu,
        onDismissRequest = { showMenu = false }
    ) {
        DropdownMenuItem(text = { Text("Удалить") }, onClick = { onDelete(item); showMenu = false })
        DropdownMenuItem(text = { Text("Поделиться") }, onClick = { onShare(item); showMenu = false })
    }
}

DropdownMenu позиционируется автоматически относительно родительского Box — проблема выхода за границы экрана решается платформой.

Типичные ошибки

Меню открывается при скролле. Причина — OnLongClickListener на itemView без проверки состояния скролла. Фикс: recyclerView.scrollState == RecyclerView.SCROLL_STATE_IDLE перед показом меню.

Нет визуального выделения при удержании. itemView должен иметь android:background="?attr/selectableItemBackground" для корректного ripple-эффекта при долгом нажатии.

Сложность реализации — от нескольких часов (простой PopupMenu) до 1-2 дней (кастомный BottomSheet с анимациями и мультиселектом). Стоимость рассчитывается индивидуально.