I want to change the text that's appearing on the button each time I click it, so I have written the following code, but it's not working. Where am I going wrong?
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
var i=0;
Button(onClick = {i++ }) {
Text("Clicked $i times") //!!not updating here
}
}
}
}
Check how compose works with states and recomposition.
Use something like:
var i by remember { mutableStateOf(0) }
Button(onClick = {i++ }) {
Text("Clicked $i times")
}
Related
How can the properties of a top app bar be accessed and reused several times? Are there any limitations towards this approach? I want to be able to change the text in a top app bar when necessary.
class MainActivity : ComponentActivity() {
private val topBarTitle: String = "?"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
AirlinesTheme {
setContent {
Scaffold(
topBar = { TopBar() },
content = {}
)
}
}
}
}
#Composable
fun TopBar() {
SmallTopAppBar(title = { Text(text = topBarTitle) })
}
}
Usually the important data is stored inside a ViewModel
class MyVM : ViewModel(){
var topBarProperty by mutableStateOf("Initial")
}
Then initialize the VM like this
val vm by viewModels<MyVM>()
Now, use the property in your top-bar
Scaffold(
topBar = { Text(text = vm.topBarProperty) },
content = {}
)
Now, you could do something like vm.topBarProperty = "Updated", from anywhere in your activity, and it will update the value on the topBar. This is because we are using a MutableState<T> type variable which will trigger recompositions on the Composables reading it, when modified.
I'm having issues whit the onClick on Jetpack compose, it performs the click as soon as I run the app and after returning to this activity the button stops working. Any insights?
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val context = LocalContext.current
linkButton("Go to text views", goTo(context, TextViewActivity::class.java))
}
}
}
#Composable
fun linkButton(msg: String, link: Unit) {
Button(onClick = {
link
}) {
Text(msg)
}
}
#Preview
#Composable
fun PreviewMessageCard() {
val context = LocalContext.current
linkButton(
msg = "Sample",
link = goTo(context, TextViewActivity::class.java)
)
}
private fun goTo(context: Context, clazz: Class<*>) {
context.startActivity(Intent(context, clazz))
}
You are actually calling the method at the moment you are composing the linkButton, not passing it as a callback to be called on click. And on click, it is just returning a Unit which causes the unexpected behavior.
To fix that, you should change the parameter type in your composable function to () -> Unit, which represents a function type.
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val context = LocalContext.current
linkButton("Go to text views") {
goTo(context, TextViewActivity::class.java)
}
}
}
}
#Composable
fun LinkButton(msg: String, link: () -> Unit) {
Button(onClick = {
link()
}) {
Text(msg)
}
}
I am trying to add when or if statement to my code. for example, once I press the first/second button it will change the colors of button,button2 to red. and if I just press the button3 it will become green. If there is also a way more easy method I am looking for it.
`binding.button.isSelected
binding.button.setOnClickListener {
binding.button.setBackgroundColor(R.drawable.red)
}
binding.button2.isSelected
binding.button2.setOnClickListener {
binding.button2.setBackgroundColor(R.drawable.red)
}
binding.button3.isSelected
binding.button3.setOnClickListener {
binding.button3.setBackgroundColor(R.drawable.green)
}`
EDIT
I did figure out thanks to #Tonnie, I had to change a few lines to work it as I intended. this is the code;
var isRedButtonsClicked = true
var isGreenButtonClicked = true
fun colorButtonsRed() {
binding.button.setBackgroundColor(R.color.red)
binding.button2.setBackgroundColor(R.color.red)
}
fun colorButtonGreen() {
binding.button3.setBackgroundColor(R.color.green)
}
binding.button.setOnClickListener {
when (isRedButtonsClicked) {
true -> colorButtonsRed()
}
}
binding.button2.setOnClickListener {
when (isRedButtonsClicked) {
true -> colorButtonsRed()
}
}
binding.button3.setOnClickListener {
when (isGreenButtonClicked) {
true -> colorButtonGreen()
}
}
setContentView(binding.root)
I get you, you need the Buttons to work simultaneously.
In this case try to build onto this code to suit your needs.
First create a var which I name isRedButtonsSelected to monitor
Button States.
Add 2 functions to switch colors btw Green/Red and Gray (or any
color you choose)
Add 3 onClickListeners to change button Colors
The code
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private var isRedButtonsClicked = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
binding.button.setOnClickListener {
when (isRedButtonsClicked) {
true -> colorButtons()
false -> unColorButtons()
}
}
binding.button2.setOnClickListener {
when (isRedButtonsClicked) {
true -> colorButtons()
false -> unColorButtons()
}
}
binding.button3.setOnClickListener {
when (isRedButtonsClicked) {
true -> colorButtons()
false -> unColorButtons()
}
}
setContentView(binding.root)
}
private fun colorButtons() {
binding.button.setBackgroundColor(Color.GRAY)
binding.button2.setBackgroundColor(Color.GRAY)
binding.button3.setBackgroundColor(Color.GREEN)
isRedButtonsClicked = false
}
private fun unColorButtons() {
binding.button.setBackgroundColor(Color.RED)
binding.button2.setBackgroundColor(Color.RED)
binding.button3.setBackgroundColor(Color.GRAY)
isRedButtonsClicked = true
}
}
#Gabe Sechan is right. You should use setBackgroundColor() with a Color Constant.
I am not sure what isSelected is intended to do but this code should work.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = ActivityMainBinding.inflate(layoutInflater)
binding.button.setOnClickListener {
binding.button.setBackgroundColor(Color.RED)
}
binding.button2.setOnClickListener {
binding.button2.setBackgroundColor(Color.RED)
}
binding.button3.setOnClickListener {
binding.button3.setBackgroundColor(Color.GREEN)
}
setContentView(binding.root)
}
I wanted to build a very simple demo. A button which you can click, and it counts the clicks.
Code looks like this:
class MainActivity : ComponentActivity() {
private var clicks = mutableStateOf(0)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Surface(color = MaterialTheme.colors.background) {
NewsStory(clicks.value) { onClick() }
}
}
}
private fun onClick() {
clicks.value++
}
}
#Composable
fun NewsStory(clicks: Int, onClick: () -> Unit) {
Column(modifier = Modifier.padding(8.dp)) {
Button(onClick = onClick) {
Text("Clicked: $clicks")
}
}
}
From my understanding this should be recomposed everytime the button is clicked, as clicks is changed.
But it does not work, any ideas what I'm doing wrong here?
I'm on androidx.activity:activity-compose:1.3.0-beta01, kotlin 1.5.10 and compose version 1.0.0-beta08
You need to use the "remember" keyword for the recomposition to happen each time, as explained here: https://foso.github.io/Jetpack-Compose-Playground/general/state/
In short, your composable would look like this:
#Composable
fun NewsStory (){
val clickState = remember { mutableStateOf(0) }
Column (modifier = Modifier.padding(8.dp)) {
Button(
onClick = { clickState.value++ }) {
}
Text("Clicked: $clickState.value.toString()")
}
}
I have tried to basic composable codelab exercise. In Android Studio BasicCodelabThemes shows as an error. Please help me to find the error
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyApp {
Greeting("Android")
}
}
}
}
#Composable
fun MyApp(content:#Composable () -> Unit) {
BasicsCodelabTheme {
Surface(color = Color.Yellow) {
content()
}
}
}
#Composable
fun Greeting(name: String) {
Text(text = "Hello $name!")
}
Yeah from my research on the BasicCodelabTheme, it is a custom-built composable function, it isn't a predefined one, so you need to create it yourself in your Kotlin file as a composable function for your theme.BasicCodelabTheme function definition