How to align VerticalPager page with pager indicators? - kotlin

Pager indicator and pager are in two separate libraries. I've been unable to get the indicators to sit to the right of the page.
#OptIn(ExperimentalPagerApi::class)
#Composable
fun Photos(photos: List<String>){
val state = rememberPagerState()
Row{
VerticalPager(count = photos.size, state = state, contentPadding = PaddingValues(vertical = 32.dp)) {
AsyncImage(model = photos[it], contentDescription = null, modifier = Modifier.fillMaxSize())
}
VerticalPagerIndicator(pagerState = state)
}
}
I've tried setting a custom width for the AsyncImage but it's not giving me what I'm expecting which is enough space for the indicator to sit horizontally next to the page.

Set verticalAlignment to Alignment.CenterVertically, it's Alignment.Top by default
Row(
verticalAlignment = Alignment.CenterVertically
){
VerticalPager(count = photos.size, state = state, contentPadding = PaddingValues(vertical = 32.dp)) {
AsyncImage(model = photos[it], contentDescription = null, modifier = Modifier.fillMaxSize())
}
VerticalPagerIndicator(pagerState = state)
}

Related

Compose onValueChange behaviour isn't consistent

I'm making a sudoku game and solver. For my user interface I used LazyVerticalGrid to create a 9x9 grid. I successfully made it so when you click on a cell it will only accept digits [1-9] via an OutLinedTextField. I then added a conditional that only empty cells would have the text field applied. That worked and only those cells could be altered but when I do that the logic that only accepts digits doesn't work and the program crashes. If I comment out the conditional statement and the OutLinedTextField is applied to all cells it works again. I get the following error.
Also if I add conditionals for backgroundColor or Content Color the same thing happens and the program crashes if a non digit is pressed. I'm not sure why the conditionals affect the onValueChange logic. Why is this and how do I fix it?
fun displayPuzzle(answer: Array<Array<IntArray>>) {
var list: SnapshotStateList<String> = mutableStateListOf()
for (x in answer[0]) list.addAll(x.map { it.toString() })
var columnHeighty by remember { mutableStateOf(0F) }
var columnWidthx by remember { mutableStateOf(0f) }
var pad = 20.dp
LazyVerticalGrid(
columns = GridCells.Fixed(9),
contentPadding = PaddingValues(
start = pad,
top = pad,
end = pad,
bottom = pad
)
) {
items(list.size) { index ->
Card(
shape = RectangleShape,
backgroundColor = Color.Red,
modifier = Modifier
.requiredWidth(83.dp)
.fillMaxWidth()
.fillMaxHeight()
.onGloballyPositioned { coordinates ->
columnWidthx = coordinates.size.width.toFloat()
columnHeighty = coordinates.size.height.toFloat()
},
//backgroundColor = if (list[index].toInt() == 0) Color.Yellow else Color.White ,
//contentColor = if (list[index].toInt() == 0) Color.Blue else Color.Black ,
border = BorderStroke(width = 1.dp, color = Color.Black)
) {
Text(
text = list[index],
fontWeight = FontWeight.Bold,
fontSize = 30.sp,
color = Color(0xFF000000),
textAlign = TextAlign.Center,
modifier = Modifier
.padding(23.dp)
.clickable { }
)
}
// When the if statement is included the program crashes on a non digit entry
//if (list[index].toInt() == 0) {
val pattern = remember { Regex("[1-9]") }
var value by remember { mutableStateOf("") }
OutlinedTextField(
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
colors = TextFieldDefaults.outlinedTextFieldColors(cursorColor = Color.Transparent),
textStyle = TextStyle(color = Color.Red),
modifier = Modifier
.fillMaxHeight()
.padding(vertical = 10.dp, horizontal = 10.dp),
value = value,
onValueChange = { if (it.isEmpty() || (it.matches(pattern) && (it.length == 1)))
value = it
list[index] = value}
)
//}
}
}
Your game crashed because you trying to convert for example 'a' to Int value and runtime throws NumberFormatException.
You need to use:
if (list[index].toIntOrNull() == null)
This condition will be triggered if a non-decimical number is obtained from your SnapshotStateList
Explanation: toIntOrNull() returns Int from String (example: "4".toIntOrNull() - returns 4) otherwise it returns null

How can i make this animation stop after completion in Jetpack Compose or not be infinite

#Composable
fun Gojo(
maxWidth:Dp,
maxHeight:Dp,)
{
val resource: Painter
val modifier: Modifier
val gojoSize = 200.dp
val infiniteTransition = rememberInfiniteTransition()
val posistionState = infiniteTransition.animateFloat(
initialValue = 0f,
targetValue = 1f,
animationSpec = infiniteRepeatable(
animation = tween(
durationMillis = 1000,
easing = LinearEasing
),
repeatMode=RepeatMode.Reverse
)
)
if(posistionState.value<=0.1f) {
modifier = Modifier.offset(
x = -140.dp,
y = maxHeight * 0.75f,
).rotate(50.0F)
}
else if(posistionState.value<=0.2f){
modifier = Modifier.offset(
x = -100.dp,
y = maxHeight * 0.75f,
).rotate(50.0F)
}
else if(posistionState.value<=0.25f){
modifier = Modifier.offset(
x = -100.dp,
y = maxHeight * 0.75f,
).rotate(0.0F)
}
else if(posistionState.value<=0.3f){
modifier = Modifier.offset(
x = -100.dp+(maxWidth*posistionState.value),
y = maxHeight * 0.75f,
).rotate(50.0F)
}
else{
modifier = Modifier.offset(
x = maxWidth * 0.25f,
y = maxHeight * 0.75f,
)
}
resource=painterResource(R.drawable.gojo)
Image(modifier=modifier.width(gojoSize).height(gojoSize),painter = resource, contentDescription ="gojo sama")
}
you are asking for not to be infinite and using infinite transition? just use animateDpAsState and change size of the image by using the dp values. If you want to start the transition when the item has composed just call a LaunchedEffect (true) {startTransition = true} by remembering the startTransition value as false in the beginning:
var startTransition by remember {
mutableStateOf(false)
}
LaunchedEffect(true){
startTransition = true
}
val size = animateDpAsState(
targetValue = if(startTransition == false)
0.dp
else
/*Your Desired Value*/
)
// And use size in Image. You can create different animateDpAsState values for width and height.

How to monitor mouse point move entered a path in Jetpack Compose?

I got a problem on how to detect mouse pointer entered a path or reach in Jetpack Compose canvas, what I want is something like isPointInPath()in JavaScript: when my mouse moved into the react area in canvas, I want to change the react color into green.
My current code is blow, I wanted to make the rectangle change color like the white dot on the canvas in the code, I searched on google android doc, but I got nothing, any thing helpful will be appriciated:
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.awaitFirstDown
import androidx.compose.foundation.gestures.forEachGesture
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.*
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.*
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.input.pointer.PointerEventType
import androidx.compose.ui.input.pointer.onPointerEvent
import androidx.compose.ui.input.pointer.pointerInput
data class PathProperties(val Angle: Float, val length: Float, val startPoint: Pair<Float, Float>)
#OptIn(ExperimentalComposeUiApi::class)
#Composable
fun customCanvas(){
var currentPosition by remember { mutableStateOf(Offset.Unspecified) }
var previousPosition by remember { mutableStateOf(Offset.Unspecified) }
val randomAngle = listOf(45f, -45f)
var paths = remember { mutableStateListOf<Pair<Path, PathProperties>>() }
var currentPath by remember { mutableStateOf(Path()) }
var show by remember { mutableStateOf(false) }
Canvas(
modifier = Modifier
.fillMaxSize()
.background(color = Color.Gray)
.pointerInput(Unit) {
forEachGesture {
awaitPointerEventScope {
awaitFirstDown().also {
currentPosition = it.position
previousPosition = currentPosition
currentPath.moveTo(currentPosition.x, currentPosition.y)
val angle = randomAngle.random()
paths.add(Pair(currentPath, PathProperties(angle, 30f, Pair(currentPosition.x, currentPosition.y))))
}
}
}
}
.onPointerEvent(PointerEventType.Move) {
val position = it.changes.first().position
show = (position.x in 90f..110f) && position.y in 90f..110f
}
){
with(drawContext.canvas.nativeCanvas) {
val checkPoint = saveLayer(null, null)
paths.forEach { it: Pair<Path, PathProperties> ->
rotate(it.second.Angle, it.second.startPoint.first, it.second.startPoint.second )
drawLine(
color = Color.Black,
start = Offset(it.second.startPoint.first, it.second.startPoint.second ),
end = Offset(it.second.startPoint.first + it.second.length, it.second.startPoint.second),
cap = StrokeCap.Round
)
// draw a widder line on canvas using drawLine
drawLine(
color = Color.White,
start = Offset(it.second.startPoint.first, it.second.startPoint.second ),
end = Offset(it.second.startPoint.first + it.second.length, it.second.startPoint.second),
strokeWidth = 10f,
cap = StrokeCap.Square
)
rotate(-it.second.Angle, it.second.startPoint.first, it.second.startPoint.second)
}
// draw a white dot example
drawCircle(
color = if (show) Color.Green else Color.White,
center= Offset(100f, 100f),
radius = 10f,
)
}
}
}

UI doesn't update when mutableStateOf changes

I have #Composable item - ThumbButton and Text which displays current likes number. When I click button I want to increment likes number. I don't know why it doesn't work
val likesCounter = remember { mutableStateOf(0)}
Row(
modifier = Modifier.wrapContentSize(),
verticalAlignment = Alignment.CenterVertically
) {
ThumbButton(
iconSize = sizeButton,
isSelected = isActive,
onClick = { likesCounter.value = likesCounter.value+1 }
)
Text(text = "($likesCounter)")
}
Try referencing the value property while displaying it?
Text(text = "(${likesCounter.value})")

Jetpack Compose offset image vector in Canvas

I have a problem with vector image in Canvas. As shown below I can just call vector image but I can’t make any offset in Canvas. So I only can have it the way it is.
I don't know the reason why there is no Offset option like in drawCircle or drawRect, if someone has some ideas it would be great.
val vector = ImageVector.vectorResource(id = R.drawable.ic_test)
val painter = rememberVectorPainter(image = vector)
Box(contentAlignment = Alignment.Center) {
Canvas(
modifier = Modifier
.fillMaxWidth()
.padding(10.dp)
) {
with(painter) {
draw(
painter.intrinsicSize
)
}
}
}
I tried something like adding Offset into with(painter) but nothing changes:
with(painter) {
draw(
painter.intrinsicSize
)
Offset(x = 10f, y = 10f)
}
You can use DrawScope.translate:
translate(left = 10f, top = 10f) {
with(painter) {
draw(
painter.intrinsicSize
)
}
}