Comments 16
Думаю, было бы неплохо такую фишку стандартизировать, чтобы пользователям не нужно было запоминать свайпы для каждого приложения. Желательно в виде библиотеки, где разработчикам всего то и нужно, что наследовать свои Activity от вашей реализации.
Ну и еще я думаю, что свайп слева как в iOS был бы лучше, чем сверху, так как достать туда проще. Да и кнопка и стрелка «назад» показывают именно влево.
Добрый день! Именно для этого мы его и написали — чтобы задняя activity была видна в любой момент времени.
По этому наверно правильнее делать на фрагментах, так как они в любом случае остаются видимыми.
так как они в любом случае остаются видимыми
Это зависит от того, как мы совершаем транзакцию: add или replace. Replace нам удалит предыдущий фрагмент с экрана, так что он тоже не будет видимым и работать это не будет. Add добавит фрагмент поверх предыдущего, однако предыдущий фрагмент не получит onPause()/onResume() колбэков, в отличие от примера с activity. Если использовать подход с фрагментами, то лучше сразу использовать BottomSheetFragmentDialog из дизайнерской либы.
Я бы сказал, что в общем случае лучше руководствоваться здравым смыслом. Если контент фрагментов слишком разный (стили, цвета, набор иконок в тулбаре, наличие и отсутствие бокового меню, интеграция с context), то объединение их в одну активити ради scroll-to-dismiss принесет больше проблем, чем профита.
Но активити сама по себе как системный класс — тяжелее фрагмента. совсем не здорово, когда в приложении все активити остаются висеть в памяти в активном состоянии.
Плюс при повороте будет создаваться весь стек активити, и это заметно.
Плюс отсутствие вызова онСтоп не позволяет впрямую обработать переход на новый экран (остановить какой-нибудь поллинг) — можно конечно свои методы для этого нагородить.
Я понимаю, что сама задача требует активного предыдущего экрана под текущим, но в хорошей реализации должно быть учтено, что оставаться должен только ОДИН предыдущий экран.
Есть компромиссное решение — делать скриншот экрана, но тут проблем еще больше, ибо довольно часто при переходе назад экран будет уже не соответствовать скриншоту
все активити остаются висеть в памяти в активном состоянии.
Почему все? Только активная и предыдущая
Плюс при повороте будет создаваться весь стек активити
Как и активных фрагментов
и это заметно
Если это заметно, скорее всего активити/фрагмент делают больше, чем им положено
отсутствие вызова онСтоп не позволяет впрямую обработать переход на новый экран (остановить какой-нибудь поллинг)
Для этого есть onPause
Есть компромиссное решение — делать скриншот экрана
Был и такой вариант :) Под кодовым названием План Y :)
Почему все? Только активная и предыдущая
если открыть третье активити с возможностью закрытия свайпом, то и первое и второе и третье будут активными. и так далее.
Активити создаются заметно дольше фрагментов. Никаких тяжелых операций в них запускать для этого не надо, достаточно взять не самый топовый девайс и можно определять на глаз, где фрагменты, а где активити.
А вообще хорошая статья, кому-то точно поможет разобраться)
Но не получается добавить затемнение.
Может можно увидеть живой проект на гите?
Вот кусок кода. У меня слайд вправо, так что код немного изменен.
abstract class SlidingActivity : AppCompatActivity() {
var windowScrim: ColorDrawable = ColorDrawable(Color.argb(0xE0, 0, 0, 0))
<...>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
window.statusBarColor = Color.TRANSPARENT
}
windowScrim.alpha = 0
window.setBackgroundDrawable(windowScrim)
}
private fun updateScrim() {
Log.v(TAG, "updateScrim")
val progress = root.x / screenSize.x
val alpha = (progress * 255f).toInt()
windowScrim.alpha = 255 - alpha
this.window.setBackgroundDrawable(windowScrim)
}
override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
<...>
when (ev.action) {
MotionEvent.ACTION_MOVE -> {
if ((isSlidingRight(startX, startY, ev) && canSlideRight()) || isSliding) {
updateScrim()
<...>
}
}
}
}
}
Все работает отлично, при сдвиге updateScrim() в логе отрабатывается тоже, но затемнения не происходит.
Может быть, я что-то упускаю?
Добрый день! С виду все правильно. Нужно убедиться, что updateScrim() вызывается на каждое событие ACTION_MOVE и при завершающей анимации. В самой функции updateScrim() стоит проверить, что alpha действительно считается правильно и меняется от 0 до 255.
На гитхабе, к сожалению, проекта нет, зато можем показать гист :) https://gist.github.com/forceLain/49e02e8d772e99707ebda9137b3b6ccb
Рецепты под Android: Scroll-To-Dismiss Activity