我需要在比例改变后获取ImageView内图像的位置、宽度和高度。我需要这些值来添加代码来控制滚动限制。 我见过其他使用 Matrix 机制的线程,但在我的情况下,它们并不适用,因为我的图像确实超出了 ImageView 的范围,因为比例更改是将图像缩放 2 倍和 3 倍。
我需要的是保持图像在滚动时不显示空白区域。例如,图像的左上角不能低于视图的上边框,也不能超出视图左边框的最右侧。与其他角类似,图像不能越过底部边框或右边框的最左侧等。
当我执行 pdfview.x 和 pdfview.width 等操作时,这些值给了我原始值。我可以通过数学得到宽度和高度,但不能用位置来做到这一点,因为它在滚动时会改变。
我尝试获取边界,但它也给了我原始值。
边界代码:
var bounds: RectF = getImageBounds(pdfview)
fun getImageBounds(imageView: ImageView): RectF {
val bounds = RectF()
val drawable = imageView.drawable
if (drawable != null) {
imageView.imageMatrix.mapRect(bounds, RectF(drawable.bounds))
}
return bounds
}
缩放代码:
val binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
pdfview = binding.pdfview
slider = binding.slider
slider.addOnChangeListener { slider, value, fromUser ->
// Responds to when slider's value is changed
pdfview.scaleX = 1 + slider.value / 100
pdfview.scaleY = 1 + slider.value / 100
}
PAN 代码:
var preX: Float = pdfview.x
var preY: Float = pdfview.y
pdfview.setOnTouchListener { v, event ->
val currentX: Float
val currentY: Float
when (event.action) {
MotionEvent.ACTION_DOWN -> {
preX = event.x
preY = event.y
}
MotionEvent.ACTION_MOVE -> {
currentX = event.x
currentY = event.y
pdfview.scrollBy((preX - currentX).toInt(), (preY - currentY).toInt())
preX = currentX
preY = currentY
}
MotionEvent.ACTION_UP -> {
currentX = event.x
currentY = event.y
pdfview.scrollBy((preX - currentX).toInt(), (preY - currentY).toInt())
}
}
true
}
布局 xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/myLayout"
tools:context=".MainActivity">
<FrameLayout
android:id="@+id/frame"
android:layout_width="350dp"
android:layout_height="515dp"
android:layout_marginStart="30dp"
android:layout_marginTop="4dp"
android:layout_marginEnd="30dp"
android:background="@drawable/image_border"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/creatorButton">
<View
android:id="@+id/view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:cropToPadding="true"
android:padding="1dp"
android:scaleType="centerCrop" />
<ImageView
android:id="@+id/pdfview"
android:layout_width="350dp"
android:layout_height="515dp"
android:contentDescription="@string/pdf"
android:cropToPadding="true"
android:padding="1dp"
android:scaleType="centerCrop"
app:srcCompat="@color/material_dynamic_neutral80" />
</FrameLayout>
<LinearLayout
android:id="@+id/linear"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical"
android:visibility="invisible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/frame"
app:layout_constraintVertical_bias="0.0">
<com.google.android.material.slider.Slider
android:id="@+id/slider"
android:layout_width="350dp"
android:layout_height="wrap_content"
android:layout_marginTop="0dp"
android:layout_marginBottom="0dp"
android:valueFrom="0.0"
android:valueTo="300.0" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
原来我找到了如何使用矩阵移动机制而不是滚动机制。关键是要执行正确的矩阵重绘代码。
以下为动作代码:
pdfview.setOnTouchListener { _, event -> //v, event ->
val bounds: RectF = getImageBounds(pdfview, m)
val currentX: Float
val currentY: Float
when (event.action) {
MotionEvent.ACTION_DOWN -> {
preX = event.x
preY = event.y
}
MotionEvent.ACTION_MOVE -> {
currentX = event.x
currentY = event.y
//// The function xyComp is used to control the limits of the Matrix movements
//// with the help of the Drawable boundaries and corner coordinates, and total size of the View.
//// Those values are obtain on each movement below.
if (xyComp(
bounds,
fixbounds,
preX,
preY,
currentX,
currentY,
(preX - currentX),
(preY - currentY)
)
) {
//// Matrix movement. postTranslate move the Matrix in continuos mode
m.postTranslate(
-(preX - currentX),
-(preY - currentY)
)
//// Redraw Matrix by assigning the moved Matrix to the View, do not use invalidate method
pdfview.imageMatrix = m
//// Get the size(top,left,bottom,right) coordinates of the Drawable/Matrix within the View
pbounds = getImageBounds(pdfview)
//// Get the Matrix corner coordinates
val f = FloatArray(9)
m.getValues(f)
pscrollX = f[Matrix.MTRANS_X]
pscrollY = f[Matrix.MTRANS_Y]
//// With the size and corner then you can control the limits which can it move
preX = currentX
preY = currentY
}
}
MotionEvent.ACTION_UP -> {
currentX = event.x
currentY = event.y
if (xyComp(
bounds,
fixbounds,
preX,
preY,
currentX,
currentY,
(preX - currentX),
(preY - currentY)
)
) {
m.postTranslate(
-(preX - currentX),
-(preY - currentY)
)
pdfview.imageMatrix = m
pbounds = getImageBounds(pdfview)
val f = FloatArray(9)
m.getValues(f)
pscrollX = f[Matrix.MTRANS_X]
pscrollY = f[Matrix.MTRANS_Y]
}
}
}
if (pscrollX != scrollX) {
switchPAN.tag = true
switchPAN.visibility = VISIBLE
switchCenter.visibility = GONE
}
true
}