Compose-自定义输入框(BasicTextField)


前言

Compose 中的 TextField()material 风格的输入框, 只得把 BasicTextField 自定义一下。
BasicTextField 的参数这里就不介绍了, 网上介绍的文章已经不少了.

先上图:
在这里插入图片描述
自定义的内容有:

  1. 左侧的小图标
  2. 右侧的删除按钮
  3. hint 空字符时的提示

一、上代码

/**
 * @param hint: 空字符时的提示
 * @param startIcon: 左侧图标;  -1 则不显示
 * @param iconSpacing: 左侧图标与文字的距离; 相当于: drawablePadding
 */
@Composable
fun CustomEdit(
  text: String = "",
  onValueChange: (String) -> Unit,
  modifier: Modifier,
  hint: String = "请输入",
  @DrawableRes startIcon: Int = -1,
  iconSpacing: Dp = 6.dp,

  enabled: Boolean = true,
  readOnly: Boolean = false,
  textStyle: TextStyle = TextStyle.Default,
  keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
  keyboardActions: KeyboardActions = KeyboardActions.Default,
  visualTransformation: VisualTransformation = VisualTransformation.None,
  cursorBrush: Brush = SolidColor(MaterialTheme.colors.primary)
) {
  // 焦点, 用于控制是否显示 右侧叉号
  var hasFocus by remember { mutableStateOf(false) }

  BasicTextField(
    value = text,
    onValueChange = onValueChange,
    modifier = modifier.onFocusChanged { hasFocus = it.isFocused },
    singleLine = true,
    enabled = enabled,
    readOnly = readOnly,
    textStyle = textStyle,
    keyboardOptions = keyboardOptions,
    keyboardActions = keyboardActions,
    visualTransformation = visualTransformation,
    cursorBrush = cursorBrush,
    decorationBox = @Composable { innerTextField ->
      Row(
        modifier = Modifier.fillMaxWidth(),
        verticalAlignment = Alignment.CenterVertically
      ) {
        // -1 不显示 左侧Icon
        if(startIcon != -1){
          Image(painter = painterResource(id = startIcon), contentDescription = null)
          Spacer(modifier = Modifier.width(iconSpacing))
        }

        Box(modifier = Modifier.weight(1f)){
          // 当空字符时, 显示hint
          if(text.isEmpty())
            Text(text = hint, color = GrayAa, style = textStyle)

          // 原本输入框的内容
          innerTextField()
        }

        // 存在焦点 且 有输入内容时. 显示叉号
        if(hasFocus && text.isNotEmpty()) {
          Image(imageVector = Icons.Filled.Clear, // 清除图标
            contentDescription = null,
            // 点击就清空text
            modifier = Modifier.clickable { onValueChange.invoke("") })
        }
      }
    }
  )
}

二、使用

// vm : ViewModel; 
// 手机号输入框
CustomEdit(
  text = vm.phone,
  onValueChange = {
    vm.phone = it
  },
  modifier = Modifier
    .fillMaxWidth()
    .padding(start = 16.dp, top = 20.dp, end = 16.dp)
    .height(50.dp)
    .background(GrayE5, shape = MaterialTheme.shapes.medium)
    .padding(horizontal = 16.dp),
  hint = "请输入手机号",
  startIcon = R.drawable.ic_login_phone,
  iconSpacing = 16.dp,
  textStyle = Typography.body1,
  // keyboardType -> 半个 inputType; 这里是 Phone
  keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Phone),
)

// code 输入框
CustomEdit(
  text = vm.code,
  onValueChange = {
    vm.code = it
  },
  modifier = Modifier
    .fillMaxSize()
    .background(GrayE5, shape = MaterialTheme.shapes.medium)
    .padding(horizontal = 16.dp),
  hint = "请输入验证码",
  startIcon = R.drawable.ic_login_pwd,
  iconSpacing = 16.dp,
  textStyle = Typography.body1,
  keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
)

三、只有hint的 BasicTextField

1. 自定义CustomEditHint

/**
 * 只增加 hint;  适合多行输入框, 没有前后Icon的小输入框; 背景 尺寸等 定义在modifier中;
 * @param hint: 空字符时的提示
 */
@Composable
fun CustomEditHint(
  text: String = "",
  onValueChange: (String) -> Unit,
  modifier: Modifier,
  hint: String = "请输入",

  enabled: Boolean = true,
  readOnly: Boolean = false,
  singleLine: Boolean = false,
  textStyle: TextStyle = TextStyle.Default,
  keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
  keyboardActions: KeyboardActions = KeyboardActions.Default,
  visualTransformation: VisualTransformation = VisualTransformation.None,
  cursorBrush: Brush = SolidColor(MaterialTheme.colors.primary)
) {
  // 焦点, 用于控制是否显示 右侧叉号
  BasicTextField(
    value = text,
    onValueChange = onValueChange,
    modifier = modifier,
    singleLine = singleLine,
    enabled = enabled,
    readOnly = readOnly,
    textStyle = textStyle,
    keyboardOptions = keyboardOptions,
    keyboardActions = keyboardActions,
    visualTransformation = visualTransformation,
    cursorBrush = cursorBrush,
    decorationBox = @Composable { innerTextField ->
      if(text.isEmpty())
        Text(text = hint, color = GrayAa, style = textStyle)
      innerTextField()
    }
  )
}

2.Preview

@Preview(showBackground = true)
@Composable
fun TextFieldViewPreview() {
  val scrollState = rememberScrollState()
  Column(
    modifier = Modifier.verticalScroll(scrollState)
  ) {
    var text by remember { mutableStateOf("") }
	// 带前icon 及 后清除icon 的输入框
    CustomEdit(
      text = text,
      onValueChange = {
        text = it.trim()
      },
      modifier = Modifier
        .fillMaxWidth()
        .padding(start = 16.dp, top = 20.dp, end = 16.dp)
        .height(50.dp)
        .background(GrayE5, shape = MaterialTheme.shapes.medium)
        .padding(horizontal = 16.dp),
      hint = "请输入手机号",
      iconSpacing = 16.dp,
      textStyle = TextDark16,
      keyboardOptions = KeyboardOptions(imeAction = ImeAction.Search),
      keyboardActions = KeyboardActions(onSearch = {
        ComApplication.INSTANCES.toast("搜索:$text")
      }),
    )

	// 多行输入框
    CustomEditHint(
      text = text,
      onValueChange = {
        text = it.trim()
      },
      modifier = Modifier
        .fillMaxWidth()
        .padding(top = 16.dp)
        .height(200.dp)
        .background(GrayE5)
        .padding(horizontal = 14.dp, vertical = 12.dp),
      hint = "请输入详情",
    )
	
	// 小输入框
    var text2 by remember { mutableStateOf("") }
    Box(
      modifier = Modifier
        .fillMaxWidth()
        .background(Color.White)
        .padding(14.dp)
    ){
      Text(text = "联系方式", style = TextDarkBlod14)

      CustomEditHint(
        text = text2,
        onValueChange = {
          text2 = it.trim().let { str ->
            // maxLength = 15
            if(str.length > 15){
              str.substring(0, 15)
            } else {
              str
            }
          }
        },
        modifier = Modifier
          .align(Alignment.CenterEnd)
          .defaultMinSize(100.dp, 14.dp),
        hint = "手机或邮箱都可以哦",
        singleLine = true,
        textStyle = TextStyle.Default.copy(textAlign = TextAlign.End)
      )
    }
  }
}

总结

没有总结!

上一篇: 记一次自定义View:滑动标尺
下一篇: Compose-navigation: 问题汇总

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值