Computer >> Máy Tính >  >> Hệ thống >> Android

Cách tạo kiểu và tạo chủ đề cho một ứng dụng với Jetpack Compose

Trong bài này, chúng ta sẽ học cách tạo kiểu và tạo chủ đề cho một ứng dụng trong Jetpack Compose.

Soạn là một khung giao diện người dùng mới dành cho Android (mặc dù hỗ trợ Máy tính để bàn và Web đang được phát triển), thay thế hệ thống Chế độ xem dựa trên XML cũ.

Mặc dù vẫn đang trong bản phát hành beta kể từ khi viết bài này, tôi không mong đợi phần cụ thể này của thư viện sẽ thay đổi đáng kể để có bản phát hành ổn định.

Các chủ đề bao gồm:

  • Bản tóm tắt ngắn gọn về cách tiếp cận XML
  • Cách di chuyển từ hệ thống màu sắc, chủ đề và kiểu chữ (phông chữ) dựa trên XML
  • Cách thiết lập chủ đề sáng và tối cho ứng dụng của bạn chỉ trong vài dòng mã
  • Cách sử dụng thông tin kiểu mới dựa trên Kotlin trong các tác phẩm tổng hợp của bạn
  • Cách tạo kiểu cụ thể cho Phần mềm văn bản

Trước khi tiếp tục, điều quan trọng là bạn phải hiểu tổng hợp là gì. Tôi sẽ không dừng lại để giải thích khái niệm đó ở đây, như tôi đã có trong bài viết này.

Xem video ngắn này để biết tóm tắt.

Cách chúng tôi sử dụng để tạo kiểu ứng dụng Android bằng tài nguyên XML

Như thường lệ, tôi muốn chia sẻ với bạn những động lực đằng sau và một chút lịch sử về những chủ đề này. Trong trường hợp bạn không quan tâm, vui lòng bỏ qua phần tiếp theo để chúng ta đi sâu vào nội dung thực tế.

Tài nguyên Android

Hệ thống tài nguyên ứng dụng Android là thứ mà nhóm Android xứng đáng được đánh giá cao, ít nhất là theo ý kiến ​​của tôi. Nhưng giống như mọi quyết định thiết kế, một tính năng trong một tình huống này sẽ trở thành một lỗ hổng trong một tình huống khác.

Cụ thể, một trong những thách thức lớn nhất đối với cả nhà phát triển nền tảng và ứng dụng là tạo ra thứ mà tôi sẽ gọi là tài nguyên bản địa hóa . Tôi đang đề cập đến thách thức xây dựng ứng dụng:

  • Hiển thị văn bản và đồ họa bằng nhiều ngôn ngữ và bảng chữ cái khác nhau
  • Nhìn và cảm thấy tương xứng với nhiều loại yếu tố hình thức (kích thước, mật độ, v.v.).

Đó chỉ là hai ví dụ phổ biến - còn rất nhiều điều khác nữa. Hệ thống tài nguyên cung cấp cho chúng tôi một nơi mà các nhà phát triển ứng dụng có thể cung cấp các tài nguyên được bản địa hóa mà nền tảng có thể chọn tại thời điểm biên dịch. Điều này giúp chúng ta không phải tự viết mã soạn sẵn đó.

Tính năng hay Lỗi?

Mặc dù tôi không bao giờ muốn tự mình quản lý mã soạn sẵn cần thiết cho các tài nguyên chuỗi được bản địa hóa, nhưng điều đó không có nghĩa là tôi thích viết XML.

Trên thực tế, có rất ít điều tôi muốn làm trong XML qua một ngôn ngữ hiện đại, thành ngữ và thanh lịch như Kotlin hoặc Swift. Ngoài sở thích cá nhân, có một lý do kỹ thuật hơn tại sao tài nguyên XML không phải lúc nào cũng lý tưởng.

Xin lưu ý rằng điều này không có nghĩa là một lời chỉ trích của các nhà phát triển / kỹ sư nền tảng. Nó chỉ đơn thuần là quan sát xem các quyết định thiết kế luôn có lợi ích và chi phí như thế nào.

Để tích hợp các tài nguyên dựa trên XML của chúng tôi vào mã ứng dụng dựa trên JVM, chúng tôi nhất thiết phải có các lớp dịch (biên dịch) và cầu nối nền tảng (API). Điều này có thể gây khó khăn cho cả nhà phát triển nền tảng và ứng dụng.

Hai vấn đề phổ biến mà tôi gặp phải là:

  • Tôi muốn truy cập vào một tài nguyên ở một nơi mà tôi không muốn kết hợp chặt chẽ với các API nền tảng cung cấp tài nguyên
  • Tôi phải viết một số mã soạn sẵn vô lý chỉ để thay đổi giao diện của một Chế độ xem (nghĩa là ghi đè một cái gì đó được xác định trong các kiểu tài nguyên và chủ đề)

Vấn đề gốc đối với tất cả mọi người tham gia là khớp nối chặt chẽ vào hệ thống View và hệ thống tài nguyên Android (chúng được kết hợp chặt chẽ với nhau).

Đối với các nhà phát triển nền tảng, điều này có nghĩa là họ phải xây dựng dựa trên hoặc làm việc xung quanh các cơ sở mã khổng lồ và cũ. Thêm rằng họ cũng phải cố gắng để các tính năng mới hoạt động trên các phiên bản hệ điều hành Android cũ hơn và điều đó trở thành một công việc vô cùng hữu ích.

Kết quả đối với chúng tôi là các nhà phát triển ứng dụng thường là rất nhiều mã viết sẵn, một số cách giải quyết khó hiểu đối với những thứ mà trực quan có vẻ như chúng phải là một lớp. Chưa kể API chính để lấy các tài nguyên này là Context , là lớp mà bạn thực sự không muốn bị rò rỉ trong bộ nhớ.

Nhập Jetpack Compose.

Cách Thiết lập Chủ đề, Màu sắc và Phông chữ bằng Jetpack Compose

Với đánh giá của chúng tôi về hệ thống cũ, hãy cùng khám phá một cách đẹp hơn và đơn giản hơn nhiều để tạo kiểu và tạo chủ đề cho một ứng dụng Android. Tôi đã nói rằng tôi sẽ giữ điều này thực tế, nhưng cho phép một điểm.

Vì chúng tôi sẽ thực hiện công việc đó trong Kotlin, nên điều đó có nghĩa là một điều rất quan trọng:Cả chúng tôi và các nhà phát triển nền tảng đều ít bị ràng buộc bởi bản dịch (biên dịch) và cầu nối API (R của Android lớp và Context ) giữa XML và JVM.

Nói một cách dễ hiểu, điều này có nghĩa là mã soạn sẵn ít hơn nhiều nhiều quyền kiểm soát hơn trong thời gian chạy .

Đối với phần thực hành của bài viết này, gợi ý của tôi cho bạn là hãy làm theo quy trình này theo thứ tự mà tôi giải thích. Tôi đã cấu trúc nó theo thứ tự khi viết mã này trong một Ứng dụng mới.

Cách thay thế các tài nguyên Colors.xml bằng Kotlin Compose

Nếu bạn vẫn chưa quyết định cách phối màu cho ứng dụng của mình, tôi khuyên bạn nên sử dụng các tài nguyên khác nhau có sẵn trên trang web Material Design chính thức. Hãy thử:

  • Các bảng màu
  • Công cụ màu

Nếu bạn định hỗ trợ các chủ đề ứng dụng sáng và tối (sẽ giải thích ngay sau đây), hãy thử chọn một bảng màu hỗ trợ văn bản trắng và một bảng màu hỗ trợ văn bản đen.

Cách tạo kiểu và tạo chủ đề cho một ứng dụng với Jetpack Compose
Ví dụ về cách phối màu sáng và tối.

Tạo một tệp có tên như Color.kt (tên không quan trọng) và điền vào tệp đó bằng val không thay đổi 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
//...

Bạn có thể sử dụng một giá trị được xác định trước như Color.Black hoặc cung cấp giá trị ARGB Hex của riêng bạn.

Vì ARGB Hex chỉ là một loạt các biệt ngữ để mô tả cái quái gì "0XFF00bc00 "có nghĩa là, hãy để tôi dịch:

  • Hai ký tự đầu tiên 0x nói với trình biên dịch rằng đây là một số thập lục phân
  • Hai ký tự thứ hai, "FF "hoặc" DC ", đại diện cho Tính minh bạch / Độ mờ đục / A lpha trong Hex
  • Sáu cặp ký tự còn lại đại diện cho R ed, G reen và B lue

Cách Thêm Phông chữ và Thay thế fontFamily Thuộc tính

Kiểu chữ (phông chữ) cũng rất dễ quản lý. Đây là kiểu mà các đối số mặc định của Kotlin rất hữu ích.

Tạo một tệp có tên là Type.kt (tên vẫn không quan trọng) và tạo Typography lớp ...:

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
    )
)
//...

... và một số TextStyle các lớp:

//...
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
)
//...

Cho dù bạn cung cấp các chức năng hoặc giá trị công khai (Tôi khuyên bạn không nên sử dụng var tại đây) tùy thuộc vào sở thích cá nhân của bạn và yêu cầu hiện tại.

Cách tạo Chủ đề ứng dụng trong Jetpack Compose

Điều cuối cùng bạn cần định cấu hình trước khi sử dụng chủ đề của mình trong các tệp tổng hợp của bạn là MaterialTheme @Composable . Tôi có bảng màu sáng và tối của mình trong một tệp có tên 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
    )
}

Vì bạn hẳn đã quen thuộc với việc tổng hợp là gì (tôi đã cảnh báo công bằng cho bạn), điều mới duy nhất ở đây là darkTheme: Boolean = isSystemInDarkTheme() .

Để đưa ra lời giải thích đơn giản, isSystemInDarkTheme() là một cuộc gọi hỏi bất kỳ thiết bị Android tương thích nào về sở thích của người dùng về chủ đề sáng hay tối.

trả về giá trị boolean mà chúng ta có thể sử dụng trong một biểu thức Gán bậc ba (Có điều kiện) chẳng hạn như colors = if (darkTheme) DarkColorPalette else LightColorPalette .

Đó thực sự là nó. Màu sắc, Phông chữ và hai Chủ đề được xác định sau vài phút.

Cách sử dụng chủ đề trong soạn thư

Bây giờ đã đến lúc sử dụng Chủ đề này trong ứng dụng của bạn. Trong ứng dụng này, chỉ có hai màn hình chính, tôi chỉ sử dụng Hoạt động làm vùng chứa cho các tác phẩm tổng hợp của tôi:

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

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

Bất cứ nơi nào bạn thấy mình đang gọi setContent {} , gợi ý của tôi cho người mới bắt đầu là đặt ngay Chủ đề của bạn có thể kết hợp vào bên trong nó. Làm như vậy sẽ khiến thông tin kiểu phân tầng / kế thừa cho từng tệp có thể tổng hợp lồng nhau .

Bạn xong việc rồi! Gần như vậy.

Cách Ghi đè Kiểu và Chủ đề

Nếu bạn có thể giúp được, hãy cố gắng đưa bất kỳ màu nào bạn muốn vào bảng màu sáng và tối. Bằng cách này, khi bạn gọi MaterialTheme.colors.<Color> , hệ thống sẽ xử lý logic có điều kiện cần thiết để chọn bảng màu thích hợp:

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

Tuy nhiên, đôi khi nó phù hợp hơn để viết logic có điều kiện của riêng bạn ... hoặc tôi chỉ lười biếng. May mắn thay, Compose cung cấp nhiều cấu hình như vậy có sẵn dưới dạng thuộc tính:

@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 trả về một boolean cho biết chúng đang ở chế độ nào, sau đó chúng ta có thể sử dụng một Phép gán bậc ba khác từ đó.

Cách tạo kiểu cho văn bản có thể ghép lại

Chỉ cần đặt style đối số bằng một trong các kiểu văn bản của bạn (cho dù nó đến từ MaterialTheme hoặc một trong các kiểu trong 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
)

TextStylecopy của riêng nó chức năng sẵn sàng hoạt động nếu bạn cần ghi đè bất kỳ thứ gì.

Và đó là nó! Bây giờ bạn đã biết cách tạo kiểu và tạo chủ đề cho một ứng dụng bằng Jetpack Compose. Cảm ơn vì đã đọc :)

Xã hội

Bạn có thể tìm thấy tôi trên Instagram tại đây và trên Twitter tại đây.

Dưới đây là một số hướng dẫn và khóa học của tôi

https://youtube.com/wiseass https://www.freecodecamp.org/news/author/ryan-michael-kay/ https://skl.sh/35IdKsj (giới thiệu về Android với Android Studio)