background

Still troubled by Dark Mode and RTL Mode? Try Jetpack Compose! One key switch, improve the happiness index. Learn about the cool Jetpack Compose

preview

design

TitleBar

The classic three-step, Back Icon, Setting Icon, Title Text, is recorded by settingDialogState:

  TopAppBar(
        backgroundColor = MaterialTheme.colors.background,
        contentPadding = PaddingValues(start = 18.dp, end = 18.dp)
    ) {
        Icon(
            painter = rememberVectorPainter(image = Icons.Default.ArrowBack),
            contentDescription = "back",
            modifier = Modifier.size(24.dp)
        )
        Text(
            text = "Window list",
            fontSize = TextUnit(17f, TextUnitType.Sp),
            fontWeight = FontWeight(700),
            textAlign = TextAlign.Center,
            modifier = Modifier.weight(1f)
        )
        Icon(
            painter = rememberVectorPainter(image = Icons.Default.Settings),
            contentDescription = "setting",
            modifier = Modifier
                .size(24.dp)
                .clickable {
                    settingDialogState.value = true})}Copy the code
preview

goods

Images and text are grouped together, not particularly complex layouts using a mashup of Row and Column:

Row(modifier = Modifier.padding(start = 16.dp, end = 16.dp, top = 16.dp)) { Image( painter = rememberGlidePainter(product.url), contentDescription = "product image", contentScale = ContentScale.FillBounds, modifier = Modifier .size(108.dp, 108.dp) .clip(RoundedCornerShape(2.dp)), ) Column( modifier = Modifier .padding(start = 12.dp) .requiredHeight(108.dp) .fillMaxWidth() ) { Text( text = product.name, fontSize = TextUnit(15f, TextUnitType.Sp), fontWeight = FontWeight(500), maxLines = 2 ) Text( text = product.price, fontWeight = FontWeight(600), fontSize = TextUnit(15f, TextUnitType.Sp), modifier = Modifier.padding(top = 4.dp) ) Text( text = product.origin, fontWeight = FontWeight(300), fontSize = TextUnit(13f, TextUnitType.Sp), modifier = Modifier.padding(top = 4.dp) ) Spacer(modifier = Modifier.weight(1f)) RedButton( text = if (product.added) "Added" else "Add", modifier = Modifier .align(Alignment.End) .clickable { if (! product.added) { product.added = true addBtnClick(product.id) } }, isDark = isDarkMode, isAdded = product.added ) } }Copy the code
preview

The key here is that this button has two states: Add and Added:

Add Added

How would this be represented in the data? We know that the UI for Jetpack Compose is driven by State, so we’ll define this field using State as well:

data class ProductBean(
    val id: Int.val url: String,
    val name: String,
    val price: String,
    val origin: String
) {
    var added by mutableStateOf(false)}Copy the code

This changes the button color when the added field changes.

Once the fields are defined, how do you design the UI? There are only two parts of the button, the background and the text, so you only need to control the color of each of them, but with dark mode in mind, there are four styles:

class RedButtonColorDelegate(private val isDark: Boolean.private val isAdded: Boolean) {
    val btnColor: Color = if (isAdded) {
        btnColorAdded
    } else {
        btnColorAdd
    }
    val textColor: Color = if (isAdded) {
        textColorAdded
    } else {
        textColorAdd
    }


    private val btnColorAdd: Color
        get() = Color(0xFFFE2C55)
        

    private val textColorAdd: Color
        get() = Color.White


    //added
    private val btnColorAdded: Color
        get() =
            if (isDark) {
                Color(0x14FFFFFF)}else {
                Color(0xF161823)}private val textColorAdded: Color
        get() =
            if (isDark) {
                Color(0x57FFFFFF)}else {
                Color(0x57161823)}}Copy the code

After defining the color, we just need to pick the color according to the state:

@Composable
fun RedButton(
    modifier: Modifier = Modifier,
    text: String,
    isAdded: Boolean = false,
    isDark: Boolean = false
) {
    Box(
        modifier = modifier
            .size(height = 28.dp, width = 88.dp)
            .clip(RoundedCornerShape(2.dp))
            .background(
                color = RedButtonColorDelegate(
                    isDark = isDark,
                    isAdded = isAdded
                ).btnColor
            )
    ) {
        Text(
            text = text,
            color = RedButtonColorDelegate(
                isDark = isDark,
                isAdded = isAdded
            ).textColor,
            fontSize = TextUnit(14f, TextUnitType.Sp),
            fontWeight = FontWeight(600),
            textAlign = TextAlign.Center,
            modifier = Modifier
                .align(Alignment.Center)
                .padding(start = 8.dp, end = 8.dp)
        )
    }
}

Copy the code

A long list of

The Jetpack Compose long list is so simple that you don’t need to write Adapter again:

LazyColumn(modifier = Modifier
                        .weight(1f)
                        .fillSize()) {
        items(items = products, key = { it.id }) {
                ProductItem(product = it, isDarkMode =false, productClick)
             }
     }
Copy the code

Popup window

In Jetpack Compose we can use ModalBottomSheetLayout to implement the bottom popover, which is very simple:

 val scope = rememberCoroutineScope()
 
 val addMenuState = rememberModalBottomSheetState(ModalBottomSheetValue.Hidden)

 ModalBottomSheetLayout(
                sheetState = addMenuState,
                sheetShape = RoundedCornerShape(topStart = 8.dp, topEnd = 8.dp),
                sheetContent = {
                // Popover content
                    AddMenu { scope.launch { addMenuState.hide() } }
                }
            ) {
            
            ...
          
          }
Copy the code
preview

DarkMode

Switching the Dark Mode with Jetpack Compose is even easier. However, we can use the MaterialTheme provided by MaterialDesign or we can fully customize it.

// Define the color

private val DarkColorPalette = darkColors(
    primary = Purple200,
    primaryVariant = Purple700,
    secondary = Teal200
)

private val LightColorPalette = lightColors(
    primary = Purple500,
    primaryVariant = Purple700,
    secondary = Teal200
}

// Define the topic
@Composable
fun ManageShowCaseComposeTheme(
    darkTheme: Boolean = isSystemInDarkTheme(),
    content: @Composable()() - >Unit
) {
    val colors = if (darkTheme) {
        DarkColorPalette
    } else {
        LightColorPalette
    }

    MaterialTheme(
        colors = colors,
        typography = Typography,
        shapes = Shapes,
        content = content
    )
}

// Use this theme:

ManageShowCaseComposeTheme(darkTheme = viewModel.darkModeState.value){
      TitileBar()
       ...
}

Copy the code
The title

RTL

Some products for Arab countries require RTL Mode, which is something Compose has ready for us: CompositionLocalProvider: CompositionLocalProvider: CompositionLocalProvider: CompositionLocalProvider: CompositionLocalProvider: CompositionLocalProvider: CompositionLocalProvider: CompositionLocalProvider: CompositionLocalProvider: CompositionLocalProvider: CompositionLocalProvider: CompositionLocalProvider: CompositionLocalProvider: CompositionLocalProvider: CompositionLocalProvider So let’s say LocalLayoutDirection, it’s the same instance. The layout will be based on the location of the layout.


 CompositionLocalProvider(LocalLayoutDirection provides if (rtlState.value) LayoutDirection.Rtl else LayoutDirection.Ltr) {
 
   TitileBar()
       ...
   
   
 }
Copy the code

Note: Currently LocalLayoutDirection only flips the layout, it does not mirror the component’s content. It may take some work to flip the image.

preview

conclusion

Is it very simple? Jetpack Compose is coming for Release, so get started

Code examples have been sent to Github: github.com/Palardin3/C…