Upgrade to Pro — share decks privately, control downloads, hide ads and more …

TextField theme in Compose

TextField theme in Compose

Mobile勉強会 Wantedly × チームラボ #6 での発表内容です。
https://wantedly.connpass.com/event/256518/

rmakiyama

August 30, 2022
Tweet

More Decks by rmakiyama

Other Decks in Technology

Transcript

  1. 5FYU'JFMEUIFNFJO$PNQPTF
    3ZP.BLJZBNBSNBLJZBNB
    3BEJPUBML*OD
    .PCJMFษڧձ8BOUFEMZºνʔϜϥϘ

    View Slide

  2. 5FYU'JFMEDPMPSUIFNF
    JO$PNQPTF
    3ZP.BLJZBNBSNBLJZBNB
    3BEJPUBML*OD
    .PCJMFษڧձ8BOUFEMZºνʔϜϥϘ

    View Slide

  3. w ຀ࢁྎ
    w 3BEJPUBMLגࣜձࣾ
    w "OESPJEΤϯδχΞ
    [email protected]
    wSNBLJZBNB
    ࣗݾ঺հ

    View Slide

  4. w ຀ࢁྎ
    w 3BEJPUBMLגࣜձࣾ
    w "OESPJEΤϯδχΞ
    [email protected]
    wSNBLJZBNB
    ࣗݾ঺հ
    +FUQBDL$PNQPTFੵۃಋೖத🚀

    View Slide

  5. 5FYU'JFMEͷಋೖ
    w WͰ͸͍͔ͭ͘ෆ۩߹͕͋ͬͨ
    w #BDLTQBDFΩʔ௕ԡ͠Ͱจࣈ͕࿈ଓͰফ͑ͳ͍
    w ςΩετબ୒࣌ͷڍಈ͕ෆ҆ఆ
    w WͰ͸ෆ۩߹͕ղফ͞Εͨ👏
    w طଘσβΠϯʹ߹Θͤͯಋೖ։࢝

    View Slide

  6. BOESPJEYDPNQPTFNBUFSJBM5FYU'JFMELU
    @Composable

    fun TextField(

    value: String,

    onValueChange: (String)
    ->
    Unit,

    modifier: Modifier = Modifier,

    enabled: Boolean = true,

    readOnly: Boolean = false,

    textStyle: TextStyle = LocalTextStyle.current,

    label: @Composable (()
    ->
    Unit)? = null,

    placeholder: @Composable (()
    ->
    Unit)? = null,

    leadingIcon: @Composable (()
    ->
    Unit)? = null,

    trailingIcon: @Composable (()
    ->
    Unit)? = null,

    isError: Boolean = false,

    visualTransformation: VisualTransformation = VisualTransformation.None,

    keyboardOptions: KeyboardOptions = KeyboardOptions.Default,

    keyboardActions: KeyboardActions = KeyboardActions(),

    singleLine: Boolean = false,

    maxLines: Int = Int.MAX_VALUE,

    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },

    shape: Shape =

    MaterialTheme.shapes.small.copy(bottomEnd = ZeroCornerSize, bottomStart = ZeroCornerSize),

    colors: TextFieldColors = TextFieldDefaults.textFieldColors()

    ) {…}

    View Slide

  7. BOESPJEYDPNQPTFNBUFSJBM5FYU'JFMELU
    @Composable

    fun TextField(

    value: String,

    onValueChange: (String)
    ->
    Unit,

    modifier: Modifier = Modifier,

    enabled: Boolean = true,

    readOnly: Boolean = false,

    textStyle: TextStyle = LocalTextStyle.current,

    label: @Composable (()
    ->
    Unit)? = null,

    placeholder: @Composable (()
    ->
    Unit)? = null,

    leadingIcon: @Composable (()
    ->
    Unit)? = null,

    trailingIcon: @Composable (()
    ->
    Unit)? = null,

    isError: Boolean = false,

    visualTransformation: VisualTransformation = VisualTransformation.None,

    keyboardOptions: KeyboardOptions = KeyboardOptions.Default,

    keyboardActions: KeyboardActions = KeyboardActions(),

    singleLine: Boolean = false,

    maxLines: Int = Int.MAX_VALUE,

    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },

    shape: Shape =

    MaterialTheme.shapes.small.copy(bottomEnd = ZeroCornerSize, bottomStart = ZeroCornerSize),

    colors: TextFieldColors = TextFieldDefaults.textFieldColors()

    ) {…}

    View Slide

  8. BOESPJEYDPNQPTFNBUFSJBM5FYU'JFME%FGBVMUTLU
    @Stable

    interface TextFieldColors {

    @Composable

    fun textColor(enabled: Boolean): State

    @Composable

    fun backgroundColor(enabled: Boolean): State

    @Composable

    fun placeholderColor(enabled: Boolean): State

    @Composable

    fun labelColor(…): State

    @Composable

    fun leadingIconColor(enabled: Boolean, isError: Boolean): State

    @Composable

    fun trailingIconColor(enabled: Boolean, isError: Boolean): State

    @Composable

    fun indicatorColor(…): State

    @Composable

    fun cursorColor(isError: Boolean): State

    }

    View Slide

  9. 5FYU'JFMEͷ৭ͷछྨ
    ᶃ UFYU$PMPS
    ᶄ CBDLHSPVOE$PMPS
    ᶅ QMBDFIPMEFS$PMPS
    ᶆ MBCFM$PMPS
    ᶇ MFBEJOH*DPO$PMPS
    ᶈ USBJMJOH*DPO$PMPS
    ᶉ JOEJDBUPS$PMPS
    ᶊ DVSTPS$PMPS

    View Slide

  10. 5FYU'JFMEͷ৭ͷछྨ
    ᶃ UFYU$PMPS
    ᶄ CBDLHSPVOE$PMPS
    ᶅ QMBDFIPMEFS$PMPS
    ᶆ MBCFM$PMPS
    ᶇ MFBEJOH*DPO$PMPS
    ᶈ USBJMJOH*DPO$PMPS
    ᶉ JOEJDBUPS$PMPS
    ᶊ DVSTPS$PMPS
    ᶃUFYU$PMPS ᶄCBDLHSPVOE$PMPS
    ᶆMBCFM$PMPS
    ᶉJOEJDBUPS$PMPS
    ᶊDVSTPS$PMPS

    View Slide

  11. 5FYU'JFMEͷ৭ͷछྨ
    ᶃ UFYU$PMPS
    ᶄ CBDLHSPVOE$PMPS
    ᶅ QMBDFIPMEFS$PMPS
    ᶆ MBCFM$PMPS
    ᶇ MFBEJOH*DPO$PMPS
    ᶈ USBJMJOH*DPO$PMPS
    ᶉ JOEJDBUPS$PMPS
    ᶊ DVSTPS$PMPS
    ᶅQMBDFIPMEFS$PMPS

    View Slide

  12. 5FYU'JFMEͷ৭ͷछྨ
    ᶃ UFYU$PMPS
    ᶄ CBDLHSPVOE$PMPS
    ᶅ QMBDFIPMEFS$PMPS
    ᶆ MBCFM$PMPS
    ᶇ MFBEJOH*DPO$PMPS
    ᶈ USBJMJOH*DPO$PMPS
    ᶉ JOEJDBUPS$PMPS
    ᶊ DVSTPS$PMPS
    ᶇMFBEJOH*DPO$PMPS
    ᶈUSBJMJOH*DPO$PMPS

    View Slide

  13. BOESPJEYDPNQPTFNBUFSJBM5FYU'JFMELU
    @Composable

    fun TextField(



    colors: TextFieldColors = TextFieldDefaults.textFieldColors()

    ) {…}

    View Slide

  14. BOESPJEYDPNQPTFNBUFSJBM5FYU'JFME%FGBVMUTLUUFYU'JFME$PMPST
    @Composable

    fun textFieldColors(

    textColor: Color = LocalContentColor.current.copy(LocalContentAlpha.current),

    disabledTextColor: Color = textColor.copy(ContentAlpha.disabled),

    backgroundColor: Color = MaterialTheme.colors.onSurface.copy(alpha = BackgroundOpacity),

    cursorColor: Color = MaterialTheme.colors.primary,

    errorCursorColor: Color = MaterialTheme.colors.error,

    focusedIndicatorColor: Color =

    MaterialTheme.colors.primary.copy(alpha = ContentAlpha.high),

    unfocusedIndicatorColor: Color =

    MaterialTheme.colors.onSurface.copy(alpha = UnfocusedIndicatorLineOpacity),

    disabledIndicatorColor: Color = unfocusedIndicatorColor.copy(alpha = ContentAlpha.disabled),

    errorIndicatorColor: Color = MaterialTheme.colors.error,

    leadingIconColor: Color =

    MaterialTheme.colors.onSurface.copy(alpha = IconOpacity),

    disabledLeadingIconColor: Color = leadingIconColor.copy(alpha = ContentAlpha.disabled),

    errorLeadingIconColor: Color = leadingIconColor,

    trailingIconColor: Color =

    MaterialTheme.colors.onSurface.copy(alpha = IconOpacity),

    disabledTrailingIconColor: Color = trailingIconColor.copy(alpha = ContentAlpha.disabled),

    errorTrailingIconColor: Color = MaterialTheme.colors.error,

    focusedLabelColor: Color =

    MaterialTheme.colors.primary.copy(alpha = ContentAlpha.high),

    unfocusedLabelColor: Color = MaterialTheme.colors.onSurface.copy(ContentAlpha.medium),

    disabledLabelColor: Color = unfocusedLabelColor.copy(ContentAlpha.disabled),

    errorLabelColor: Color = MaterialTheme.colors.error,

    placeholderColor: Color = MaterialTheme.colors.onSurface.copy(ContentAlpha.medium),

    disabledPlaceholderColor: Color = placeholderColor.copy(ContentAlpha.disabled)

    ): TextFieldColors = …

    View Slide

  15. BOESPJEYDPNQPTFNBUFSJBM5FYU'JFME%FGBVMUTLUUFYU'JFME$PMPST
    @Composable

    fun textFieldColors(

    textColor: Color = LocalContentColor.current.copy(LocalContentAlpha.current),

    disabledTextColor: Color = textColor.copy(ContentAlpha.disabled),

    backgroundColor: Color = MaterialTheme.colors.onSurface.copy(alpha = BackgroundOpacity),

    cursorColor: Color = MaterialTheme.colors.primary,

    errorCursorColor: Color = MaterialTheme.colors.error,

    focusedIndicatorColor: Color =

    MaterialTheme.colors.primary.copy(alpha = ContentAlpha.high),

    unfocusedIndicatorColor: Color =

    MaterialTheme.colors.onSurface.copy(alpha = UnfocusedIndicatorLineOpacity),

    disabledIndicatorColor: Color = unfocusedIndicatorColor.copy(alpha = ContentAlpha.disabled),

    errorIndicatorColor: Color = MaterialTheme.colors.error,

    leadingIconColor: Color =

    MaterialTheme.colors.onSurface.copy(alpha = IconOpacity),

    disabledLeadingIconColor: Color = leadingIconColor.copy(alpha = ContentAlpha.disabled),

    errorLeadingIconColor: Color = leadingIconColor,

    trailingIconColor: Color =

    MaterialTheme.colors.onSurface.copy(alpha = IconOpacity),

    disabledTrailingIconColor: Color = trailingIconColor.copy(alpha = ContentAlpha.disabled),

    errorTrailingIconColor: Color = MaterialTheme.colors.error,

    focusedLabelColor: Color =

    MaterialTheme.colors.primary.copy(alpha = ContentAlpha.high),

    unfocusedLabelColor: Color = MaterialTheme.colors.onSurface.copy(ContentAlpha.medium),

    disabledLabelColor: Color = unfocusedLabelColor.copy(ContentAlpha.disabled),

    errorLabelColor: Color = MaterialTheme.colors.error,

    placeholderColor: Color = MaterialTheme.colors.onSurface.copy(ContentAlpha.medium),

    disabledPlaceholderColor: Color = placeholderColor.copy(ContentAlpha.disabled)

    ): TextFieldColors = …








    View Slide

  16. 5FYU'JFME΁ͷ৭ࢦఆ
    TextField(

    value = value,

    onValueChange = onValueChange,

    colors = TextFieldDefaults.textFieldColors(

    textColor = Color.Yellow,

    disabledTextColor = Color.Magenta,

    )

    )
    &OBCMFE
    %JTBCMFE

    View Slide

  17. ΄΅Ϛελʔ🎉

    View Slide

  18. ಥવͷ🕵ΫΠζλΠϜ

    View Slide

  19. 25FYU4UZMFDPMPS5FYU'JFME$PMPSTUFYU$PMPS
    TextField(

    value = value,

    onValueChange = onValueChange,

    textStyle = TextStyle(color = Color.Blue),

    colors = TextFieldDefaults.textFieldColors(

    textColor = Color.Yellow,

    disabledTextColor = Color.Magenta,

    )

    )
    🤔

    View Slide

  20. "5FYU4UZMFDPMPS5FYU'JFME$PMPSTUFYU$PMPS
    TextField(

    value = value,

    onValueChange = onValueChange,

    textStyle = TextStyle(color = Color.Blue),

    colors = TextFieldDefaults.textFieldColors(

    textColor = Color.Yellow,

    disabledTextColor = Color.Magenta,

    )

    )
    &OBCMFE
    %JTBCMFE

    View Slide

  21. 5FYU'JFME΁ͷઃఆ
    @Composable

    fun TextField(

    …,

    textStyle: TextStyle = LocalTextStyle.current,

    …,

    colors: TextFieldColors = TextFieldDefaults.textFieldColors()

    ) {

    //
    If color is not provided via the text style, use content color as a default

    val textColor = textStyle.color.takeOrElse {

    colors.textColor(enabled).value

    }



    }
    BOESPJEYDPNQPTFNBUFSJBM5FYU'JFMELU

    View Slide

  22. 2DVSTPS$PMPSͷద༻ൣғ
    TextField(

    value = value,

    onValueChange = onValueChange,

    colors = TextFieldDefaults.textFieldColors(

    cursorColor = Color.Magenta,

    )

    )
    🤔

    View Slide

  23. "DVSTPS$PMPSͷద༻ൣғ
    TextField(

    value = value,

    onValueChange = onValueChange,

    colors = TextFieldDefaults.textFieldColors(

    cursorColor = Color.Magenta,

    )

    )

    View Slide

  24. "DVSTPS$PMPSͷద༻ൣғ
    TextField(

    value = value,

    onValueChange = onValueChange,

    colors = TextFieldDefaults.textFieldColors(

    cursorColor = Color.Magenta,

    )

    )
    🤔

    View Slide

  25. 5FYU4FMFDUJPO$PMPSTͰఏڙ
    @Immutable

    class TextSelectionColors(

    val handleColor: Color,

    val backgroundColor: Color

    ) {…}

    val LocalTextSelectionColors = compositionLocalOf { DefaultTextSelectionColors }

    private val DefaultSelectionColor = Color(0xFF4286F4)

    @Stable

    private val DefaultTextSelectionColors = TextSelectionColors(

    handleColor = DefaultSelectionColor,

    backgroundColor = DefaultSelectionColor.copy(alpha = 0.4f)

    )
    BOESPJEYDPNQPTFGPVOEBUJPOUFYUTFMFDUJPO5FYU4FMFDUJPO$PMPSTLU

    View Slide

  26. 5FYU4FMFDUJPO$PMPSTΛΧελϚΠζ
    val tsColors = remember {

    TextSelectionColors(

    handleColor = Color.Magenta,

    backgroundColor = Color.Green,

    )

    }

    CompositionLocalProvider(

    LocalTextSelectionColors provides tsColors

    ) {

    TextField(

    value = value,

    onValueChange = onValueChange,

    )

    }

    View Slide

  27. ·ͱΊ
    w 5FYU'JFMEͷ৭ࢦఆ͸

    5FYU'JFME%FGBVMUTUFYU'JFME$PMPSTΛ࢖͓͏
    w 5FYU4UZMFͷ৭Λࢦఆ͍ͯ͠Δ৔߹͸஫ҙ
    w 5FYU4FMFDUJPO$PMPST͸ผͰࢦఆͷඞཁ͋Γ
    w ྑ͍$PNQPTFϥΠϑΛ👋

    View Slide

  28. "QQFOEJYFT
    w IUUQTEFWFMPQFSBOESPJEDPNKFUQBDLDPNQPTFUFYU IMKB
    w IUUQTEFWFMPQFSBOESPJEDPNKFUQBDLDPNQPTFUIFNFTDVTUPN [email protected]
    DVTUPN
    w IUUQTDTBOESPJEDPNBOESPJEYQMBUGPSNGSBNFXPSLTTVQQPSUBOESPJEYNBJODPNQPTF
    GPVOEBUJPOGPVOEBUJPOTSDDPNNPO.BJOLPUMJOBOESPJEYDPNQPTFGPVOEBUJPOUFYU
    $PSF5FYU'JFMELUM RDPSFUFYU
    fi
    F
    w IUUQTDTBOESPJEDPNBOESPJEYQMBUGPSNGSBNFXPSLTTVQQPSUBOESPJEYNBJODPNQPTF
    GPVOEBUJPOGPVOEBUJPOTSDBOESPJE.BJOLPUMJOBOESPJEYDPNQPTFGPVOEBUJPOUFYU
    "OESPJE$VSTPS)BOEMFBOESPJELUM R"OESPJE$VSTPS)BOEMFTR

    View Slide