salman
salman

Reputation: 104

jetpack compose AndroidView not detect theme when change dark mode

How are you I have some problem with AndroidView I want use MPChart it works fine but when I change to dark mode theme in MPChart it still in light mode and Also textView the problem in AndroidView

see codes

    AndroidView(factory = {
        TextView(it).apply {
            layoutParams = ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT
            )

            text = "How are you"
            textSize = 28f
}

I SOLVE THIS

just init variable before AndroidView using materialTheme color scheme like this

val primaryColor = MaterialTheme.colorScheme.onPrimary

Upvotes: 4

Views: 1324

Answers (1)

Inidam Leader
Inidam Leader

Reputation: 649

1- Extend AppCompatActivity instead of ComponentActivity and use AppCompatDelegate.setDefaultNightMode to manage night mode changing.

2- (Optional) Disable configuration changes on theme change in the manifest to prevent the activity from being recreated when the theme changes. This can improve performance and maintain a consistent visual UI. (In this case be aware that you have to change the status icon colors according the night mode selected)

<activity
   android:name=".MainActivity"
   android:configChanges="uiMode"
/>

3- Wrappe each AndroidView in your code with composable function key(){} which has composable function isSystemInDarkTheme() as key. This will force the AndroidView to be redrawn/recomposed with the new theme colors each time the theme changes.

key(isSystemInDarkTheme()) {
    AndroidView(
        modifier = modifier,
        factory = { context ->
        // ...
        },
    )
}

When to use this solution?

This solution is used when it’s complicated/impossible to update the View style or color directly in AndroidView update parameter and the project is based on jetpack compose.

Example:

NumberPicker dialog does not have setTextColor() method on API 28 and below, so we "can’t" update text color on theme changing with the traditional way.

So instead of:

@Composable
fun NumberPickerWidget(
    value: Int,
    minValue: Int,
    maxValue: Int,
    onValueChange: (Int) -> Unit,
    modifier: Modifier = Modifier,
) {
    val color1 = MaterialTheme.colorScheme.onSurface

    AndroidView(
        modifier = modifier,
        factory = { context ->
            NumberPicker(context)
        },
        update = { numberPicker ->
            numberPicker.apply {
                this.wrapSelectorWheel = wrapSelectorWheel
                this.minValue = minValue
                this.maxValue = maxValue
                this.value = value
                // Needs API 29+
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
                    this.textColor = color1.toArgb()
                setOnValueChangedListener { _, _, newVal ->
                    onValueChange(newVal)
                }
            }
        }
    )
}

use:

@Composable
fun NumberPickerWidget(
    value: Int,
    minValue: Int,
    maxValue: Int,
    onValueChange: (Int) -> Unit,
    modifier: Modifier = Modifier,
    wrapSelectorWheel: Boolean = false,
) {
    key(isSystemInDarkTheme()) {
        AndroidView(
            modifier = modifier,
            factory = { context ->
                NumberPicker(context)
            },
            update = { numberPicker ->
                numberPicker.apply {
                    this.wrapSelectorWheel = wrapSelectorWheel
                    this.minValue = minValue
                    this.maxValue = maxValue
                    this.value = value
                    // Needs API 29+
                    // this.textColor = Color.Red.toArgb()
                    setOnValueChangedListener { _, _, newVal ->
                        onValueChange(newVal)
                    }
                }
            },
        )
    }
}

Upvotes: 2

Related Questions