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
Related
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)
}
#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.
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})")
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
)
}
}
I am trying to learn tornadofx and i have come across an error i cant figure out how to solve sadly I am using the filterwhen fun and it works great however when i filter the data i get the error handler telling me i have a string out of range and it happens randomly often when i delete a char from the textfield i know the code is a mess :D
enter code hereclass CenterView : View("My View") {
private val ExcelHandler: ExcelController by inject()
private var content = mutableListOf<Products>().observable()
private var rowcounter = SimpleIntegerProperty()
private var oktorun = SimpleBooleanProperty(true)
val table = TableView<Products>()
val data = SortedFilteredList(content).bindTo(table)
private var Accounts = mutableListOf<String>().observable()
override val root = borderpane() {
bottom{
hbox(10) {
style{
padding = box(10.px)
alignment = Pos.CENTER
}
button("Import"){
addClass(Styles.btmDesign)
style{
backgroundColor += Color.PURPLE
fontFamily = "Comic Sans MS"
}
useMaxWidth = true
enableWhen(oktorun)
action {
oktorun.value = false
runAsync {
ExcelHandler.readExcel("data/test.xlsx")
} ui { loadedText ->
content.isEmpty()
content.addAll(loadedText.observable())
rowcounter.value = loadedText.count()
Accounts.addAll(loadedText.map { it.Account }.toList().distinct()
.observable())
oktorun.value = true
}
}
}
hbox{
label("Rows ")
{
style{
fontSize = 20.px
fontWeight = FontWeight.BOLD
}
}
label {
style{
fontSize = 20.px
fontWeight = FontWeight.BOLD
textFill = Color.GREEN
}
bind(rowcounter)
}
}
textfield {
promptText = "Filter"
data.filterWhen(textProperty()) { query, item ->
item.Account!!.contains(query, ignoreCase = true)
}
}
}
left{
listview(Accounts) {
style{
padding = box(20.px)
fontSize = 20.px
fontWeight = FontWeight.BOLD
}
}
}
center{
style{
prefWidth = 100.px
alignment = Pos.CENTER
padding = box(20.px)
}
tableview(data) {
isEditable = true
style{
fontSize =20.px
fontWeight = FontWeight.EXTRA_BOLD
}
column("External", Products::ExternalProperty)
column("ItemRelation", Products::ItemRelationProperty)
column("Account",Products::AccountProperty)
column("Price", Products::AmmountProperty)
column("currency", Products::ValutaProperty)
column("Date", Products::DateProperty)
column("Status", Products::StatusProperty)
enableDirtyTracking()
columnResizePolicy = SmartResize.POLICY
}.multiSelect(true)
}
right {
}
}
}
}
Thank you very much for your time!
the error is
java.lang.StringIndexOutOfBoundsException: String index out of range:
3 at java.lang.String.charAt(String.java:658) at
com.sun.glass.ui.win.WinTextRangeProvider.GetBoundingRectangles(WinTextRangeProvider.java:314)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method) at
com.sun.glass.ui.win.WinApplication.lambda$null$147(WinApplication.java:177)
at java.lang.Thread.run(Thread.java:748)