พื้นฐานของสไตล์

คุณใช้สไตล์ในแอปได้ 3 วิธีดังนี้

  1. ใช้โดยตรงกับคอมโพเนนต์ที่มีอยู่ซึ่งแสดง Style พารามิเตอร์
  2. ใช้สไตล์กับ Modifier.styleable ในคอมโพสเซเบิลเลย์เอาต์ ที่ไม่ยอมรับพารามิเตอร์ Style
  3. ใช้ Modifier.styleable{} ในระบบการออกแบบที่กำหนดเองและแสดงพารามิเตอร์สไตล์ในคอมโพเนนต์ของคุณเอง

พร็อพเพอร์ตี้ที่ใช้ได้ในสไตล์

สไตล์รองรับพร็อพเพอร์ตี้จำนวนมากที่ตัวปรับแต่งรองรับ อย่างไรก็ตาม ไม่ใช่ทุกอย่างที่เป็นตัวปรับแต่งจะจำลองแบบด้วยสไตล์ได้ คุณยังคงต้องใช้ตัวปรับแต่งสำหรับลักษณะการทำงานบางอย่าง เช่น การโต้ตอบ การวาดที่กำหนดเอง หรือการซ้อนพร็อพเพอร์ตี้

การจัดกลุ่ม พร็อพเพอร์ตี้ พร็อพเพอร์ตี้ย่อยรับช่วง
เลย์เอาต์และการปรับขนาด
ระยะห่างจากขอบเนื้อหา (ด้านใน) - contentPadding(all: Dp)
- contentPadding(horizontal: Dp, vertical: Dp)
- contentPadding(start: Dp, top: Dp, end: Dp, bottom: Dp)
- contentPaddingHorizontal(value: Dp) / contentPaddingVertical(value: Dp)
- contentPaddingStart(value: Dp) / contentPaddingTop(value: Dp) / contentPaddingEnd(value: Dp) / contentPaddingBottom(value: Dp)
ไม่
ระยะห่างจากขอบภายนอก (ด้านนอก) - externalPadding(all: Dp)
- externalPadding(horizontal: Dp, vertical: Dp)
- externalPadding(start: Dp, top: Dp, end: Dp, bottom: Dp)
- externalPaddingHorizontal(value: Dp) / externalPaddingVertical(value: Dp)
- externalPaddingStart(value: Dp) / externalPaddingTop(value: Dp) / externalPaddingEnd(value: Dp) / externalPaddingBottom(value: Dp)
ไม่
ขนาด fillWidth()/fillHeight()/fillSize() และ width, height และ size (รองรับเศษส่วน Dp, DpSize หรือ Float) ไม่
จุดยืน ออฟเซ็ต left/top/right/bottom ไม่
ลักษณะที่ปรากฏ
เติม background และ foreground (รองรับ Color หรือ Brush) ไม่
เส้นขอบ borderWidth, borderColor และ borderBrush ไม่
รูปร่าง shape ไม่ แต่ใช้ร่วมกับพร็อพเพอร์ตี้อื่นๆ clip และ border ใช้รูปร่างที่กำหนดนี้
เงา dropShadow, innerShadow ไม่
การแปลง
การเคลื่อนไหวเชิงพื้นที่ของเลเยอร์กราฟิก translationX, translationY, scaleX/scaleY, rotationX/rotationY/rotationZ ไม่
ควบคุม alpha, zIndex (ลำดับการซ้อน) และ transformOrigin (จุดหมุน) ไม่
การจัดรูปแบบตัวอักษร
การจัดรูปแบบ textStyle, fontSize, fontWeight, fontStyle และ fontFamily ใช่
การใช้สี contentColor และ contentBrush นอกจากนี้ยังใช้สำหรับการจัดรูปแบบไอคอนด้วย ใช่
ย่อหน้า lineHeight, letterSpacing, textAlign, textDirection, lineBreak และ hyphens ใช่
ของตกแต่ง textDecoration, textIndent และ baselineShift ใช่

ใช้สไตล์โดยตรงกับคอมโพเนนต์ที่มีพารามิเตอร์สไตล์

คอมโพเนนต์ที่แสดงพารามิเตอร์ Style ช่วยให้คุณตั้งค่าการจัดรูปแบบได้ดังนี้

BaseButton(
    onClick = { },
    style = { }
) {
    BaseText("Click me")
}

ภายในแลมบดาสไตล์ คุณสามารถตั้งค่าพร็อพเพอร์ตี้ต่างๆ เช่น externalPadding หรือ background ได้ดังนี้

BaseButton(
    onClick = { },
    style = { background(Color.Blue) }
) {
    BaseText("Click me")
}

ดูรายการพร็อพเพอร์ตี้ที่รองรับทั้งหมดได้ที่ พร็อพเพอร์ตี้ที่ใช้ได้ใน สไตล์

ใช้สไตล์โดยใช้ตัวปรับแต่งสำหรับคอมโพเนนต์ที่ไม่มีพารามิเตอร์ที่มีอยู่

สำหรับคอมโพเนนต์ที่ไม่มีพารามิเตอร์สไตล์ในตัว คุณยังคงใช้สไตล์กับตัวปรับแต่ง styleable ได้ วิธีนี้ยังมีประโยชน์เมื่อพัฒนาคอมโพเนนต์ที่กำหนดเอง

Row(
    modifier = Modifier.styleable { }
) {
    BaseText("Content")
}

คุณสามารถใส่พร็อพเพอร์ตี้ เช่น background, contentPadding หรือ externalPadding ไว้ในแลมบดาได้เช่นเดียวกับพารามิเตอร์ style

Row(
    modifier = Modifier.styleable {
        background(Color.Blue)
    }
) {
    BaseText("Content")
}

ตัวปรับแต่ง Modifier.styleable ที่เชื่อมโยงกันหลายรายการจะเพิ่มพร็อพเพอร์ตี้ที่ไม่ได้รับช่วงในคอมโพสเซเบิลที่ใช้ โดยทำงานคล้ายกับตัวปรับแต่งหลายรายการที่กำหนดพร็อพเพอร์ตี้เดียวกัน สำหรับพร็อพเพอร์ตี้ที่รับช่วง ระบบจะลบล้างพร็อพเพอร์ตี้เหล่านั้น และตัวปรับแต่ง styleable ตัวสุดท้ายในเชนจะตั้งค่า

เมื่อใช้ Modifier.styleable คุณอาจต้องการสร้างและระบุ StyleState เพื่อใช้กับตัวปรับแต่งเพื่อใช้การจัดรูปแบบตามสถานะ ดูรายละเอียดเพิ่มเติมได้ที่สถานะและภาพเคลื่อนไหวด้วย สไตล์

กำหนดสไตล์แบบสแตนด์อโลน

คุณสามารถกำหนดสไตล์แบบสแตนด์อโลนเพื่อวัตถุประสงค์ในการนำกลับมาใช้ใหม่ได้ดังนี้

val style = Style { background(Color.Blue) }

จากนั้นคุณสามารถส่งสไตล์ที่กำหนดนั้นไปยังพารามิเตอร์สไตล์ของคอมโพสเซเบิลหรือใช้ Modifier.styleable ได้ เมื่อใช้ Modifier.styleable คุณต้องสร้างออบเจ็กต์ StyleState ด้วย StyleState จะอธิบายโดยละเอียดในเอกสารประกอบ สถานะและ ภาพเคลื่อนไหวด้วยสไตล์

ตัวอย่างต่อไปนี้แสดงวิธีใช้สไตล์โดยตรงผ่านพารามิเตอร์ในตัวของคอมโพเนนต์ หรือผ่าน Modifier.styleable

val style = Style { background(Color.Blue) }

// built in parameter
BaseButton(onClick = { }, style = style) {
    BaseText("Button")
}

// modifier styleable
val styleState = remember { MutableStyleState(null) }
Column(
    Modifier.styleable(styleState, style)
) {
    BaseText("Column content")
}

นอกจากนี้ คุณยังส่งสไตล์นั้นไปยังคอมโพเนนต์หลายรายการได้ด้วย

val style = Style { background(Color.Blue) }

// built in parameter
BaseButton(onClick = { }, style = style) {
    BaseText("Button")
}
BaseText("Different text that uses the same style parameter", style = style)

// modifier styleable
val columnStyleState = remember { MutableStyleState(null) }
Column(
    Modifier.styleable(columnStyleState, style)
) {
    BaseText("Column")
}
val rowStyleState = remember { MutableStyleState(null) }
Row(
    Modifier.styleable(rowStyleState, style)
) {
    BaseText("Row")
}

เพิ่มพร็อพเพอร์ตี้สไตล์หลายรายการ

คุณสามารถเพิ่มพร็อพเพอร์ตี้สไตล์หลายรายการได้โดยการตั้งค่าพร็อพเพอร์ตี้ต่างๆ ในแต่ละบรรทัดดังนี้

BaseButton(
    onClick = { },
    style = {
        background(Color.Blue)
        contentPaddingStart(16.dp)
    }
) {
    BaseText("Button")
}

พร็อพเพอร์ตี้ในสไตล์จะไม่เพิ่มค่า ซึ่งแตกต่างจากการจัดรูปแบบตามตัวปรับแต่ง สไตล์จะใช้ค่าที่ตั้งไว้ล่าสุดในรายการพร็อพเพอร์ตี้ภายในบล็อกสไตล์เดียว ในตัวอย่างต่อไปนี้ เมื่อตั้งค่าพื้นหลัง 2 ครั้ง ระบบจะใช้ TealColor เป็นพื้นหลัง สำหรับระยะห่างจากขอบ contentPaddingTop จะลบล้างระยะห่างจากขอบด้านบนที่ตั้งค่าโดย contentPadding และจะไม่รวมค่า

BaseButton(
    style = {
        background(Color.Red)
        // Background of Red is now overridden with TealColor instead
        background(TealColor)
        // All directions of padding are set to 64.dp (top, start, end, bottom)
        contentPadding(64.dp)
        // Top padding is now set to 16.dp, all other paddings remain at 64.dp
        contentPaddingTop(16.dp)
    },
    onClick = {
        //
    }
) {
    BaseText("Click me!")
}

ปุ่มที่มีการตั้งค่าสีพื้นหลัง 2 สี และการลบล้าง contentPadding 2 รายการ
รูปที่ 1 ปุ่มที่มีการตั้งค่าสีพื้นหลัง 2 สีและการลบล้าง contentPadding 2 รายการ

ผสานออบเจ็กต์สไตล์หลายรายการ

คุณสามารถสร้างออบเจ็กต์สไตล์หลายรายการและส่งไปยังพารามิเตอร์สไตล์ของคอมโพสเซเบิลได้

val style1 = Style { background(TealColor) }
val style2 = Style { contentPaddingTop(16.dp) }

BaseButton(
    style = style1 then style2,
    onClick = {

    },
) {
    BaseText("Click me!")
}

ปุ่มที่มีสีพื้นหลังและตั้งค่า contentPaddingTop
รูปที่ 2 ปุ่มที่มีการตั้งค่าสีพื้นหลังและ contentPaddingTop

เมื่อสไตล์หลายรายการระบุพร็อพเพอร์ตี้เดียวกัน ระบบจะเลือกพร็อพเพอร์ตี้ที่ตั้งค่าล่าสุด เนื่องจากพร็อพเพอร์ตี้ในสไตล์จะไม่เพิ่มค่า ระยะห่างจากขอบที่ส่งเข้ามาล่าสุดจะลบล้าง contentPaddingHorizontal ที่ตั้งค่าโดย contentPadding เริ่มต้น นอกจากนี้ สีพื้นหลังล่าสุดจะลบล้างสีพื้นหลังที่ตั้งค่าโดยสไตล์เริ่มต้นที่ส่งเข้ามา

val style1 = Style {
    background(Color.Red)
    contentPadding(32.dp)
}

val style2 = Style {
    contentPaddingHorizontal(8.dp)
    background(Color.LightGray)
}

BaseButton(
    style = style1 then style2,
    onClick = {

    },
) {
    BaseText("Click me!")
}

ในกรณีนี้ การจัดรูปแบบที่ใช้จะมีพื้นหลังสีเทาอ่อนและระยะห่างจากขอบ 32.dp ยกเว้นระยะห่างจากขอบด้านซ้ายและขวาซึ่งมีค่าเป็น 8.dp

ปุ่มที่มี contentPadding ซึ่งถูกลบล้างโดย Styles อื่นๆ
รูปที่ 3 ปุ่มที่มี contentPadding ซึ่งถูกลบล้างโดยสไตล์ต่างๆ

การรับช่วงสไตล์

พร็อพเพอร์ตี้สไตล์บางอย่าง เช่น contentColor และพร็อพเพอร์ตี้ที่เกี่ยวข้องกับสไตล์ข้อความ จะเผยแพร่ไปยังคอมโพสเซเบิลย่อย สไตล์ที่ตั้งค่าในคอมโพสเซเบิลย่อยจะลบล้างการจัดรูปแบบระดับบนสุดที่รับช่วงมาสำหรับคอมโพสเซเบิลย่อยนั้นๆ

การส่งต่อสไตล์ด้วยพารามิเตอร์ Style, styleable และ direct
รูปที่ 4 การเผยแพร่สไตล์ด้วย Style, styleable และพารามิเตอร์โดยตรง
รายการสำคัญ วิธีการ เอฟเฟ็กต์
1 (สูงสุด) อาร์กิวเมนต์โดยตรงในคอมโพสเซเบิล ลบล้างทุกอย่าง เช่น Text(color = Color.Red)
2 พารามิเตอร์สไตล์ สไตล์ภายในจะลบล้าง Text(style = Style { contentColor(Color.Red)}
3 เชนตัวปรับแต่ง Modifier.styleable{ contentColor(Color.Red) ในคอมโพเนนต์เอง
4 (ต่ำสุด) สไตล์ระดับบนสุด สำหรับพร็อพเพอร์ตี้ที่รับช่วงได้ (การจัดรูปแบบตัวอักษร/สี) ที่ส่งมาจากระดับบนสุด

การจัดรูปแบบระดับบนสุด

คุณสามารถตั้งค่าพร็อพเพอร์ตี้ข้อความ (เช่น contentColor) จากคอมโพสเซเบิลระดับบนสุด และพร็อพเพอร์ตี้เหล่านั้นจะเผยแพร่ไปยังคอมโพสเซเบิล Text ย่อยทั้งหมด

val styleState = remember { MutableStyleState(null) }
Column(
    modifier = Modifier.styleable(styleState) {
        background(Color.LightGray)
        val blue = Color(0xFF4285F4)
        val purple = Color(0xFFA250EA)
        val colors = listOf(blue, purple)
        contentBrush(Brush.linearGradient(colors))
    },
) {
    BaseText("Children inherit", style = { width(60.dp) })
    BaseText("certain properties")
    BaseText("from their parents")
}

การรับช่วงพร็อพเพอร์ตี้ของ Composable ย่อย
รูปที่ 5 การรับช่วงพร็อพเพอร์ตี้ของคอมโพสเซเบิลย่อย

การลบล้างพร็อพเพอร์ตี้ของคอมโพสเซเบิลย่อย

นอกจากนี้ คุณยังตั้งค่าการจัดรูปแบบในคอมโพสเซเบิล Text ที่เฉพาะเจาะจงได้ด้วย หากคอมโพสเซเบิลระดับบนสุดมีการตั้งค่าการจัดรูปแบบไว้ การจัดรูปแบบที่ตั้งค่าในคอมโพสเซเบิลย่อยจะลบล้างการจัดรูปแบบของคอมโพสเซเบิลระดับบนสุด

val styleState = remember { MutableStyleState(null) }
Column(
    modifier = Modifier.styleable(styleState) {
        background(Color.LightGray)
        val blue = Color(0xFF4285F4)
        val purple = Color(0xFFA250EA)
        val colors = listOf(blue, purple)
        contentBrush(Brush.linearGradient(colors))
    },
) {
    BaseText("Children can ", style = {
        contentBrush(Brush.linearGradient(listOf(Color.Red, Color.Blue)))
    })
    BaseText("override properties")
    BaseText("set by their parents")
}

Composable ขององค์ประกอบย่อยจะลบล้างพร็อพเพอร์ตี้ขององค์ประกอบหลัก
รูปที่ 6 คอมโพสเซเบิลย่อยจะลบล้างพร็อพเพอร์ตี้ระดับบนสุด

ใช้พร็อพเพอร์ตี้สไตล์ที่กำหนดเอง

คุณสามารถสร้างพร็อพเพอร์ตี้ที่กำหนดเองซึ่งแมปกับคำจำกัดความสไตล์ที่มีอยู่ได้โดยใช้ฟังก์ชันส่วนขยายใน StyleScope ดังที่แสดงในตัวอย่างต่อไปนี้

fun StyleScope.outlinedBackground(color: Color) {
    border(1.dp, color)
    background(color)
}

ใช้พร็อพเพอร์ตี้ใหม่นี้ภายในคำจำกัดความสไตล์

val customExtensionStyle = Style {
    outlinedBackground(Color.Blue)
}

ระบบไม่รองรับการสร้างพร็อพเพอร์ตี้ที่จัดรูปแบบได้ใหม่ หากกรณีการใช้งานของคุณ ต้องมีการรองรับดังกล่าว โปรดส่งคำขอฟีเจอร์

อ่านค่า CompositionLocal

รูปแบบที่ใช้กันทั่วไปคือการจัดเก็บโทเค็นระบบการออกแบบไว้ใน CompositionLocal เพื่อเข้าถึงตัวแปรโดยไม่ต้องส่งตัวแปรเป็นพารามิเตอร์ สไตล์สามารถเข้าถึง CompositionLocal เพื่อดึงค่าทั้งระบบภายในสไตล์ได้ดังนี้

val buttonStyle = Style {
    contentPadding(12.dp)
    shape(RoundedCornerShape(50))
    background(Brush.verticalGradient(LocalCustomColors.currentValue.background))
}