Создание настраиваемой масштабируемой и масштабируемой ViewGroup, которая расширяет ConstraintLayout

Я пытаюсь включить пользовательский макет (например, ViewGroup), который расширяет ConstraintLayout (так что я могу добавить дочерние представления с ограничениями позиции), которые пользователь должен иметь возможность панорамирования и масштабирования. Я пробовал несколько способов добиться этого; в том числе:

  • Попытка адаптировать образец Google для панорамирования / масштабирования вида.

  • Перемещение холста на основе событий касания, подобных этому (вот мой onTouchEvent для класса).

     override fun onTouchEvent(event: MotionEvent): Boolean { // These two are the coordinates of the user's finger whenever onTouchEvent is called val x: Float = event.x val y: Float = event.y when(event.action and ACTION_MASK) { ACTION_DOWN -> { // Might not be necessary; check out later dragging = true // We want to store the coords of the user's finger as it is before they move // in order to calculate dx and dy initX = x initY = y } ACTION_MOVE -> { // Self explanatory; the difference in x- and y-coords between successive calls to // onTouchEvent val dx: Float = x - initX val dy: Float = y - initY if (dragging) { // Move the canvas dx units right and dy units down // dx and dy are divided by scaleFactor so that panning speeds are consistent // with the zoom level canvasX += dx/scaleFactor canvasY += dy/scaleFactor invalidate() // Re-draw the canvas // Change initX and initY to the new x- and y-coords initX = x initY = y } } ACTION_POINTER_UP -> { // This sets initX and initY to the position of the pointer finger so that the // screen doesn't jump when it's lifted with the main finger still down initX = x initY = y } ACTION_UP -> dragging = false // Again, may be unnecessary } detector.onTouchEvent(event) // Listen for scale gestures (ie pinching or double tap+drag // Just some useful coordinate data Log.d("TOUCHEVENT", "x: $x, y: $y,\ninitY: $initX, initY,\n" + "canvasX: $canvasX, canvasY: $canvasY,\nwidth: $dispWidth, height: $dispHeight\n" + "focusX: ${detector.focusX}, focusY: ${detector.focusY}") // Data pertaining to fingers for responsiveness and stuff Log.d("TOUCHEVENT", "Action: ${event.action and MotionEvent.ACTION_MASK}\n") return true } 

Я достиг такого эффекта для регулярного просмотра (код во второй ссылке – это просто слегка измененная версия кода, который я написал для представления), но мне нужна ViewGroup для моих целей. Я искал библиотеку, чтобы выполнить это, но я не могу найти какой-либо подходящий для моего использования случай даже с обширной модификацией, плюс, я бы лучше попытался сделать это сам, поэтому мне не нужно полагаться на библиотеки для все. Я уже прошел через многие сообщения StackOverflow относительно аналогичной проблемы, но еще раз я не смог заставить код работать с моей стороны.

Я считал, что просто использовал какую-то 2D-графику или библиотеку разработки игр, чтобы как-то добиться такого макета, но я чувствую, что это добавит ненужное раздувание в мое приложение.

Примечание. Я использую Kotlin (как вы можете видеть в моем коде выше), но даже если кто-то может помочь мне на Java, я всегда могу преобразовать его сам.