I have tried many of the similar questions offered by the Stackoverflow system but they are for other escenarios. I do not use canvas, and I use Matrix to Zoom and PAN but in combination with scrollBy and imageview.scaleX, imageview.scaleY.
The problem is that I want to replace the Bitmap in the ImageView but when replaced it takes the same position and zoom states of the previous Bitmap.
I tried doing ScrollTo(0,0) to reset the position. Tried translateX(0), translateY(0). Tried setX(0), setY(0)
Tried to do setImageMatrix(originalM) where originalM is the imageview.imageMatrix at Create. Tried imageview.imageMatrix = Matrix()
Tried to imageview.setScaleType(ImageView.ScaleType.CENTER_CROP) then imageview.setScaleType(ImageView.ScaleType.MATRIX)
To benefit the readers this is part of my code. You will notice I translate and scale the Matrix behind the scene but do not invalidate() the imageview. I want the user to see the changes in the view but not the Matrix. I am trying to make the zoom and pan of the matrix in PX (this part does not work correctly but is outside the scope of this Question. The use use of this Matrix is probably part of the problem but I can't remove it as is use for another function in the code and for other Topic/Question)
Layout:
<FrameLayout
android:id="@+id/frame"
android:layout_width="350dp"
android:layout_height="500dp"
android:layout_marginStart="30dp"
android:layout_marginTop="2dp"
android:layout_marginEnd="30dp"
android:background="@drawable/image_border"
android:visibility="visible"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/button_layout">
<ImageView
android:id="@+id/pdfview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="@string/pdf"
android:cropToPadding="true"
android:scaleType="matrix"
app:layout_constraintDimensionRatio="1:1"
app:srcCompat="@color/material_dynamic_neutral80" />
<!--android:scaleType="centerCrop"-->
</FrameLayout>
Zoom:
slider.addOnChangeListener { slider, value, fromUser ->
// Responds to when slider's value is changed
tv = "Zoom Value:\n${value.format(2)}%"
zoom.text = tv
m = pdfview.imageMatrix
scaleX = 1 + value / 100
scaleY = 1 + value / 100
// Responds to when slider's value is changed
pdfview.scaleX = scaleX
pdfview.scaleY = scaleY
scrollX = pdfview.scrollX
scrollY = pdfview.scrollY
m.setScale(scaleX, scaleY, centerX, centerY)
m.postTranslate(
-(scrollX).toInt().toFloat().px,
-(scrollY).toInt().toFloat().px
)
}
Extension function
private val Float.px: Float get() = (this * getSystem().displayMetrics.density)
PAN:
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())
m.postTranslate(
-(preX - currentX).toInt().toFloat().px,
-(preY - currentY).toInt().toFloat().px
)
preX = currentX
preY = currentY
}
MotionEvent.ACTION_UP -> {
currentX = event.x
currentY = event.y
pdfview.scrollBy((preX - currentX).toInt(), (preY - currentY).toInt())
m.postTranslate(
-(preX - currentX).toInt().toFloat().px,
-(preY - currentY).toInt().toFloat().px
)
}
}
true
}
Imageview Bitmap:
@Throws(IOException::class)
private fun openPdfFromStorage(uri: Uri) {
var FILE_NAME = getFileName(uri)//"temp${Date()}.pdf"
if (FILE_NAME == null) FILE_NAME = "temp${Date()}.pdf"
val fileCopy = File(cacheDir, FILE_NAME) //anything as the name
copyToCache(fileCopy, uri) /////////// Function not shown. Reads full file from Uri and place it in memory
// Get a page from the PDF doc by calling 'open'
val fileDescriptor = ParcelFileDescriptor.open(
fileCopy,
ParcelFileDescriptor.MODE_READ_ONLY
)
mPdfRenderer = PdfRenderer(fileDescriptor)
pdfpages = mPdfRenderer.pageCount
pdfnum = 0
val mPdfPage = mPdfRenderer.openPage(pdfnum)
val bitmap = Bitmap.createBitmap(
pdfview.width, //bmWidth,
pdfview.height, //bmHeight,
Bitmap.Config.ARGB_8888
) //Not RGB, but ARGB
mPdfPage.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY)
pdfview.setImageBitmap(bitmap)
///////////
// WHEN THIS IS EXECUTED OVER A PREVIOUSLY USED IMAGEVIEW THE BITMAP IS SHOWN WITH THE SAME POSITION AND SCALE OF THE PREVIOUS BITMAP
///////////
pdfview.setScaleType(ImageView.ScaleType.CENTER_CROP)
pdfview.setScaleType(ImageView.ScaleType.MATRIX)
m = pdfview.imageMatrix
mPdfPage.close()
pbounds = getImageBounds(pdfview) //imageView.imageMatrix.mapRect(bounds, RectF(drawable.bounds))
centerX = pbounds.centerX()
centerY = pbounds.centerY()
}
Once I found how to use the Matrix movement mechanism correctly it was simple:
Before replacing the Image move the current Image to the origin. Following code will PAN the Image back to the origin.
val sX = scrollX //current X coord.
val sY = scrollY //current Y coord.
val pX = pscrollX //previous X coord.
val pY = pscrollY //previous Y coord.
m.postTranslate(-(pX - sX), -(pY - sY))
pdfview.imageMatrix = m
val f = FloatArray(9)
m.getValues(f)
pscrollX = f[Matrix.MTRANS_X]
pscrollY = f[Matrix.MTRANS_Y]
Then to replace the Image just:
pdfview.imageMatrix = Matrix()
pdfview.scaleType = ImageView.ScaleType.MATRIX
pdfview.setImageBitmap(bitmap)