Computer >> คอมพิวเตอร์ >  >> ระบบ >> Android

วิธีจัดรูปแบบและกำหนดธีมของแอปด้วย Jetpack Compose

ในบทความนี้ เราจะเรียนรู้วิธีจัดรูปแบบและกำหนดธีมของแอปพลิเคชันใน Jetpack Compose

เขียนเป็นเฟรมเวิร์ก UI ใหม่สำหรับ Android (แม้ว่าจะมีการพัฒนาการสนับสนุนเดสก์ท็อปและเว็บ) ซึ่งจะมาแทนที่ระบบมุมมองแบบ XML แบบเก่า

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

หัวข้อได้แก่:

  • สรุปสั้นๆ เกี่ยวกับแนวทาง XML
  • วิธีการโยกย้ายจากระบบสี ธีม และการพิมพ์ (แบบอักษร) แบบ XML
  • วิธีตั้งค่าธีมสว่างและมืดสำหรับแอปของคุณในโค้ดเพียงไม่กี่บรรทัด
  • วิธีใช้ข้อมูลรูปแบบ Kotlin ใหม่ในคอมโพสิทของคุณ
  • วิธีการจัดรูปแบบ Text Composable โดยเฉพาะ

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

ดูวิดีโอสั้นๆ เพื่อดูข้อมูลสรุป

วิธีที่เราใช้จัดรูปแบบแอป Android โดยใช้ทรัพยากร XML

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

ทรัพยากร Android

ระบบทรัพยากรของแอป Android เป็นสิ่งที่ทีม Android สมควรได้รับคะแนนสูงสุด อย่างน้อยในความคิดของฉัน แต่เช่นเดียวกับการตัดสินใจในการออกแบบทุกครั้ง คุณลักษณะในสถานการณ์หนึ่งจะกลายเป็นข้อบกพร่องในอีกสถานการณ์หนึ่ง

อย่างเจาะจง หนึ่งในความท้าทายที่ยิ่งใหญ่ที่สุดสำหรับทั้งนักพัฒนาแพลตฟอร์มและนักพัฒนาแอปพลิเคชันคือการสร้างสิ่งที่ฉันจะเรียกว่าทรัพยากรที่แปลเป็นภาษาท้องถิ่น . ฉันหมายถึงความท้าทายในการสร้างแอปที่:

  • แสดงข้อความและกราฟิกในภาษาและตัวอักษรต่างๆ
  • รูปลักษณ์และสัมผัสได้สัดส่วนกับรูปแบบปัจจัยที่หลากหลาย (ขนาด ความหนาแน่น และอื่นๆ)

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

คุณลักษณะหรือข้อบกพร่อง

แม้ว่าฉันจะไม่ต้องการจัดการโค้ดสำเร็จรูปซึ่งจำเป็นสำหรับทรัพยากรสตริงที่แปลเป็นภาษาท้องถิ่น แต่นั่นไม่ได้หมายความว่าฉันสนุกกับการเขียน XML

อันที่จริง มีบางสิ่งที่ฉันอยากทำใน XML น้อยมาก ในภาษาสมัยใหม่ สำนวน และสง่างามเช่น Kotlin หรือ Swift นอกจากความชอบส่วนบุคคลแล้ว ยังมีเหตุผลทางเทคนิคอีกว่าทำไมทรัพยากร XML จึงไม่เหมาะเสมอไป

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

ในการผสานรวมทรัพยากรแบบ XML เข้ากับโค้ดแอปพลิเคชันที่ใช้ JVM เราจำเป็นต้องมีชั้นการแปล (การรวบรวม) และ สะพานแพลตฟอร์ม (API). สิ่งนี้สามารถนำเสนอปัญหาสำหรับทั้งผู้พัฒนาแพลตฟอร์มและแอปพลิเคชัน

ปัญหาทั่วไปที่ฉันพบคือ:

  • ฉันต้องการเข้าถึงทรัพยากรในที่ที่ฉันไม่ต้องการเชื่อมต่อกับ API ของแพลตฟอร์มซึ่งจัดหาทรัพยากรอย่างแน่นหนา
  • ฉันต้องเขียนโค้ดสำเร็จรูปที่ไร้สาระเพียงเพื่อเปลี่ยนรูปลักษณ์ของมุมมอง (นั่นคือ แทนที่บางสิ่งที่กำหนดไว้ภายในรูปแบบและธีมของทรัพยากร)

ปัญหารากเหง้า สำหรับทุกคนที่เกี่ยวข้องคือการมีเพศสัมพันธ์ที่แน่นหนา กับระบบดูและระบบทรัพยากร Android (ซึ่งประกอบเข้าด้วยกันอย่างแน่นหนา)

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

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

ป้อน Jetpack เขียน

วิธีตั้งค่าธีม สี และแบบอักษรด้วย Jetpack Compose

ด้วยการทบทวนระบบเก่าของเรา เรามาสำรวจวิธีการจัดสไตล์และธีมแอปพลิเคชัน Android ที่สวยงามและเรียบง่ายกว่ากัน ฉันบอกว่าฉันจะรักษาสิ่งนี้ไว้ได้จริง แต่ให้จุดหนึ่ง

เนื่องจากเราจะทำงานนั้นใน Kotlin จึงหมายถึงสิ่งหนึ่งที่สำคัญมาก:ทั้งเราและนักพัฒนาแพลตฟอร์มต่างก็ผูกพันกันน้อยกว่ามากโดยการแปล (การรวบรวม) และการเชื่อมโยง API (R ของ Android) คลาสและ Context ) ระหว่าง XML และ JVM

พูดง่ายๆ ก็คือ รหัสต้นแบบน้อยกว่ามาก และ ควบคุมได้มากขึ้นในขณะรันไทม์ .

สำหรับภาคปฏิบัติของบทความนี้ คำแนะนำของฉันคือให้ทำตามขั้นตอนนี้ตามลำดับที่ฉันอธิบาย ฉันได้จัดโครงสร้างตามลำดับที่ฉันติดตามเมื่อเขียนโค้ดนี้ในแอปใหม่

วิธีการแทนที่แหล่งข้อมูล Colors.xml ด้วย Kotlin Compose

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

  • จานสี
  • เครื่องมือสี

หากคุณวางแผนที่จะรองรับธีมแอพสีอ่อนและสีเข้ม (มีคำอธิบายเร็วๆ นี้) ให้ลองเลือกแบบแผนชุดสีที่รองรับข้อความสีขาวและชุดรูปแบบสีที่รองรับข้อความสีดำ

วิธีจัดรูปแบบและกำหนดธีมของแอปด้วย Jetpack Compose
ตัวอย่างโทนสีอ่อนและสีเข้ม

สร้างไฟล์ที่เรียกว่า Color.kt (ชื่อไม่สำคัญ) และเติมด้วย val ที่ไม่เปลี่ยนรูป ues:

import androidx.compose.ui.graphics.Color

val primaryGreen = Color(0XFF00bc00)
val primaryCharcoal = Color(0xFF2b2b2b)
val accentAmber = Color(0xFFffe400)

val textColorLight = Color(0xDCFFFFFF)
val textColorDark = Color(0xFFf3f3f3)
val gridLineColorLight = Color.Black
//...

คุณสามารถใช้ค่าที่กำหนดไว้ล่วงหน้าเช่น Color.Black หรือระบุค่า ARGB Hex ของคุณเอง

เนื่องจาก ARGB Hex เป็นเพียงกลุ่มของศัพท์แสงที่อธิบายว่าห่าอะไร "0XFF00bc00 " แปลว่า ให้ฉันแปล:

  • อักขระสองตัวแรก 0x บอกคอมไพเลอร์ว่านี่คือเลขฐานสิบหก
  • อักขระสองตัวที่สอง , "FF " หรือ "DC " หมายถึง ความโปร่งใส/ความทึบ/A lpha ใน Hex
  • คู่อักขระที่เหลืออีก 6 คู่เป็นตัวแทนของ R เอ็ด จี เรน และ B ลือ

วิธีเพิ่มแบบอักษรและแทนที่ fontFamily คุณสมบัติ

วิชาการพิมพ์ (แบบอักษร) ยังง่ายต่อการจัดการ นี่คือสิ่งที่อาร์กิวเมนต์เริ่มต้นของ Kotlin มีประโยชน์มาก

สร้างไฟล์ที่เรียกว่า Type.kt (ชื่อยังคงไม่สำคัญ) และสร้าง Typography คลาส...:

val typography = Typography(
    body1 = TextStyle(
        fontFamily = FontFamily.Default,
        fontWeight = FontWeight.Normal,
        fontSize = 16.sp
    ),

    button = TextStyle(
        fontFamily = FontFamily.Default,
        fontWeight = FontWeight.Bold,
        fontSize = 32.sp
    ),

    caption = TextStyle(
        fontFamily = FontFamily.Default,
        fontWeight = FontWeight.Normal,
        fontSize = 12.sp
    )
)
//...

...และ TextStyle some บางส่วน ชั้นเรียน:

//...
val mainTitle = TextStyle(
    fontFamily = FontFamily.Default,
    fontWeight = FontWeight.Light,
    fontSize = 48.sp,
    textAlign = TextAlign.Center
)

fun dropdownText(color: Color) = TextStyle(
    fontFamily = FontFamily.Default,
    fontWeight = FontWeight.Normal,
    fontSize = 32.sp,
    textAlign = TextAlign.Center,
    color = color
)
//...

ไม่ว่าคุณจะให้ฟังก์ชันสาธารณะหรือค่านิยม (ฉันไม่แนะนำให้ใช้ var ที่นี่) ขึ้นอยู่กับความชอบส่วนบุคคลและข้อกำหนดปัจจุบันของคุณ

วิธีสร้างธีมของแอปใน Jetpack Compose

สิ่งสุดท้ายที่คุณต้องกำหนดค่าก่อนใช้ธีมของคุณในคอมโพสิทได้คือ MaterialTheme @Composable . ฉันมีของฉันแล้ว พร้อมด้วยจานสีอ่อนและสีเข้มในไฟล์ชื่อ GraphSudokuTheme:

import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material.MaterialTheme
import androidx.compose.material.darkColors
import androidx.compose.material.lightColors
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color

private val LightColorPalette = lightColors(
    primary = primaryGreen,
    secondary = textColorLight,
    surface = lightGrey,
    primaryVariant = gridLineColorLight,
    onPrimary = accentAmber,
    onSurface = accentAmber
)

private val DarkColorPalette = darkColors(
    //main background color
    primary = primaryCharcoal,
    //used for text color
    secondary = textColorDark,
    //background of sudoku board
    surface = lightGreyAlpha,
    //grid lines of sudoku board
    primaryVariant = gridLineColorLight,
    onPrimary = accentAmber,

    onSurface = accentAmber

)

@Composable
fun GraphSudokuTheme(
    darkTheme: Boolean = isSystemInDarkTheme(),
    content: @Composable () -> Unit
) {

    MaterialTheme(
        colors = if (darkTheme) DarkColorPalette else LightColorPalette,
        typography = typography,
        shapes = shapes,
        content = content
    )
}

เนื่องจากคุณควรจะคุ้นเคยกับสิ่งที่เขียนได้ (ฉันให้คำเตือนที่เป็นธรรมแก่คุณ) สิ่งใหม่ที่นี่คือ darkTheme: Boolean = isSystemInDarkTheme() .

เพื่อให้คำอธิบายแบบง่าย isSystemInDarkTheme() เป็นการโทรที่ถามอุปกรณ์ Android ที่ใช้งานร่วมกันได้เพื่อให้ผู้ใช้เลือกธีมสีอ่อนหรือสีเข้ม

คืนค่าบูลีน ซึ่งเราสามารถใช้ใน Ternary (Conditional) Assignment expression เช่น colors = if (darkTheme) DarkColorPalette else LightColorPalette .

ที่เป็นจริงมัน กำหนดสี แบบอักษร และสองธีมในไม่กี่นาที

วิธีใช้ธีมในการเขียน

ถึงเวลาที่จะใช้ธีมนี้ในแอปของคุณแล้ว ในแอพนี้ซึ่งมีหน้าจอหลักเพียงสองหน้าจอ ฉันแค่ใช้กิจกรรมเป็น คอนเทนเนอร์ สำหรับคอมโพสิทของฉัน:

class NewGameActivity : AppCompatActivity(), NewGameContainer {
	//...
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
		//...

        setContent {
            GraphSudokuTheme {
                NewGameScreen(
                    onEventHandler = logic::onEvent,
                    viewModel
                )
            }
        }
		//...
    }

ทุกที่ที่คุณพบว่าตัวเองโทร setContent {} คำแนะนำของฉันสำหรับผู้เริ่มต้นคือการวางธีมที่ประกอบได้ไว้ข้างในทันที การทำเช่นนั้นจะทำให้ข้อมูลรูปแบบเรียงต่อกัน/สืบทอดไปยังแต่ละองค์ประกอบที่ซ้อนกันได้ .

คุณทำเสร็จแล้ว! ใกล้แล้วครับ

วิธีการแทนที่สไตล์และธีม

หากคุณสามารถช่วยได้ ให้ลองใส่สีใดๆ ที่คุณต้องการลงในจานสีอ่อนและสีเข้ม วิธีนี้เมื่อคุณโทร MaterialTheme.colors.<Color> , ระบบจะจัดการตรรกะแบบมีเงื่อนไขที่จำเป็นในการเลือกจานสีที่เหมาะสม:

@Composable
fun NewGameContent(
    onEventHandler: (NewGameEvent) -> Unit,
    viewModel: NewGameViewModel
) {
    Surface(
        Modifier
            .wrapContentHeight()
            .fillMaxWidth()
    ) {
        ConstraintLayout(Modifier.background(MaterialTheme.colors.primary)) { 
        	//...
        }
        //...
      }
}      
        

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

@Composable
fun DoneIcon(onEventHandler: (NewGameEvent) -> Unit) {
    Icon(
        imageVector = Icons.Filled.Done,
        tint = if (MaterialTheme.colors.isLight) textColorLight 
        else textColorDark,
        contentDescription = null,
        modifier = Modifier
            .clickable(
            //...
            )
    )
}

MaterialTheme.Colors.isLight คืนค่าบูลีนที่ระบุโหมดที่พวกเขาอยู่ใน จากนั้นเราสามารถใช้ Ternary Assignment อื่นได้จากที่นั่น

วิธีจัดรูปแบบข้อความที่เขียนได้

เพียงแค่ตั้งค่า style อาร์กิวเมนต์เท่ากับหนึ่งในสไตล์ข้อความของคุณ (ไม่ว่าจะมาจาก MaterialTheme หรือรูปแบบใดรูปแบบหนึ่งภายใน Type.kt ):

Text(
    text = stat.toTime(),
    style = statsLabel.copy(
        color = if (isZero) Color.White
        else MaterialTheme.colors.onPrimary,
    fontWeight = FontWeight.Normal
    ),
    modifier = Modifier
        .wrapContentSize()
        .padding(end = 2.dp, bottom = 4.dp),
        textAlign = TextAlign.End
)

TextStyle มี copy . เป็นของตัวเอง ฟังก์ชันพร้อมใช้งานหากคุณต้องการเขียนทับสิ่งใด

และนั่นแหล่ะ! ตอนนี้คุณรู้วิธีจัดรูปแบบและกำหนดธีมของแอปพลิเคชันโดยใช้ Jetpack Compose ขอบคุณสำหรับการอ่าน :)

โซเชียล

คุณสามารถพบฉันบน Instagram ที่นี่และบน Twitter ที่นี่

ต่อไปนี้คือบทเรียนและหลักสูตรบางส่วนของฉัน

https://youtube.com/wiseass https://www.freecodecamp.org/news/author/ryan-michael-kay/ https://skl.sh/35IdKsj (แนะนำ Android พร้อม Android Studio)