前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Jetpack Compose中的基本组件及组件提取

Jetpack Compose中的基本组件及组件提取

作者头像
码客说
发布2024-03-29 12:57:44
1870
发布2024-03-29 12:57:44
举报
文章被收录于专栏:码客

前言

除了布局组件外,Jetpack Compose 还提供了一系列其他常用的 UI 组件。

https://developer.android.google.cn/jetpack/compose/components?hl=zh-cn

https://developer.android.google.cn/courses/pathways/compose?hl=zh-cn

占位

代码语言:javascript
复制
Spacer(modifier = Modifier.height(16.dp))

分割线

代码语言:javascript
复制
Divider(
    color = Color.Black,
    modifier = Modifier.fillMaxHeight().width(1.dp)
)

文本

Text(文本):

代码语言:javascript
复制
Text("Hello, World!")

文本居中

代码语言:javascript
复制
Text(
    text = "A",
    modifier = Modifier
        .background(Color.Red)
        .width(30.dp).height(30.dp)
        .wrapContentSize(Alignment.Center),
    textAlign = TextAlign.Center,
)

设置行数

代码语言:javascript
复制
Text(
    text = "ABC",
    modifier = Modifier
        .background(Color.Red)
        .width(30.dp).height(30.dp)
        .wrapContentSize(Alignment.Center),
    textAlign = TextAlign.Center,
    maxLines = 1
)

按钮

基本使用

代码语言:javascript
复制
Button(
    modifier = Modifier.width(100.dp).height(40.dp),
    shape = MaterialTheme.shapes.medium,
    onClick = { /* 按钮点击事件 */ }
) {
    Text(
        text = "点击",
        fontSize = 16.sp,
        color = Color.White
    )
}

自定义按钮

效果

组件定义

代码语言:javascript
复制
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp

@Composable
fun ZBtnView(text:String){
    val mShape = RoundedCornerShape(6.dp)
    Box(
        modifier = Modifier
            .fillMaxSize()
            .clip(mShape)
    ) {
        Box(
            modifier = Modifier
                .padding(0.dp,6.dp,0.dp,0.dp)
                .fillMaxSize()
                .background(
                    Color(0xff2B89E0),
                    shape =mShape
                )
                .clip(mShape)
        )
        Box(
            modifier = Modifier
                .padding(0.dp,0.dp,0.dp,2.5.dp)
                .fillMaxSize()
                .background(
                    brush = Brush.verticalGradient(
                        colors = listOf(
                            Color(0xff8AEFFD),
                            Color(0xff3BD9FD),
                            Color(0xff32C8FD),
                            Color(0xff36B3FE),
                            Color(0xff50B8FF),
                        ), // 定义垂直渐变色
                        startY = 0f,
                    ),
                    shape = mShape
                )
                .clip(mShape)
        )
        Text(
            text = text,
            color = Color.White,
            style = TextStyle(fontSize = 14.sp),
            textAlign = TextAlign.Center,
            modifier = Modifier
                .align(Alignment.Center)
                .wrapContentSize(Alignment.Center),
        )
    }
}

使用

代码语言:javascript
复制
Box(
    modifier = Modifier
        .align(Alignment.Bottom)
        .size(72.dp, 28.dp)
        .clip(RoundedCornerShape(6.dp))
        .clickable { }) {
    ZBtnView("安装")
}

单选按钮

代码语言:javascript
复制
@Composable
fun MyRadioBtn(onSelectChange: (Boolean) -> Unit) {
    val isSelected = remember {mutableStateOf(false)}
    RadioButton(selected = isSelected.value, onClick = {
        isSelected.value = !isSelected.value
        onSelectChange(isSelected.value)
    })
}

Switch

代码语言:javascript
复制
@Composable
fun SwitchMinimalExample() {
    var checked by remember { mutableStateOf(true) }
    Switch(
        checked = checked,
        onCheckedChange = {
            checked = it
        }
    )
}

文本输入

BasicTextField

代码语言:javascript
复制
BasicTextField(
    value = "",
    onValueChange = {},
)

TextField

代码语言:javascript
复制
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SimpleFilledTextFieldSample() {
    var text by remember { mutableStateOf("") }
    TextField(
        value = text,
        onValueChange = { text = it },
        label = { Text("姓名") }
    )
}

输入类型为密码

代码语言:javascript
复制
@Composable
fun PasswordTextField() {
    var password by rememberSaveable { mutableStateOf("") }

    TextField(
        value = password,
        onValueChange = { password = it },
        label = { Text("Enter password") },
        visualTransformation = PasswordVisualTransformation(),
        keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password)
    )
}

彩虹色文字

代码语言:javascript
复制
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SimpleFilledTextFieldSample() {
    var text by remember { mutableStateOf("") }
    val brush = remember {
        Brush.linearGradient(
            colors = listOf<Color>(Color.Red, Color.Green, Color.Blue)
        )
    }
    TextField(
        value = text, onValueChange = { text = it }, textStyle = TextStyle(brush = brush)
    )
}

OutlinedTextField

代码语言:javascript
复制
@Composable
fun SimpleOutlinedTextFieldSample() {
    var text by remember { mutableStateOf("") }

    OutlinedTextField(
        value = text,
        onValueChange = { text = it },
        label = { Text("Label") }
    )
}

图片

适配模式

代码语言:javascript
复制
Image(
    modifier = Modifier
        .padding(10.dp)
        .size(200.dp, 150.dp)
        .background(color = Color.Yellow),
    painter = painterResource(id = R.drawable.logo),
    contentDescription = null,
    contentScale = ContentScale.Crop
)

contentScale:

  • ContentScale.Fit 等比缩放 保证图片完全显示 默认的方式
  • ContentScale.Crop 等比缩放后居中剪裁
  • ContentScale.Inside 等比缩放保证图片完全显示
  • ContentScale.FillBounds 拉伸填充
  • ContentScale.FillHeight 等比缩放 填充高度
  • ContentScale.FillWidth 等比缩放 填充宽度
  • ContentScale.None 不缩放后居中剪裁

着色

非透明的PNG图片的区域添加着色。

代码语言:javascript
复制
Image(
    modifier = Modifier
        .padding(10.dp)
        .size(200.dp, 150.dp),
    painter = painterResource(id = R.drawable.logo),
    contentDescription = null,
    colorFilter = ColorFilter.tint(color = Color.Green, BlendMode.SrcAtop)
)

圆角

圆形

代码语言:javascript
复制
Image(
    modifier = Modifier
        .padding(10.dp)
        .size(200.dp)
        .background(color = Color.Yellow)
        .clip(shape = CircleShape),
    painter = painterResource(id = R.drawable.logo),
    contentDescription = null,
    contentScale = ContentScale.Crop,
)

圆角

代码语言:javascript
复制
Image(
    modifier = Modifier
        .padding(10.dp)
        .size(200.dp)
        .background(color = Color.Yellow)
        .clip(shape = RoundedCornerShape(20.dp)),
    painter = painterResource(id = R.drawable.logo),
    contentDescription = null,
    contentScale = ContentScale.Crop,
)

背景剪裁

图片的背景是不会被剪裁的,我们可以在外面套一个Box做剪裁。

代码语言:javascript
复制
Box(
    modifier = Modifier
        .padding(10.dp)
        .size(200.dp)
        .clip(shape = RoundedCornerShape(20.dp)),
) {
    Image(
        painter = painterResource(id = R.drawable.logo),
        contentDescription = null,
        modifier = Modifier
            .background(color = Color.Yellow)
            .fillMaxSize(),
        contentScale = ContentScale.Crop
    )
}

加载本地图片

代码语言:javascript
复制
Image(
    painter = painterResource(R.drawable.my_image),
    contentDescription = "My Image"
)

图片角标

代码语言:javascript
复制
Image(
    painter = painterResource(id = R.drawable.logo),
    modifier = Modifier
        .padding(10.dp)
        .size(46.dp)
        .drawWithContent {
            drawContent()
            drawCircle(
                Color.Red,
                5.dp.toPx(),
                Offset(size.width - 1.dp.toPx(), 1.dp.toPx())
            )

        },
    contentDescription = "头像"
)

加载网络图片

添加依赖

代码语言:javascript
复制
implementation("io.coil-kt:coil-compose:2.6.0")

添加网络权限

代码语言:javascript
复制
<uses-permission android:name="android.permission.INTERNET" />

使用

代码语言:javascript
复制
@Composable
fun LoadWebImage(url:String){
    AsyncImage(
        model = url,
        contentDescription = null,
    )
}

调用

代码语言:javascript
复制
LoadWebImage(url = "https://www.psvmc.cn/head.jpg")

设置占位图

代码语言:javascript
复制
@Composable
fun LoadWebImage(url:String){
    AsyncImage(
        model = ImageRequest.Builder(LocalContext.current)
            .data(url)
            .crossfade(true)
            .build(),
        placeholder = painterResource(R.drawable.ic_launcher_foreground),
        contentDescription = stringResource(R.string.app_name),
        contentScale = ContentScale.Crop,
        modifier = Modifier.clip(CircleShape).size(60.dp)
    )
}

加载中动画

代码语言:javascript
复制
CircularProgressIndicator(modifier = Modifier.size(30.dp))

消息框

Toast

组件化

代码语言:javascript
复制
import android.widget.Toast
import androidx.compose.runtime.Composable
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch

@Composable
fun ShowToast(message: String) {
    val context = LocalContext.current

    // 启动一个协程来显示 Toast
    CoroutineScope(Dispatchers.Main).launch {
        Toast.makeText(context, message, Toast.LENGTH_SHORT).show()
    }
}

调用

代码语言:javascript
复制
var showToast by remember { mutableStateOf(false) }

if (showToast) {
    ShowToast("哈哈");
}

组件内方法

代码语言:javascript
复制
val context = LocalContext.current

// 显示 Toast 的函数
fun showToast(message: String) {
    CoroutineScope(Dispatchers.Main).launch {
        Toast.makeText(context, message, Toast.LENGTH_SHORT).show()
    }
}

Snackbar

基本示例

代码语言:javascript
复制
@Composable
fun SnackbarExample() {
    var snackbarVisible by remember { mutableStateOf(false) }

    Box {
        Button(onClick = { snackbarVisible = true }) {
            Text("显示 Snackbar")
        }
        if (snackbarVisible) {
            Snackbar(
                content = { Text(text = "文本") },
                action = {
                    Button(onClick = { snackbarVisible = false }) {
                        Text(text = "关闭")
                    }
                }
            )
        }
    }
}

使用snackbarHost

代码语言:javascript
复制
val scope = rememberCoroutineScope()
val snackbarHostState = remember { SnackbarHostState() }
Scaffold(
    snackbarHost = {
        SnackbarHost(hostState = snackbarHostState)
    },
    floatingActionButton = {

    }
) { contentPadding ->
    Box {
        Button(
            modifier = Modifier.padding(10.dp).width(100.dp).height(40.dp),
            shape = MaterialTheme.shapes.medium,
            onClick = {
                scope.launch {
                    snackbarHostState.showSnackbar("我是提示消息")
                }
            }
        ){
            Text(
                text = "点击",
                fontSize = 16.sp,
                color = Color.White
            )
        }
    }
}

对话框

代码语言:javascript
复制
Dialog(onDismissRequest = { /* 关闭对话框事件 */ }) {
    Surface(
        modifier = Modifier.size(300.dp),
        shape = RoundedCornerShape(16.dp),
        color = MaterialTheme.colorScheme.background
    ) {
        Text("文字")
    }
}

隐藏键盘

代码语言:javascript
复制
val keyboardController = LocalSoftwareKeyboardController.current

// 在需要隐藏键盘的地方调用这个函数
fun hideKeyboard() {
    keyboardController?.hide()
}

加载网页

代码语言:javascript
复制
@Composable
fun WebViewContainer(url: String) {
    AndroidView(factory = { context ->
        WebView(context).apply {
            layoutParams = ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT
            )
            webViewClient = WebViewClient()
            loadUrl(url)
        }
    })
}

视频播放器

代码语言:javascript
复制
import android.net.Uri
import androidx.compose.runtime.Composable
import androidx.compose.ui.viewinterop.AndroidView
import com.google.android.exoplayer2.ExoPlayer
import com.google.android.exoplayer2.SimpleExoPlayer
import com.google.android.exoplayer2.ui.PlayerView
import com.google.android.exoplayer2.source.ProgressiveMediaSource
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory
import com.google.android.exoplayer2.util.Util

@Composable
fun VideoPlayer(videoUrl: String) {
    val context = LocalContext.current
    val exoPlayer = SimpleExoPlayer.Builder(context).build().apply {
        val dataSourceFactory = DefaultDataSourceFactory(
            context,
            Util.getUserAgent(context, context.getString(R.string.app_name))
        )
        val videoSource = ProgressiveMediaSource.Factory(dataSourceFactory)
            .createMediaSource(Uri.parse(videoUrl))
        prepare(videoSource)
    }
    AndroidView(factory = { ctx ->
        PlayerView(ctx).apply {
            player = exoPlayer
            useController = true
        }
    }, update = { playerView ->
        playerView.player = exoPlayer
    })
}

实战-登录页面

代码语言:javascript
复制
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun LoginScreen(onLoginClicked: (String, String) -> Unit) {
    var username by remember { mutableStateOf("") }
    var password by remember { mutableStateOf("") }
    Log.i("LoginScreen", "Username: $username, Password: $password")
    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(16.dp),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center
    ) {
        OutlinedTextField(
            value = username,
            onValueChange = { username = it },
            label = { Text("用户名") },
            modifier = Modifier.fillMaxWidth()
        )
        Spacer(modifier = Modifier.height(16.dp))
        OutlinedTextField(
            value = password,
            onValueChange = { password = it },
            label = { Text("密码") },
            visualTransformation = PasswordVisualTransformation(),
            modifier = Modifier.fillMaxWidth()
        )
        Spacer(modifier = Modifier.height(16.dp))
        Button(
            onClick = {
                Log.i("登录点击", "Username: $username, Password: $password")
                onLoginClicked(username, password)
            },
            modifier = Modifier.fillMaxWidth()
        ) {
            Text(text = "登录")
        }
    }
}

调用

代码语言:javascript
复制
LoginScreen { name, pwd ->
   Log.i("LoginScreen", "Username: $name, Password: $pwd")
};

组件提取

因为Compose组件本质都是方法,所以可以使用提取方法来提取组件

快捷键:Ctrl+Alt+M

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-03-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 占位
  • 分割线
  • 文本
  • 按钮
    • 基本使用
      • 自定义按钮
      • 单选按钮
      • Switch
      • 文本输入
        • BasicTextField
          • TextField
            • OutlinedTextField
            • 图片
              • 适配模式
                • 着色
                  • 圆角
                    • 圆形
                    • 圆角
                    • 背景剪裁
                  • 加载本地图片
                    • 图片角标
                      • 加载网络图片
                      • 加载中动画
                      • 消息框
                        • Toast
                          • 组件化
                          • 组件内方法
                        • Snackbar
                          • 基本示例
                          • 使用snackbarHost
                      • 对话框
                      • 隐藏键盘
                      • 加载网页
                      • 视频播放器
                      • 实战-登录页面
                      • 组件提取
                      领券
                      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档