Make `TextField` look active without it having a default value - kotlin

I was wondering how I would go about making a TextField always look active:
Without it actually having a default value like the TextField in the screenshot does
My current code for the TextField in the screenshot is:
TextField(
value = npcId.toString(),
onValueChange = { npcId = it.toInt() },
label = { Text("Npc id") },
enabled = true
)

So essentially you do not want the default value to display in the TextField.
If the default value is -1 in this case, the following should work:
TextField(
value = if (npcID == -1) "" else npcId.toString(),
onValueChange = { npcId = it.toInt() },
label = { Text("Npc id") },
enabled = true
)

I succeded with this way.It is here source code:
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.material.TextField
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.platform.LocalTextInputService
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.tooling.preview.Preview
import kotlinx.coroutines.delay
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MainScreen()
}
}
}
#Composable
fun MainScreen() {
Surface(
modifier = Modifier.fillMaxSize()
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
AutoFocusingText()
}
}
}
#Composable
fun AutoFocusingText() {
val focusRequester = remember { FocusRequester() }
val inputService = LocalTextInputService.current
val focus = remember { mutableStateOf(true) }
val text = remember { mutableStateOf("-1")}
TextField(
value = if (text.value == "-1") "" else text.value,
onValueChange = {
text.value = it
},
label = { Text("Npc id") },
keyboardOptions = KeyboardOptions.Default.copy(keyboardType = KeyboardType.Number),
modifier = Modifier
.focusRequester(focusRequester)
.onFocusChanged {
if (focus.value != it.isFocused) {
focus.value = it.isFocused
if (!it.isFocused) {
inputService?.hideSoftwareKeyboard()
}
}
}
)
LaunchedEffect(true) {
delay(100)
inputService?.showSoftwareKeyboard()
focusRequester.requestFocus()
}
}
#ExperimentalComposeUiApi
#Preview(showBackground = true)
#Composable
fun DefaultPreview() {
MainScreen()
}

Related

Jetpack Compose: TextField aligns outside of AlertDialog as text grows

If you run the following composable and enter a long multiline text into the textfield, you will see that as the text grows, the textfield leaves the AlertDialog.
Is there a way to fix this?
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
#Preview
#Composable
fun MyComposable() {
var text by remember {
mutableStateOf("Press enter a couple of times to see the problem")
}
AlertDialog(
onDismissRequest = { },
title = {
OutlinedTextField(
value = text,
onValueChange = { text = it },
textStyle = MaterialTheme.typography.h5,
label = { Text(text = "Text") },
modifier = Modifier
.fillMaxWidth()
.height(150.dp)
)
},
confirmButton = {
TextButton(
onClick = {}
) {
Text("Done")
}
},
dismissButton = {
TextButton(
onClick = { }
) {
Text("Cancel")
}
}
)
}
Modifier.heightIn constrain the height of the content to be between mindp and maxdp as permitted by the incoming measurement Constraints. If the incoming constraints are more restrictive the requested size will obey the incoming constraints and attempt to be as close as possible to the preferred size.
Column {
var text by remember { mutableStateOf("some text")}
OutlinedTextField(value = text,
onValueChange = {text = it},
textStyle = MaterialTheme.typography.headlineSmall,
label = { Text(text = "Text") },
modifier = Modifier.fillMaxWidth()
.heightIn(min = 0.dp, max = 150.dp))
}
Textfield will grow to max height specified in heightIn modifier and then start scrolling.

Jetpack Compose imitates Twitter user homepage

Because scrolling nesting cannot be used, I used the following method to achieve the scrolling nesting effect.
However, the effect is not ideal, and the scroll position of the list cannot be handled well when switching between pages.
Is my way the best solution? Is there a better solution to this problem?
Or how can this solution of mine solve the problem of alignment of the scroll position of the list?
YouTube Video
package com.feifeng.my
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyGridState
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.rememberLazyGridState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Person
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
import androidx.compose.ui.input.nestedscroll.NestedScrollSource
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.feifeng.app.theme.FlywindTheme
import com.google.accompanist.pager.*
import kotlinx.coroutines.launch
import kotlin.math.roundToInt
#ExperimentalPagerApi
#ExperimentalMaterial3Api
#Composable
fun UserView() {
Scaffold(
topBar = {
SmallTopAppBar(title = {
Text(text = "User Home")
})
},
content = {
UserContent()
}
)
}
#ExperimentalPagerApi
#Composable
fun UserContent() {
val userGridState = rememberLazyGridState()
val likeGridState = rememberLazyGridState()
val favoriteGridState = rememberLazyGridState()
val headerOffsetY = rememberSaveable { mutableStateOf(0f) }
val headerHeight = rememberSaveable { mutableStateOf(0) }
val pagerState = rememberPagerState()
Box(modifier = Modifier.fillMaxSize()) {
HorizontalPager(count = 3, state = pagerState, itemSpacing = 16.dp) { page ->
if (page == 0) {
UserContentColumn(30, userGridState, headerHeight.value) {
headerOffsetY.value = it
}
}
if (page == 1) {
UserContentColumn(10, likeGridState, headerHeight.value) {
headerOffsetY.value = it
}
}
if (page == 2) {
UserContentColumn(3, favoriteGridState, headerHeight.value) {
headerOffsetY.value = it
}
}
}
Column(modifier = Modifier
.offset {
IntOffset(x = 0, y = headerOffsetY.value.roundToInt())
}
.background(Color.White)
.onSizeChanged { headerHeight.value = it.height }) {
Row(modifier = Modifier.padding(16.dp)) {
Icon(imageVector = Icons.Filled.Person,
contentDescription = "user",
tint = Color.Gray,
modifier = Modifier.size(80.dp))
Text(text = "User Name", modifier = Modifier.padding(16.dp), fontSize = 24.sp)
}
Text(text = "User Bio", modifier = Modifier.padding(16.dp))
UserTabBar(titleList = listOf("Video", "Like", "Favorite"), pagerState = pagerState)
}
}
}
#Composable
fun UserContentColumn(count: Int, state: LazyGridState, headerHeight: Int, onScroll: (Float) -> Unit) {
val offsetY = rememberSaveable { mutableStateOf(0f) }
val scrollConnection = remember {
object : NestedScrollConnection {
override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
offsetY.value = offsetY.value + available.y
if (offsetY.value > 0) {
offsetY.value = 0f
}
onScroll(offsetY.value)
return Offset.Zero
}
}
}
val current = LocalDensity.current
LazyVerticalGrid(state = state,
columns = GridCells.Fixed(2),
horizontalArrangement = Arrangement.spacedBy(3.dp),
verticalArrangement = Arrangement.spacedBy(3.dp),
contentPadding = PaddingValues(top = current.run { headerHeight.toDp() } + 3.dp, start = 3.dp, end = 3.dp),
modifier = Modifier.nestedScroll(scrollConnection)) {
items(count = count) {
Text(text = "Grid Item",
modifier = Modifier
.fillMaxWidth()
.height(100.dp)
.background(Color.Yellow)
.padding(32.dp))
}
}
}
#ExperimentalPagerApi
#Composable
fun UserTabBar(titleList: List<String>, pagerState: PagerState) {
val scope = rememberCoroutineScope()
androidx.compose.material.TabRow(
selectedTabIndex = pagerState.currentPage,
indicator = { tabPositions ->
TabRowDefaults.Indicator(
Modifier.pagerTabIndicatorOffset(pagerState, tabPositions)
)
},
backgroundColor = Color.White,
contentColor = MaterialTheme.colorScheme.primary) {
titleList.forEachIndexed { index, title ->
Tab(
text = { Text(text = title) },
selected = pagerState.currentPage == index,
onClick = {
scope.launch {
pagerState.scrollToPage(index)
}
}
)
}
}
}
#ExperimentalPagerApi
#ExperimentalMaterial3Api
#Preview
#Composable
fun PreviewTest() {
UserView()
}

Jetpack Compose First Try - Correct Usage and what can I do better?

I build a really small practicing application, but I found some Questions.
package com.example.jetrecept
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.sharp.Add
import androidx.compose.material.icons.sharp.Delete
import androidx.compose.material.icons.sharp.Edit
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import com.example.jetrecept.ui.theme.JetReceptTheme
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
JetReceptTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colors.background
) {
MainContent()
}
}
}
}
}
#Preview(showBackground = true)
#Composable
fun MainContent() {
var recipeTitle by remember { mutableStateOf("") }
val ingredientList = remember { mutableStateListOf<Ingredient>() }
var amount by remember { mutableStateOf("") } // Change to Double
var unit by remember { mutableStateOf("") }
var notation by remember { mutableStateOf("") }
RecipeContent(
recipeTitle = recipeTitle,
onRecipeTitleChange = { recipeTitle = it },
ingredientList = ingredientList,
onIngredientListUpdate = { ingredient: Ingredient, i: Int -> ingredientList[i] = ingredient},
onIngredientListAdd = { ingredientList.add(it) },
onIngredientListRemoveItem = { ingredientList.removeAt(it)},
amount = amount,
onAmountChange = { amount = it},
unit = unit,
onUnitChange = { unit = it},
notation = notation,
onNotationChange = { notation = it}
)
RecipeHeader(
recipeTitle = recipeTitle
)
}
#Composable
fun RecipeHeader(
recipeTitle: String
) {
//JetReciptTheme {
Column {
//Text(text="recipetitle: $recipeTitle") // Just for testing, if hoisting works
}
//}
}
#Composable
fun RecipeContent(
recipeTitle: String,
onRecipeTitleChange: (String) -> Unit,
ingredientList: MutableList<Ingredient>,
onIngredientListAdd: (Ingredient) -> Unit,
onIngredientListUpdate: (Ingredient, Int) -> Unit,
onIngredientListRemoveItem: (Int) -> Unit,
amount: String, // change to Double,
onAmountChange: (String) -> Unit, //change to (Double) -> Unit,
unit: String,
onUnitChange: (String) -> Unit,
notation: String,
onNotationChange: (String) -> Unit
) {
Column(modifier = Modifier
.fillMaxSize()
.padding(21.dp)) {
// Headline
Text(text="Add new recipe",
modifier = Modifier
.fillMaxWidth()
.padding(34.dp),
textAlign = TextAlign.Center)
// Title of recipe - input
SectionHeadline(title = "Recipename")
TextField(
value = recipeTitle,
onValueChange = { onRecipeTitleChange(it) },
modifier = Modifier
.fillMaxWidth()
.padding(bottom = 34.dp),
// Keyboard Action fehlt noch
)
// Ingredient - section
SectionHeadline(title = "Ingredients")
// Writing headline over the Ingredient table
if (ingredientList.isNotEmpty()) {
IngredientDescription(
modifier = Modifier.padding(bottom=4.dp),
firstColumn = "Nr.",
secondColumn = "Amount",
thirdColumn = "Unit",
fourthColumn = "Notation"
)
Divider(modifier = Modifier
.height(10.dp)
.padding(bottom = 4.dp, top = 4.dp))
}
// Print all Ingredients to an Row
ingredientList.mapIndexed { index, ingredient -> IngredientRow(
id = index,
ingredient = ingredient,
onIngredientListUpdate = onIngredientListUpdate,
onIngredientListRemoveItem = onIngredientListRemoveItem,
amount = amount,
onAmountChange = onAmountChange,
unit = unit,
onUnitChange = onUnitChange,
notation = notation,
onNotationChange = onNotationChange
)
}
// Ingredient input row
Row {
TextField(
value = amount,
onValueChange = { onAmountChange(it)},
modifier = Modifier
.width(100.dp)
.padding(end = 8.dp),
label = { Text(text="amount") },
singleLine = true
)
TextField(
value = unit,
onValueChange = { onUnitChange(it)},
modifier = Modifier
.width(80.dp)
.padding(end = 8.dp),
label = { Text(text = "unit") },
singleLine = true
)
TextField(
value = notation,
onValueChange = { onNotationChange(it)},
modifier = Modifier.weight(1F),
label = { Text(text = "notation")},
singleLine = true
)
}
Spacer(modifier= Modifier.height(8.dp))
// Add - Button, adding Ingredients
IconButton(
buttonText = "add",
icon = Icons.Sharp.Add,
iconDescription = "add icon",
enabled = amount.isNotBlank() && unit.isNotBlank() && notation.isNotBlank(),
onClick = {
onIngredientListAdd(Ingredient(amount=amount, unit=unit, notation=notation))
onAmountChange(""); onUnitChange(""); onNotationChange("")
})
}
}
#Composable
fun IngredientRow(
id: Int = 1,
ingredient: Ingredient,
onIngredientListUpdate: (Ingredient, Int) -> Unit,
onIngredientListRemoveItem: (Int) -> Unit,
amount: String,
onAmountChange: (String) -> Unit,
unit: String,
onUnitChange: (String) -> Unit,
notation: String,
onNotationChange: (String) -> Unit
) {
var buttonVisibility by remember { mutableStateOf(false)}
var showEditDialog by remember { mutableStateOf(false)}
Column( modifier = Modifier.fillMaxWidth()) {
IngredientDescription(
modifier = Modifier.clickable { buttonVisibility = !buttonVisibility },
firstColumn = "$id",
secondColumn = ingredient.amount,
thirdColumn = ingredient.unit,
fourthColumn = ingredient.notation
)
if (buttonVisibility) {
Row(modifier = Modifier
.padding(bottom = 8.dp, top = 8.dp)
.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceEvenly
) {
IconButton(
buttonText = "edit",
icon = Icons.Sharp.Edit,
iconDescription = "edit icon",
onClick = {
onAmountChange( ingredient.amount)
onUnitChange( ingredient.unit)
onNotationChange( ingredient.notation)
showEditDialog = true}
)
IconButton(
buttonText = "delete",
icon = Icons.Sharp.Delete,
iconDescription = "delete icon",
onClick = { onIngredientListRemoveItem(id) }
)
}
}
Divider(modifier = Modifier
.height(10.dp)
.padding(bottom = 4.dp, top = 4.dp))
if (showEditDialog) {
AlertDialog(
onDismissRequest = {
onAmountChange(""); onUnitChange(""); onNotationChange("")
showEditDialog = false},
title = {Text(text="Edit ingredient")},
text = {
Column {
Text(text="Amount:")
TextField(value = amount, onValueChange = { onAmountChange(it) })
Text(text="Unit:")
TextField(value = unit, onValueChange = { onUnitChange(it) })
Text(text="Notation:")
TextField(value = notation, onValueChange = { onNotationChange(it) })
}
},
confirmButton = { onIngredientListUpdate(
Ingredient(amount= amount, unit= unit, notation= notation), id)
Button(onClick = {
showEditDialog = false
buttonVisibility = false
onAmountChange(""); onUnitChange(""); onNotationChange("")}) {
Text(text = "apply")
}
},
dismissButton = {
Button(onClick = {
showEditDialog = false
buttonVisibility = false
onAmountChange(""); onUnitChange(""); onNotationChange("")}) {
Text(text = "discard")
}
}
)
}
}
}
#Composable
fun SectionHeadline(title: String) {
Text(text = title)
Divider(modifier = Modifier.height(2.dp))
Spacer(modifier = Modifier.height(8.dp))
}
#Composable
fun IngredientDescription(
modifier: Modifier = Modifier,
firstColumn: String, secondColumn: String, thirdColumn: String, fourthColumn:String) {
Row( modifier = modifier
.fillMaxWidth()
.padding(bottom = 4.dp, top = 4.dp),
verticalAlignment = Alignment.CenterVertically
) {
Text(text = firstColumn, modifier = Modifier.width(30.dp), textAlign = TextAlign.Center)
Text(text = secondColumn, modifier = Modifier.width(60.dp), textAlign = TextAlign.Center)
Text(text = thirdColumn, modifier = Modifier.width(50.dp), textAlign = TextAlign.Center)
Text(text = fourthColumn, modifier = Modifier.weight(1F))
}
}
#Composable
fun IconButton(
buttonText: String,
icon: ImageVector,
enabled: Boolean = true,
iconDescription: String,
onClick: () -> Unit
) {
Button(onClick = onClick, enabled = enabled) {
Text(text=buttonText, modifier = Modifier.padding(end=5.dp))
Icon(imageVector = icon, contentDescription = iconDescription)
}
}
// data class Ingredient (var amount: Double, var unit: String, var notation: String)
data class Ingredient (var amount: String, var unit: String, var notation: String)
Is the way of hoisting correct? I mean, I take most of the states out of the Composables but some states inside are just for internal working. Should I also take this out of the Composable to make it complete stateless (buttonVisibility and showEditDialog)?
Are there any things I can do better?

How to vertically align the text and leading/trailing icons in a TextField

Is there a way to set the trailing/leading icons and the text on the same level? On default it is not as shown in the image below. I tried changing the fontStyle parameter in TextField but no success. The text is shown higher than the icons
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material.Icon
import androidx.compose.material.OutlinedTextField
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowForward
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.window.singleWindowApplication
fun main() = singleWindowApplication {
var text by remember { mutableStateOf("TEXT") }
OutlinedTextField(
value = text,
onValueChange = { text = it },
modifier = Modifier.fillMaxWidth(),
leadingIcon = {
Icon(contentDescription = null,
imageVector = Icons.Default.ArrowForward)
},
trailingIcon = {
Icon(contentDescription = null,
imageVector = Icons.Default.ArrowForward)
})
}
There are several solutions. For desktop Compose, offset the icons. For mobile Compose, adjust the baseline. And finally, just create a custom TextField.
The icons may have extra padding at the bottom. It could also be that the icons and text are always aligned to the top. You could replace the icons with ones that have no bottom padding or shift the icons up. You can tell that the icons are affecting the vertical alignment because if you comment out your icons, the text does center vertically. You could also try reducing the size of the icons.
On desktop Compose, shift the icons up:
OutlinedTextField(
value = text,
onValueChange = { text = it },
modifier = Modifier.fillMaxWidth(),
leadingIcon = {
Icon(
modifier = Modifier.offset(y = -3.dp),
contentDescription = null,
imageVector = Icons.Default.ArrowForward
)
},
trailingIcon = {
Icon(
modifier = Modifier.offset(y = -3.dp),
contentDescription = null,
imageVector = Icons.Default.ArrowForward
)
})
On mobile devices, you can adjust the baseline of the text:
OutlinedTextField(
value = text,
textStyle = TextStyle(baselineShift = BaselineShift(-0.2f)),
onValueChange = { text = it },
modifier = Modifier.fillMaxWidth(),
leadingIcon = {
Icon(
contentDescription = null,
imageVector = Icons.Default.ArrowForward
)
},
trailingIcon = {
Icon(
contentDescription = null,
imageVector = Icons.Default.ArrowForward
)
})
Here is also a custom TextField:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
CustomTextField(
initialText = "cool",
onValueChange = {
},
onLeftButtonClick = {
},
onRightButtonClick = {
}
)
}
}
}
#Composable
fun CustomTextField(
initialText: String,
onValueChange: (text: String) -> Unit,
onLeftButtonClick: () -> Unit,
onRightButtonClick: () -> Unit
) {
var text by remember { mutableStateOf(initialText) }
Row(
modifier = Modifier
.fillMaxWidth()
.wrapContentSize()
.background(color = Color.White, shape = RoundedCornerShape(8.dp))
.border(width = 1.dp, shape = RoundedCornerShape(8.dp), color = Color(0xFF585858))
) {
ConstraintLayout(
modifier = Modifier.fillMaxWidth()
) {
val (left, mid, right) = createRefs()
IconButton(onClick = onLeftButtonClick,
modifier = Modifier.constrainAs(left) {
start.linkTo(parent.start, margin = 10.dp)
top.linkTo(parent.top)
bottom.linkTo(parent.bottom)
}) {
Icon(
contentDescription = null,
imageVector = Icons.Default.ArrowForward,
)
}
IconButton(onClick = onRightButtonClick,
modifier = Modifier.constrainAs(right) {
end.linkTo(parent.end, margin = 10.dp)
top.linkTo(parent.top)
bottom.linkTo(parent.bottom)
}) {
Icon(
contentDescription = null,
imageVector = Icons.Default.ArrowForward,
)
}
TextField(
value = text,
onValueChange = {
text = it
onValueChange(it)
},
colors = TextFieldDefaults.textFieldColors(
backgroundColor = Color.White
),
modifier = Modifier
.offset(y = 4.dp)
.constrainAs(mid) {
start.linkTo(left.end, margin = 10.dp)
top.linkTo(parent.top)
end.linkTo(right.start, margin = 10.dp)
bottom.linkTo(parent.bottom)
width = Dimension.fillToConstraints
})
}
}

kotlin.NotImplementedError: An operation is not implemented: not implemented AlertDialog

I was trying to practice a little with desktop compose for kotlin and when i was trying to implement AlertDialog element I got this exception:
Exception in thread "AWT-EventQueue-0 #coroutine#3" kotlin.NotImplementedError: An operation is not implemented: not implemented
The code that im trying to run :
fun main() {
var text = mutableStateOf(0F)
var num = mutableStateOf("a")
Window(
size = IntSize(500, 500),
title = num.value,
menuBar = MenuBar(
Menu(
name = "Test",
MenuItem(
name = "Dodaj random",
onClick = {
text.value = text.value + Random.nextFloat()
if (text.value > 1F) {
text.value = 0F
num.value += "a"
}
},
shortcut = KeyStroke(Key.A)
),
MenuItem(
name = "Exit",
onClick = {
AppManager.exit()
},
shortcut = KeyStroke(Key.L)
)
)
)
) {
MaterialTheme {
Column(Modifier.fillMaxSize(), Arrangement.spacedBy(12.dp)) {
LinearProgressIndicator(text.value.toFloat(), modifier = Modifier.align(Alignment.CenterHorizontally))
val openDialog = remember { mutableStateOf(false) }
Button(
onClick = {
openDialog.value = true
}) {
Text("Click me!")
}
if (openDialog.value) {
AlertDialog(
onDismissRequest = { openDialog.value = false },
title = { Text("Dialog title") },
text = { Text("Here is a text") },
confirmButton = {
Button(
onClick = {
openDialog.value = false
}
) { Text("Confirm butt") }
},
dismissButton = {
Button(
onClick = {
openDialog.value = false
}
) { Text("Diss butt") }
}
)
}
Button(
onClick = {
text.value += 0.1F
if (text.value > 1F) {
text.value = 0F
num.value += "a"
}
},
modifier = Modifier.align(Alignment.CenterHorizontally)
) {
Text(text.value.toString())
}
Button(
onClick = {
num.value += "a"
},
modifier = Modifier.align(Alignment.CenterHorizontally)
) {
Text(num.component1())
}
}
}
}
}
Only when I'm trying to click on the "Click me" button I'm getting this exception other buttons works perfectly.
My imports
import androidx.compose.desktop.AppManager
import androidx.compose.desktop.Window
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material.Button
import androidx.compose.material.LinearProgressIndicator
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.key.Key
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.KeyStroke
import androidx.compose.ui.window.Menu
import androidx.compose.ui.window.MenuBar
import androidx.compose.ui.window.MenuItem
import kotlin.random.Random
Your issue seems related to this github issue.
To solve it simply update compose dependency to 0.2.0-build132.
Complete example of my build.gradle with the correct versions:
import org.jetbrains.compose.compose
plugins {
kotlin("jvm") version "1.4.20"
id("org.jetbrains.compose") version "0.2.0-build132"
}
repositories {
jcenter()
maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
}
dependencies {
implementation(compose.desktop.currentOs)
}
compose.desktop {
application {
mainClass = "MainKt"
}
}