Refactor Presentation's view to be reusable

This commit is contained in:
Luke Hubmayer-Werner 2024-09-01 04:04:11 +09:30
parent 03f981d3d8
commit c64bc5f403
2 changed files with 97 additions and 64 deletions

View File

@ -6,11 +6,9 @@ import android.graphics.Bitmap
import android.util.DisplayMetrics
import android.view.Display
import android.view.WindowManager
import android.widget.HorizontalScrollView
import android.widget.ImageView
import android.widget.LinearLayout
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat
import com.lhw.pdf.ui.HorizontalGallery
class MyPresentation(outerContext: Context, display: Display) : Presentation(outerContext, display) {
val displayMetrics = DisplayMetrics()
@ -20,8 +18,7 @@ class MyPresentation(outerContext: Context, display: Display) : Presentation(out
private val bitmaps = mutableListOf<Bitmap>()
private val bitmapCumWidths = mutableListOf<Int>(0)
private val layout = LinearLayout(this.context)
private val scroll = HorizontalScrollView(this.context)
private val scroll = HorizontalGallery(this.context)
private var scrollProgress = 0f
private val layoutParams = WindowManager.LayoutParams()
init {
@ -31,75 +28,19 @@ class MyPresentation(outerContext: Context, display: Display) : Presentation(out
WindowCompat.getInsetsController(it, it.decorView)
.hide(WindowInsetsCompat.Type.systemBars())
}
scroll.addView(layout)
println(layoutParams)
addContentView(scroll, layoutParams)
}
fun updateImages(bitmaps: Iterable<Bitmap>) {
println("Updating presentation images")
println("Layout has scale ${layout.scaleX} ${layout.scaleY}")
layout.removeAllViewsInLayout()
this.bitmaps.clear()
bitmapCumWidths.clear()
bitmapCumWidths.add(0)
bitmaps.forEach {
this.bitmaps.add(it)
bitmapCumWidths.add(it.width + bitmapCumWidths.last())
}
if (lazyScroll) {
lazyIdxStart = -1
lazyIdxEnd = -1
layoutVisibleBitmaps()
} else {
layoutAllBitmaps()
}
}
private fun layoutBitmap(bitmap: Bitmap) {
val img = ImageView(this.context)
img.setImageBitmap(bitmap)
img.minimumWidth = bitmap.width // No idea what broke when I refactored this class
img.minimumHeight = bitmap.height
println("${bitmap.width}x${bitmap.height}")
layout.addView(img)
}
private fun layoutAllBitmaps() {
bitmaps.forEach(::layoutBitmap)
println("Presentation heights ${scroll.height} ${layout.height}")
}
private fun layoutVisibleBitmaps() {
val xStart = (scrollProgress * (bitmapCumWidths.last() - scroll.width)).toInt()
val xEnd = xStart + scroll.width
// bitmapCumWidths has a prepended 0
val idxStart = bitmapCumWidths.indexOfFirst { it > xStart }.let { if (it >= 1) it-1 else 0 }
val idxEnd = bitmapCumWidths.indexOfFirst { it > xEnd }.let { if (it >= 0) it else bitmaps.size}
layout.removeAllViewsInLayout()
(idxStart..<idxEnd).map(bitmaps::get).forEach(::layoutBitmap)
lazyIdxStart = idxStart
lazyIdxEnd = idxEnd
println("Laying out pages $idxStart up to $idxEnd - scrollable width ${layout.width}")
scroll.updateImages(bitmaps)
}
fun setScrollProgress(progress: Float) {
scrollProgress = progress
var progressPx = (progress * (bitmapCumWidths.last() - scroll.width)).toInt()
if (lazyScroll) {
layoutVisibleBitmaps()
progressPx -= bitmapCumWidths[lazyIdxStart]
}
println("Scrolling view to x=$progressPx of scrollable ${layout.width} (visible width ${scroll.width})")
scroll.scrollTo(progressPx, 0)
scroll.setScrollProgress(progress)
}
fun setScrollPagesProgress(pagesProgress: Float) {
// NB this is nonlinear with unequal page widths
val p = pagesProgress.toInt()
val progressPx = bitmapCumWidths[p] + (bitmaps[p].width * (pagesProgress % 1F))
val progress = progressPx / (bitmapCumWidths.last() - scroll.width).toFloat()
setScrollProgress(progress)
scroll.setScrollPagesProgress(pagesProgress)
}
}

View File

@ -0,0 +1,92 @@
package com.lhw.pdf.ui
import android.content.Context
import android.graphics.Bitmap
import android.util.DisplayMetrics
import android.view.WindowManager
import android.widget.HorizontalScrollView
import android.widget.ImageView
import android.widget.LinearLayout
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat
class HorizontalGallery(outerContext: Context) : HorizontalScrollView(outerContext) {
private val lazyScroll = android.os.Build.VERSION.SDK_INT < 34 //android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE
private var lazyIdxStart = -1
private var lazyIdxEnd = -1
private val bitmaps = mutableListOf<Bitmap>()
private val bitmapCumWidths = mutableListOf<Int>(0)
private val layout = LinearLayout(this.context)
private var scrollProgress = 0f
init {
addView(layout)
}
fun updateImages(bitmaps: Iterable<Bitmap>) {
println("Updating presentation images")
println("Layout has scale ${layout.scaleX} ${layout.scaleY}")
layout.removeAllViewsInLayout()
this.bitmaps.clear()
bitmapCumWidths.clear()
bitmapCumWidths.add(0)
bitmaps.forEach {
this.bitmaps.add(it)
bitmapCumWidths.add(it.width + bitmapCumWidths.last())
}
if (lazyScroll) {
lazyIdxStart = -1
lazyIdxEnd = -1
layoutVisibleBitmaps()
} else {
layoutAllBitmaps()
}
}
private fun layoutBitmap(bitmap: Bitmap) {
val img = ImageView(this.context)
img.setImageBitmap(bitmap)
img.minimumWidth = bitmap.width // No idea what broke when I refactored this class
img.minimumHeight = bitmap.height
println("${bitmap.width}x${bitmap.height}")
layout.addView(img)
}
private fun layoutAllBitmaps() {
bitmaps.forEach(::layoutBitmap)
println("Presentation heights $height ${layout.height}")
}
private fun layoutVisibleBitmaps() {
val xStart = (scrollProgress * (bitmapCumWidths.last() - width)).toInt()
val xEnd = xStart + width
// bitmapCumWidths has a prepended 0
val idxStart = bitmapCumWidths.indexOfFirst { it > xStart }.let { if (it >= 1) it-1 else 0 }
val idxEnd = bitmapCumWidths.indexOfFirst { it > xEnd }.let { if (it >= 0) it else bitmaps.size}
layout.removeAllViewsInLayout()
(idxStart..<idxEnd).map(bitmaps::get).forEach(::layoutBitmap)
lazyIdxStart = idxStart
lazyIdxEnd = idxEnd
println("Laying out pages $idxStart up to $idxEnd - scrollable width ${layout.width}")
}
fun setScrollProgress(progress: Float) {
scrollProgress = progress
var progressPx = (progress * (bitmapCumWidths.last() - width)).toInt()
if (lazyScroll) {
layoutVisibleBitmaps()
progressPx -= bitmapCumWidths[lazyIdxStart]
}
println("Scrolling view to x=$progressPx of scrollable ${layout.width} (visible width $width)")
scrollTo(progressPx, 0)
}
fun setScrollPagesProgress(pagesProgress: Float) {
// NB this is nonlinear with unequal page widths
val p = pagesProgress.toInt()
val progressPx = bitmapCumWidths[p] + (bitmaps[p].width * (pagesProgress % 1F))
val progress = progressPx / (bitmapCumWidths.last() - width).toFloat()
setScrollProgress(progress)
}
}