Как сделать кликабельной картинку в Jetpack Compose, если библиотека принимает только строку с ссылкой и не принимает модификаторы клика
Что проверяют
Как вы понимаете модель модификаторов и обработку жестов в Compose: можно ли навесить клик снаружи на чужой composable, который не принимает Modifier. Следом обычно спрашивают про доступность и про то, что будет, если библиотека сама перехватывает касания.
Как отвечать
Раз параметр modifier недоступен, клик вешают на обёртку. Базовый вариант: Box(Modifier.clickable(onClick = onClick)) { LibraryImage(url) }. Работает это потому, что событие касания в основном проходе идёт от вложенного элемента к родителю, и если картинка его не поглотила, clickable на Box его получит.
Дальше разберите нюансы:
- библиотека сама обрабатывает касания: например, внутри есть зум или свой
clickable. Тогда дочерний элемент поглощает жест раньше родителя. Решение: положить поверх картинки прозрачный слойBox(Modifier.matchParentSize().clickable { ... })внутри того жеBox. Он выше по z-порядку и получает касание первым; - размер:
matchParentSize()берёт размеры уже измеренногоBox, поэтому оверлей точно совпадает с картинкой, аfillMaxSize()может растянуть родителя; - доступность: у
clickableесть параметрыonClickLabelиrole, напримерRole.Button, аcontentDescriptionкартинки должен описывать смысл, иначе TalkBack прочитает пустой элемент; - отклик: ripple рисуется по границам
Box, для скруглённой картинки добавьтеModifier.clip(shape)доclickable; - замена загрузчика: если библиотека больше ничего не даёт, её можно заменить на
AsyncImageиз Coil, который принимаетmodifierнапрямую.
Где спотыкаются
Берут Modifier.pointerInput с detectTapGestures там, где хватает clickable, и теряют ripple, фокус с клавиатуры и семантику для скринридера.
Показывают код с rememberImagePainter. Это API ранних версий Coil, в Coil 3 его нет, и на собеседовании это читается как опыт по устаревшим примерам.
Не учитывают порядок модификаторов: clickable перед padding делает отступ частью области нажатия, а clip после clickable не обрезает ripple. В Compose цепочка читается строго по порядку.