Skip to content

Commit

Permalink
Added zoom controls to PdfViewer, as well as parameters for customizi…
Browse files Browse the repository at this point in the history
…ng them + bitmap scale for documents with tiny details or text
  • Loading branch information
arcanegolem committed May 6, 2024
1 parent 798e5b0 commit 8b3551e
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 25 deletions.
6 changes: 5 additions & 1 deletion app/src/main/java/ru/spektrit/composepdf/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import ru.spektrit.composepdf.ui.theme.ComposePDFTheme
import ru.spektrit.lycoris.viewdocument.PdfViewer
Expand All @@ -17,7 +18,10 @@ class MainActivity : ComponentActivity() {
Column(
modifier = Modifier.fillMaxSize(),
) {
PdfViewer(pdfResId = R.raw.sample_multipage)
PdfViewer(
pdfResId = R.raw.horizontal,
controlsAlignment = Alignment.CenterEnd,
)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.produceState
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.Dispatchers
Expand All @@ -34,6 +36,10 @@ fun PdfViewer(
modifier: Modifier = Modifier,
@RawRes pdfResId: Int,
verticalArrangement: Arrangement.Vertical = Arrangement.spacedBy(8.dp),
iconTint : Color = Color.Black,
accentColor : Color = Color.DarkGray,
controlsAlignment: Alignment = Alignment.BottomEnd,
bitmapScale : Int = 1
) {
val documentIdentifier = pdfResId.toString()

Expand All @@ -58,12 +64,16 @@ fun PdfViewer(
}

PdfViewerDisplay(
accentColor = accentColor,
modifier = modifier,
context = context,
renderer = renderer,
documentIdentifier = documentIdentifier,
verticalArrangement = verticalArrangement,
mutex = mutex
mutex = mutex,
controlsAlignment = controlsAlignment,
iconTint = iconTint,
bitmapScale = bitmapScale
)
}

Expand All @@ -80,6 +90,10 @@ fun PdfViewer(
modifier: Modifier = Modifier,
uri: Uri,
verticalArrangement: Arrangement.Vertical = Arrangement.spacedBy(8.dp),
accentColor: Color = Color.DarkGray,
iconTint: Color = Color.Black,
controlsAlignment: Alignment = Alignment.BottomEnd,
bitmapScale : Int = 1
) {
val rendererScope = rememberCoroutineScope()
val mutex = remember { Mutex() }
Expand All @@ -100,12 +114,16 @@ fun PdfViewer(
}

PdfViewerDisplay(
accentColor = accentColor,
modifier = modifier,
context = context,
renderer = renderer,
documentIdentifier = uri.toString(),
verticalArrangement = verticalArrangement,
mutex = mutex
mutex = mutex,
controlsAlignment = controlsAlignment,
iconTint = iconTint,
bitmapScale = bitmapScale
)
}

Expand All @@ -124,6 +142,10 @@ fun PdfViewer(
@Url url: String,
headers: HashMap<String, String>? = null,
verticalArrangement: Arrangement.Vertical = Arrangement.spacedBy(8.dp),
accentColor: Color = Color.DarkGray,
iconTint: Color = Color.Black,
controlsAlignment: Alignment = Alignment.BottomEnd,
bitmapScale : Int = 1
) {

val rendererScope = rememberCoroutineScope()
Expand All @@ -144,12 +166,16 @@ fun PdfViewer(
}

PdfViewerDisplay(
accentColor = accentColor,
modifier = modifier,
context = context,
renderer = renderer,
documentIdentifier = url,
verticalArrangement = verticalArrangement,
mutex = mutex
mutex = mutex,
controlsAlignment = controlsAlignment,
iconTint = iconTint,
bitmapScale = bitmapScale
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ import android.util.Log
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.rememberTransformableState
import androidx.compose.foundation.gestures.scrollBy
import androidx.compose.foundation.gestures.transformable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxWithConstraints
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxWidth
Expand All @@ -19,8 +21,11 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.Search
import androidx.compose.material.icons.rounded.ZoomIn
import androidx.compose.material.icons.rounded.ZoomOut
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.IconButtonDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
Expand Down Expand Up @@ -59,7 +64,13 @@ internal fun PdfViewerDisplay(
documentIdentifier : String,
verticalArrangement: Arrangement.Vertical,
mutex : Mutex,
accentColor : Color,
iconTint : Color,
controlsAlignment: Alignment,
bitmapScale : Int
) {
val pdfViewerDisplayScope = rememberCoroutineScope()

val imageLoader = context.imageLoader
val imageLoadingScope = rememberCoroutineScope()

Expand Down Expand Up @@ -95,9 +106,45 @@ internal fun PdfViewerDisplay(
}


val transformableState = rememberTransformableState { zoomChange, panChange, _ ->
viewerScale = (viewerScale * zoomChange).coerceIn(1f, 10f)
if (pageCount > 2) {
Column(
modifier = Modifier
.align(controlsAlignment)
.padding(8.dp)
.zIndex(2f)
) {
IconButton(
onClick = { viewerScale = (viewerScale + 0.5f).coerceIn(1f, 10f) },
colors = IconButtonDefaults.iconButtonColors(
containerColor = accentColor.copy(alpha = 0.4f)
)
) {
Icon(
imageVector = Icons.Rounded.ZoomIn,
contentDescription = "Zoom in",
tint = iconTint
)
}
IconButton(
onClick = {
viewerScale = 1f
viewerOffset = Offset(0f, 0f)
},
colors = IconButtonDefaults.iconButtonColors(
containerColor = accentColor.copy(alpha = 0.4f)
)
) {
Icon(
imageVector = Icons.Rounded.ZoomOut,
contentDescription = "Zoom out",
tint = iconTint
)
}
}
}


val transformableState = rememberTransformableState { _, panChange, _ ->
val extraWidth = (viewerScale - 1) * constraints.maxWidth
val extraHeight = (viewerScale - 1) * constraints.maxHeight

Expand All @@ -106,8 +153,9 @@ internal fun PdfViewerDisplay(

viewerOffset = Offset(
x = (viewerOffset.x + panChange.x * viewerScale).coerceIn(-maxX, maxX),
y = (viewerOffset.y + panChange.y * viewerScale).coerceIn(-maxY, maxY),
y = (viewerOffset.y + (panChange.y / 2) * viewerScale).coerceIn(-maxY, maxY),
)
pdfViewerDisplayScope.launch{ lazyListState.scrollBy(-(panChange.y / 2)) }
}
LazyColumn(
userScrollEnabled = viewerScale == 1f,
Expand Down Expand Up @@ -146,7 +194,7 @@ internal fun PdfViewerDisplay(
try {
renderer?.let {
it.openPage(index).use { page ->
destinationBitmap = Bitmap.createBitmap(page.width, page.height, Bitmap.Config.ARGB_8888)
destinationBitmap = Bitmap.createBitmap(page.width * bitmapScale, page.height * bitmapScale, Bitmap.Config.ARGB_8888)
page.render(destinationBitmap!!, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY)
}
}
Expand All @@ -171,15 +219,6 @@ internal fun PdfViewerDisplay(
.build()

Box {
Icon(
modifier = Modifier
.align(Alignment.BottomEnd)
.padding(15.dp)
.zIndex(1f),
imageVector = Icons.Rounded.Search,
contentDescription = "Magnify Indicator"
)

Image(
modifier = Modifier
.background(Color.White)
Expand All @@ -198,12 +237,14 @@ internal fun PdfViewerDisplay(
}
}

Text(
modifier = Modifier
.align(Alignment.TopEnd)
.padding(10.dp)
.zIndex(1f),
text = "${currentPage + 1}/$pageCount"
)
if (pageCount > 2) {
Text(
modifier = Modifier
.align(Alignment.TopEnd)
.padding(10.dp)
.zIndex(1f),
text = "${currentPage + 1}/$pageCount"
)
}
}
}

0 comments on commit 8b3551e

Please sign in to comment.