Как реализовать панорамирование и масштабирование всего RecyclerView - PullRequest
0 голосов
/ 22 мая 2019

У меня есть свой собственный вид, который расширяет RecyclerView, и я использую его для отображения документа на нескольких страницах.Каждый элемент в адаптере - это страница.

Я хочу добавить возможность масштабирования и панорамирования всего документа (не каждой страницы отдельно).

Я пытался следовать руководству по Android здесь , но я все еще не могу заставить и зум, и панорамирование работать должным образом.

Мой текущий подход таков:

  • Имею GestureDetector для обнаружения жестов панорамирования
  • Имеют ScaleGestureDetector для обнаружения жестов щипка
  • Когда каждый из этих детекторов регистрирует события, сохраните информацию о текущем масштабном коэффициенте и панорамировании, позвоните invalidate() и измените Canvas в методе drawChild соответствующим образом.

Это последний шаг, который я не знаю, как правильно реализовать.

Я использую этот класс данных для отслеживаниятекущее панорамирование и масштабирование представления:

private data class PanAndZoom(
    var scaleFactor: Float, 
    var focusX: Float, 
    var focusY: Float, 
    var panX: Float , 
    var panY: Float
)

// field in my custom view initialised like this:
private val panAndZoom = PanAndZoom(1f, 0f, 0f, 0f, 0f)

, и вот как я обновляю значения при получении жестов:

private val scaleGestureDetector = ScaleGestureDetector(context, object : ScaleGestureDetector.SimpleOnScaleGestureListener() {
    override fun onScale(detector: ScaleGestureDetector): Boolean {
        panAndZoom.scaleFactor *= detector.scaleFactor
        panAndZoom.focusX = detector.focusX
        panAndZoom.focusY = detector.focusY
        invalidate()
        return true
    }
}
private val gestureDetector = GestureDetector(context, object : GestureDetector.SimpleOnGestureListener() {
        override fun onScroll(e1: MotionEvent?, e2: MotionEvent?, distanceX: Float, distanceY: Float): Boolean {
        panAndZoom.panX -= distanceX
        panAndZoom.panY -= distanceY
        invalidate()
        return true
    }
}

Я переопределяю два метода в моем настраиваемом представлении, один для передачиприкоснуться к событиям моих детекторов жестов и один, чтобы нарисовать ребенка VIew:

override fun onTouchEvent(e: MotionEvent): Boolean {
    gestureDetector.onTouchEvent(e)
    scaleGestureDetector.onTouchEvent(e)
    return super.onTouchEvent(e)
}

override fun drawChild(canvas: Canvas, child: View, drawingTime: Long): Boolean {
    val save = canvas.save()
    canvas.scale(panAndZoom.scaleFactor, panAndZoom.scaleFactor, panAndZoom.focusX, panAndZoom.focusY)
    canvas.translate(panAndZoom.panX, panAndZoom.panY)
    val result = super.drawChild(canvas, child, drawingTime)
    canvas.restoreToCount(save)
    return result
}

Однако это не дает ожидаемого результата, а именно:

  • Я могу полностью выйти за пределы RV (я понимаю, что не ограничиваю своизначения панорамы, но как мне это сделать?) *
  • Панорамирование, кажется, идет очень быстро при увеличении (как мне масштабировать значения панорамирования, чтобы они учитывали коэффициент масштабирования)?
  • Если я нахожусь на странице 2 документа, и я увеличиваю, а затем перемещаюсь на страницу 3, менеджер по расположению не понимает, что представление фактически прокручивалось (то есть, вызов findFirstVisibleItem() вернет вторую страницу, когда это не так).t на самом деле видимый.
  • Скорее всего, связан с пунктом выше: я могу перемещаться по странице, и поскольку менеджер по расположению не понимает, что теперь отображается другое представление, он не отображает его (потому что он все ещесчитает, что представление скрыто от просмотра и поэтому оптимизирует его, не отображая его.)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...