Хорошо, это должно быть ошибка в TextView или что-то на некоторых устройствах, например, Amazon Fire HD 10 (API 22).
Другие мои устройства выглядят работающими.
Я удалил ScrollViewsи установите детектор / слушатель непосредственно в TextView, и у него все еще была та же проблема.
Я заменил ScaleGestureDetector / Listener на некоторый код ручной работы (см. ниже), и у него все еще была та же проблема.
Я сдамся и буду игнорировать такие глючные устройства.
ссылка:
//var scaleFactor = 1f
//scroll_view.setOnTouchListener(ZoomTouchListener())
inner class ZoomTouchListener : View.OnTouchListener {
private val firstFocalPoint = PointF()
private var firstSpan = 0f
private var firstScaleFactor = 1f
private var firstScrollY = 0
private var firstScrollX = 0
private var isInProgress = false
@SuppressLint("ClickableViewAccessibility")
override fun onTouch(v: View, e: MotionEvent): Boolean {
if (e.pointerCount > 1) {
when (e.actionMasked) {
MotionEvent.ACTION_POINTER_DOWN,
MotionEvent.ACTION_DOWN -> {
startZooming(v, e)
}
MotionEvent.ACTION_POINTER_UP,
MotionEvent.ACTION_UP,
MotionEvent.ACTION_CANCEL -> {
isInProgress = false
}
else -> {
if (!isInProgress) {
startZooming(v, e)
} else {
val focalPoint = getFocalPoint(e)
scaleFactor = (firstScaleFactor * getSpan(e, focalPoint) / firstSpan)
.coerceAtMost(10.0f)
.coerceAtLeast(0.1f)
text_view.textSize = defaultTextSize * scaleFactor
v.scrollY =
((firstScrollY + firstFocalPoint.y) * scaleFactor / firstScaleFactor
- focalPoint.y).coerceAtLeast(0f).toInt()
horizontal_scroll_view.scrollX =
((firstScrollX + firstFocalPoint.x) * scaleFactor / firstScaleFactor
- focalPoint.x).coerceAtLeast(0f).toInt()
}
}
}
return true
} else
return false
}
private fun startZooming(v: View, e: MotionEvent) {
firstFocalPoint.set(getFocalPoint(e))
firstSpan = getSpan(e, firstFocalPoint)
firstScaleFactor = scaleFactor
firstScrollX = v.scrollX
firstScrollY = v.scrollY
isInProgress = true
}
private fun getFocalPoint(e: MotionEvent): PointF {
var sumX = 0f
var sumY = 0f
for (i in 0 until e.pointerCount) {
sumX += e.getX(i)
sumY += e.getY(i)
}
val focusX = sumX / e.pointerCount
val focusY = sumY / e.pointerCount
return PointF(focusX, focusY)
}
private fun getSpan(e: MotionEvent, focalPoint: PointF): Float {
var devSumX = 0f
var devSumY = 0f
for (i in 0 until e.pointerCount) {
devSumX += abs(e.getX(i) - focalPoint.x)
devSumY += abs(e.getY(i) - focalPoint.y)
}
val devX = devSumX / e.pointerCount
val devY = devSumY / e.pointerCount
val spanX = devX * 2
val spanY = devY * 2
return hypot(spanX, spanY)
}
}