002 Learning Jetpack Compose Basic Components

Table of contents

1. Text component

2. Button component

3. TextField component

4. Image component


1. Text component

The Text component is the original TextView component, and its usage is quite simple. The simple Text usage is as follows:

package com.test.compose

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import com.test.compose.ui.theme.ComposeTestTheme

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            ComposeTestTheme {
                // A surface container using the 'background' color from the theme
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    Greeting("Compose")
                }
            }
        }
    }
}

@Composable
fun Greeting(name: String) {
    Text(
        text = "Hello $name!"
    )
}

The display effect of the above code on the real machine is Hello Compose!, as follows:

 The above is a simple use of text, and if necessary, pass parameters in Text:

fun Text(
    text: String,                                        //文本内容
    modifier: Modifier = Modifier,                       //很复杂,参考:https://developer.android.google.cn/jetpack/compose/modifiers-list?hl=zh-cn 
    color: Color = Color.Unspecified,                    //文本颜色
    fontSize: TextUnit = TextUnit.Unspecified,           //文本大小 
    fontStyle: FontStyle? = null,                        //文本样式
    fontWeight: FontWeight? = null,                      //绘制文本时使用的字体粗细(例如 FontWeight.Bold)  
    fontFamily: FontFamily? = null,                      //渲染文本时使用的字体系列。请参阅 TextStyle.fontFamily。
    letterSpacing: TextUnit = TextUnit.Unspecified,      //每个字母之间添加的空格量。请参阅 TextStyle.letterSpacing。
    textDecoration: TextDecoration? = null,              //在文本上绘制的装饰(例如下划线)。请参阅 TextStyle.textDecoration。
    textAlign: TextAlign? = null,                        //段落行内文本的对齐方式。参见文本样式
    lineHeight: TextUnit = TextUnit.Unspecified,         //TextUnit 单位中段落的行高,例如SP 或 EM。请参阅 TextStyle.lineHeight。
    overflow: TextOverflow = TextOverflow.Clip,          //应如何处理视觉溢出。如果多余文字怎么处理,例如多余文字不显示
    softWrap: Boolean = true,                            //softWrap为false只能单行显示
    maxLines: Int = Int.MAX_VALUE,                       //最大行数,如果上面softWrap为false最大行数设置是无作用的
    onTextLayout: (TextLayoutResult) -> Unit = {},       //计算新文本布局时执行的回调。
    style: TextStyle = LocalTextStyle.current            //文本的样式配置,例如颜色、字体、行高等。
)

The display effect after setting the above fields:

2. Button component

Button is a very common component, and it is very simple to use, just add Button to it, as follows:

    Column() {
        Text(
            text = "Hello11111111111222222222111111111111111111111111111111111111111111111111111111111111 $name!",
            color = Color.Blue,     //字体颜色蓝色
            fontSize = 30.sp,       //字体大小30sp
            fontStyle = FontStyle.Italic,   //字体风格斜体
            fontWeight = FontWeight.Bold,   //字体加粗
            fontFamily = FontFamily.Cursive,//字体系列
            letterSpacing = 10.sp,          //文字间隔10sp
            textDecoration = TextDecoration.Underline,     //文字加下划线
            textAlign = TextAlign.End,       //段落右对齐
            lineHeight = 50.sp,              //每行高度,注意不是文字高度,是文字所在行高度
            overflow = TextOverflow.Ellipsis,    //超过行数多余部分文字截取并用...表示
            softWrap = true,                 //是否单行显示,true不是单行显示
            maxLines = 2                     //显示两行
        )
        Button(onClick = { /*TODO*/ }) {

        }
    }

The above code shows the effect:

 It can be seen from the display effect that there is only one button without text. The detailed parameters of the Button are as follows:

fun Button(
    onClick: () -> Unit,                //点击事件
    modifier: Modifier = Modifier,      //同上,很复杂  
    enabled: Boolean = true,            //控制该按钮的启用状态。当为 false 时,该组件将不会响应用户输入,并且它将显示为视觉上禁用并且对辅助服务禁用。
    shape: Shape = ButtonDefaults.shape,//定义此按钮的容器、边框(当边框不为空时)和阴影(当使用高度时)的形状
    colors: ButtonColors = ButtonDefaults.buttonColors(),//ButtonColors 将用于解析此按钮在不同状态下的颜色。请参阅 ButtonDefaults.buttonColors。
    elevation: ButtonElevation? = ButtonDefaults.buttonElevation(),//控制按钮下方阴影的大小
    border: BorderStroke? = null,        //围绕该按钮的容器绘制的边框
    contentPadding: PaddingValues = ButtonDefaults.ContentPadding,    //在容器和内容之间内部应用的间距值
    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },//MutableInteractionSource 表示此按钮的交互流。您可以创建并传入您自己记住的实例来观察交互并自定义该按钮在不同状态下的外观行为。
    content: @Composable RowScope.() -> Unit
) {
//此处可以包装不同的组件,例如:Text
}
        Button(
            onClick = {
                Toast.makeText(context, "我被点击了!", Toast.LENGTH_SHORT).show()
            },
        ) {
            Text(text = "我是按钮")
        }

The above code then displays the interaction process on the mobile phone as follows:

3. TextField component

The TextField component is similar to the original EditText component, but the use is different. The following is a simple implementation of TextField:
Column {
        ...
        TextField(value = "", onValueChange = {})
    }

The effect of the above implementation is as follows:

 Then enter text from the input box and find that there is no response. This is the biggest difference from EditText. Since Compose is a state-driven data mode, a state needs to be defined here, and then assigned to TextField. I won’t go into details here, and I will talk about it later. Continue to elaborate on this state, and then we modify the code to look like this:

    //用于记录文本输入框的输入的数据
    var inputText by remember {
        mutableStateOf("")
    }

    val context = LocalContext.current
    Column {
        ...
        TextField(value = inputText, onValueChange = {inputText = it})
    }

Then run the above code, you can find that you can enter the content at this time

Then let's talk about the relevant properties of TextField in detail

fun TextField(
    value: String,                            //要在文本字段中显示的输入文本
    onValueChange: (String) -> Unit,          //输入服务(软键盘)更新文本时触发的回调。更新的文本作为回调的参数
    modifier: Modifier = Modifier,            //复杂,同上
    enabled: Boolean = true,                  //控制此文本字段的启用状态。当为 false 时,该组件将不会响应用户输入,并且它将显示为视觉上禁用并且对辅助服务禁用。
    readOnly: Boolean = false,                //控制文本字段的可编辑状态。如果为 true,则无法修改文本字段。但是,用户可以聚焦它并从中复制文本。只读文本字段通常用于显示用户无法编辑的预填写表单。
    textStyle: TextStyle = LocalTextStyle.current,    //要应用于输入文本的样式。默认为 LocalTextStyle。
    label: @Composable (() -> Unit)? = null,          //输入框文字提示(也不一定非要是文字),一直都在
    placeholder: @Composable (() -> Unit)? = null,    //输入框文字提示(也不一定非要是文字),输入文字后会消失
    leadingIcon: @Composable (() -> Unit)? = null,    //输入框左侧图标(也不一定非要是图标)
    trailingIcon: @Composable (() -> Unit)? = null,   //输入框右侧图标(也不一定非要是图标)
    supportingText: @Composable (() -> Unit)? = null, //下方的提示,可以是文字图标,isError为true可以变色提示
    isError: Boolean = false,        //是否输入有误
    visualTransformation: VisualTransformation = VisualTransformation.None,    //转换输入值的视觉表示形式 例如,您可以使用PasswordVisualTransformation 创建密码文本字段。默认情况下,不应用任何视觉变换。
    keyboardOptions: KeyboardOptions = KeyboardOptions.Default,    //软件键盘选项,包含 KeyboardType 和 ImeAction 等配置。
    keyboardActions: KeyboardActions = KeyboardActions.Default,    //当输入服务发出 IME 操作时,将调用相应的回调。请注意,此 IME 操作可能与您在 KeyboardOptions.imeAction 中指定的不同。
    singleLine: Boolean = false,    //当为 true 时,此文本字段将成为单个水平滚动文本字段,而不是换行到多行
    maxLines: Int = Int.MAX_VALUE,    //以最大可见行数表示的最大高度。应等于或大于 1。请注意,如果 singleLine 设置为 true,则该参数将被忽略,相反 maxLines 将设置为 1。
    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },    //交互源 - MutableInteractionSource 表示此文本字段的交互流。您可以创建并传入您自己记住的实例来观察交互并自定义此文本字段在不同状态下的外观行为。
    shape: Shape = TextFieldDefaults.filledShape,        //定义此文本字段容器的形状
    colors: TextFieldColors = TextFieldDefaults.textFieldColors()    //TextFieldColors 将用于解析不同状态下此文本字段使用的颜色。
)

Then the code after we set most of the properties is as follows:

Column {
        TextField(
            value = inputText,
            onValueChange = { inputText = it },
            enabled = true,
            readOnly = false,
            label = {
                Text(
                    text = "账号"
                )
            },
            placeholder = {
                Text(text = "Type something here")
            },
            leadingIcon = {
                Icon(imageVector = Icons.Default.AccountBox, contentDescription = "左边的图标")
            },
            trailingIcon = {
                Icon(imageVector = Icons.Default.Edit, contentDescription = "左边的图标")
            },
            supportingText = {
                Text(
                    text = if (inputText == "error") {
                        "error"
                    } else {
                        ""
                    }
                )
            },
            isError = inputText == "error",
//            visualTransformation = PasswordVisualTransformation(),
            keyboardOptions = KeyboardOptions(
                keyboardType = KeyboardType.Ascii,
                imeAction = ImeAction.Done
            ),//输入英文字符,右下角是下一步操作
            keyboardActions = KeyboardActions(
                onDone = {
                    Toast.makeText(
                        context,
                        "onDone",
                        Toast.LENGTH_SHORT
                    ).show()
                },
                onGo = { Toast.makeText(context, "onGo", Toast.LENGTH_SHORT).show() },
                onNext = { Toast.makeText(context, "onNext", Toast.LENGTH_SHORT).show() },
                onPrevious = { Toast.makeText(context, "onPrevious", Toast.LENGTH_SHORT).show() },
                onSearch = { Toast.makeText(context, "onSearch", Toast.LENGTH_SHORT).show() },
                onSend = { Toast.makeText(context, "onSend", Toast.LENGTH_SHORT).show() }
            ),//imeAction点击的回调,不过要注意在其他厂商定制系统可能没有作用,比如我的小米手机就没有作用
            singleLine = false,
            maxLines = 3,//最多三行,多余的向下滚动
            shape = RoundedCornerShape(16.dp),//此处不生效
            colors = TextFieldDefaults.outlinedTextFieldColors(textColor = Color.Blue)
        )
        TextField(
            value = inputNumber,
            onValueChange = { inputNumber = it },
            shape = RoundedCornerShape(16.dp)//此处生效
        )
    }

Try to demonstrate all the attributes. The above code demonstrates the effect on the top TextField. csdn is really frustrated, and the video demonstration cannot be at the specified position.

4. Image component

Image corresponds to ImageView in View, which is used to display pictures, so there is no doubt that this is definitely another common control that must be mastered.

The good news is that Image usage is fairly simple, so we should be up and running in no time.

As we all know, pictures in Android usually have two common forms, one is a drawable resource, and the other is a bitmap object. Image provides support for both types of images.

First, let's take a look at how to load a picture in the form of a drawable resource. The code is as follows:

Column {
        ...
        Image(
            painter = painterResource(id = R.drawable.ic_launcher_foreground),
            contentDescription = "A launcher image"
        )
    }

The above code can display the picture, as shown below:

 There are two required parameters on the Image parameter list, among which the painter parameter is used to specify the drawable resource to be displayed, and the contentDescription parameter is used to specify the text description for this resource, and then look at the Image parameter list:

Image(
    painter: Painter,        //显示的图片,必选项
    contentDescription: String?,    //图片的描述
    modifier: Modifier = Modifier,    
    alignment: Alignment = Alignment.Center,    //可选的对齐参数,用于将 Painter 放置在由宽度和高度定义的给定边界内。
    contentScale: ContentScale = ContentScale.Fit,    //可选缩放参数,用于确定在边界大小与 Painter 的固有大小不同时要使用的纵横比缩放
    alpha: Float = DefaultAlpha,        //当 Painter 在屏幕上渲染时,应用到 Painter 的可选不透明度默认使 Painter 完全不透明
    colorFilter: ColorFilter? = null,    //当 Painter 在屏幕上渲染时应用可选的 colorFilter
    filterQuality: FilterQuality = DefaultFilterQuality    //当位图缩放并绘制到目标时,采样算法应用于位图。默认值为 FilterQuality.Low,使用双线性采样算法进行缩放
)

Try to demonstrate the above parameters, but some parameters still have no effect, the code is as follows:

    Column {
        ...
        Image(
            painter = painterResource(id = R.drawable.ic_launcher_foreground),
            contentDescription = "A launcher image"
        )
        val bitmap: ImageBitmap =
            ImageBitmap.imageResource(id = android.R.drawable.ic_dialog_dialer)
        Image(
            modifier = Modifier
                .size(100.dp, 50.dp)//控件宽度100 高度50
                .background(Color.Green),//增加绿色背景
            bitmap = bitmap,//显示的图片,注意此处图片是ImageBitmap参数,如果是Bitmap需要进行转换
            contentDescription = "A dialer image",
            alignment = Alignment.BottomEnd,//右下角对齐
            contentScale = ContentScale.Inside,//显示在内部,图片不进行缩放
            alpha = 0.8.toFloat(),//图片透明度
            colorFilter = ColorFilter.lighting(Color.Black, Color.Cyan),//改变图片颜色
            filterQuality = FilterQuality.High//图片质量高
        )
    }

The demonstration effect of the above parameters is as follows:

So far, we have shown only local image resources. So what if you want to display a web image resource?

Unfortunately, the image provided by Compose does not have this capability, and we need to rely on third-party dependent libraries. Of course, ImageView does not have this ability, so we used to use third-party libraries like Glide.

At present, the third-party Compose image loading libraries recommended by Google are Coil and Glide. I know that everyone will feel very kind when they see Glide, and they may be more inclined to use this. But in fact, Coil is a new image loading library developed based on coroutines. Its usage is more suitable for Kotlin and simpler, so I recommend using this new library.

To use Coil, we first need to introduce it into our project:

dependencies {
    implementation "io.coil-kt:coil-compose:2.4.0"
}

Then open the network permission in AndroidManifest

<uses-permission android:name="android.permission.INTERNET" />

Then implement it in code

Column {
        ...
        AsyncImage(
            model = "https://img-blog.csdnimg.cn/20200401094829557.jpg",
            contentDescription = "First line of code"
        )
    }

The above code demonstrates the effect as follows:

 It can be seen that the picture loaded by the network has been displayed

Guess you like

Origin blog.csdn.net/gongjdde/article/details/131709715