compose OutlinedTextField实现hint、与自定义hint效果

类似textView中的hint属性功能(我这边所使用的是material3的依赖库)

库:androidx.compose.material3

1.在material中在Modifier中实现placeholder函数并实现Text(value=str)来实现。

Modifier
.placeholder {
                Text(
                    text = "in hint"
                )
 }

2.在material3中已经封装到OutlinedTextField里面作为@Compose参数了,以下是使用方法

@Composable
fun TextField(str:String) {
    OutlinedTextField(
        value = str,
        onValueChange = {  },
        placeholder = {
            Text(
                text =stringResource(R.string.login_input_hint_user_pwd),
                color = Color.Gray,
                fontSize = labelTextSize
            )
        },
    )
}

3.左边增加图标,这里两个函数都可以实现,leadingIcon和prefix,这两个函数所增加的icon都是在内容的前面。但两个函数有所区别,我所理解的区别在于图标所处的位置。

leadingIcon,与内容有一定的pading效果

leadingIcon = {
                    Image(imageVector = Icons.Default.Phone,
                        contentDescription = "IS PHOME")
                }

prefix,与内容中间没有pading效果。

需要使用到OutlinedTextField中的prefix函数。

prefix = {
                    Image(imageVector = Icons.Default.Phone,
                        contentDescription = "IS PHOME")
                },

4.右边增加图标,需要使用到trailingIcon此函数实现

trailingIcon = {
                    Image(imageVector = Icons.Default.Phone,
                        contentDescription = "IS PHOME")
                }

注意:placeholder函数有个问题,当实现hint时,当获取输入焦点时才会显示,否则是不显示。

这里需要注意下。因为我在实现过程中未获取焦点时就不显示,才会自定义实现hint效果。

以下是效果:

当然还有自定义实现hint效果,请看代码:

新增了4个参数:isHint,hint,hintPadding,contentAlignment等属性。

isHint是否需要显示,默认为false。以内容是否为空作为条件,当为空时才会显示hint内容;

hint是@Compose组合函数,按照自己需要添加;

hintPadding,hint与文本之间的间距调整;

contentAlignment,上下左右的居中属性;可根据需要自行调整

/**
 * 自定义输入框,增加hint 属性。hint为 @Compose()组合函数
 * @param value String 内容
 * @param onValueChange Function1<String, Unit>
 * @param modifier Modifier
 * @param isHint Boolean 需要根据输入框内容判断是否显示hint [value.isNullOrBlank()]  true则显示,false则不显示
 * @param hint [@androidx.compose.runtime.Composable] Function0<Unit>
 * @param hintPadding PaddingValues 内容区域与icon或者左边[hint]的padding间距
 * @param contentAlignment Alignment 内容区域的居中
 * @param enabled Boolean
 * @param readOnly Boolean
 * @param textStyle TextStyle
 * @param label [@androidx.compose.runtime.Composable] Function0<Unit>?
 * @param placeholder [@androidx.compose.runtime.Composable] Function0<Unit>?
 * @param leadingIcon [@androidx.compose.runtime.Composable] Function0<Unit>?
 * @param trailingIcon [@androidx.compose.runtime.Composable] Function0<Unit>?
 * @param prefix [@androidx.compose.runtime.Composable] Function0<Unit>?
 * @param suffix [@androidx.compose.runtime.Composable] Function0<Unit>?
 * @param supportingText [@androidx.compose.runtime.Composable] Function0<Unit>?
 * @param isError Boolean
 * @param visualTransformation VisualTransformation
 * @param keyboardOptions KeyboardOptions
 * @param keyboardActions KeyboardActions
 * @param singleLine Boolean
 * @param maxLines Int
 * @param minLines Int
 * @param interactionSource MutableInteractionSource
 * @param shape Shape
 * @param colors TextFieldColors
 */
@Composable
fun CustomOutlinedTextField(
	value: String,
	onValueChange: (String) -> Unit,
	modifier: Modifier = Modifier,
	isHint:Boolean = false,
	hint: @Composable () -> Unit = {},
	hintPadding: PaddingValues = PaddingValues(20.dp, 0.dp,0.dp, 0.dp),
	contentAlignment: Alignment = Alignment.CenterStart,
	enabled: Boolean = true,
	readOnly: Boolean = false,
	textStyle: TextStyle = LocalTextStyle.current,
	label: @Composable (() -> Unit)? = null,
	placeholder: @Composable (() -> Unit)? = null,
	leadingIcon: @Composable (() -> Unit)? = null,
	trailingIcon: @Composable (() -> Unit)? = null,
	prefix: @Composable (() -> Unit)? = null,
	suffix: @Composable (() -> Unit)? = null,
	supportingText: @Composable (() -> Unit)? = null,
	isError: Boolean = false,
	visualTransformation: VisualTransformation = VisualTransformation.None,
	keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
	keyboardActions: KeyboardActions = KeyboardActions.Default,
	singleLine: Boolean = false,
	maxLines: Int = if (singleLine) 1 else Int.MAX_VALUE,
	minLines: Int = 1,
	interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
	shape: Shape = OutlinedTextFieldDefaults.shape,
	colors: TextFieldColors = OutlinedTextFieldDefaults.colors()
) {
	BasicTextField(
		modifier = modifier,
		value = value,
		onValueChange = onValueChange,
		decorationBox = {
			Box(modifier = modifier,contentAlignment = contentAlignment) {
				// 添加自定义的提示
				if (isHint) {
					Box(modifier = modifier.padding(hintPadding)
						,contentAlignment = contentAlignment){
						hint()
					}
				}
				// 原生的输入框
				OutlinedTextField(
					value,
					onValueChange = onValueChange,
					modifier,
					enabled,
					readOnly,
					textStyle,
					label,
					placeholder,
					leadingIcon,
					trailingIcon,
					prefix,
					suffix,
					supportingText,
					isError,
					visualTransformation,
					keyboardOptions,
					keyboardActions,
					singleLine,
					maxLines,
					minLines,
					interactionSource,
					shape,
					colors
				)
			}
		}
	)
}

使用方法:

CustomOutlinedTextField(
                value = password,
                onValueChange = { password = it },
                hintPadding = PaddingValues(40.dp, 0.dp, 0.dp, 0.dp),
                isHint = password.isNullOrBlank(),
                hint = {
                    Text(
                        text =stringResource(R.string.login_input_hint_user_pwd),
                        color = Color.Gray,
                        fontSize = labelTextSize
                    )
                },
                placeholder = {
                    Text(
                        text =stringResource(R.string.login_input_hint_user_pwd),
                        color = Color.Gray,
                        fontSize = labelTextSize
                    )
                },
                prefix = {
                    Image(imageVector = Icons.Default.Lock,
                        contentDescription = "IS LOCK")
                },
                textStyle = outlinedTextFieldTextSize,
                visualTransformation = PasswordVisualTransformation(),
                modifier = Modifier
                    .fillMaxWidth(),
                colors = getTextFieldColors(),
                singleLine = true,
            )

接下来请看完整代码:

private val spacedColumnVerticalArrangement = Arrangement.spacedBy(16.dp)
private val boxPadding = 16.dp
private val imageSize = 100.dp
private val textFontSize = 24.sp
private val outlinedTextFieldTextSize = TextStyle(fontStyle = FontStyle(18))
private val labelTextSize = TextUnit(18f, TextUnitType.Sp)
private val shapeRoundedButton = RoundedCornerShape(8.dp)
private const val initialTime = 10
//这个是边框的颜色
@Composable
fun getTextFieldColors():TextFieldColors {
   return TextFieldDefaults.colors(
       focusedTextColor = Color.Black,
       unfocusedTextColor = Color.Black,
       focusedIndicatorColor = Color.Red,
       unfocusedIndicatorColor = Color.Red,
       focusedContainerColor = Color.Transparent,
       unfocusedContainerColor = Color.Transparent
   )
}

@Composable
fun LoginPage(modifier: Modifier, activity: ComponentActivity) {
    //输入法管理类
    val keyboardController = LocalSoftwareKeyboardController.current
    var username by remember { mutableStateOf("") }
    var password by remember { mutableStateOf("") }
    var isToLogin by remember { mutableStateOf(false) }
    
    Box(
        modifier = Modifier
            .fillMaxSize()
            .background(Color.White)
    ) {
        Column(
            modifier = modifier
                .align(Alignment.Center)
                .padding(boxPadding),
            horizontalAlignment = Alignment.CenterHorizontally,
            verticalArrangement = spacedColumnVerticalArrangement
        ) {
            Image(
                painter = painterResource(id = androidx.core.R.drawable.ic_call_answer),
                contentDescription = "App Logo",
                modifier = Modifier.size(imageSize)
            )

            Text(
                text = "Welcome Back!",
                fontSize = textFontSize,
                fontWeight = FontWeight.Bold,
                color = Color.Black
            )
            
            OutlinedTextField(
                value = username,
                modifier = Modifier.fillMaxWidth(),
                onValueChange = { username = it },
                placeholder = {
                    Text(
                        text = stringResource(R.string.login_input_hint_user_name),
                        color = Color.Gray,
                        fontSize = labelTextSize
                    )
                },
                //左边图标,与文本之间有padding
//                leadingIcon = {
//                    Image(imageVector = Icons.Default.Phone,
//                        contentDescription = "IS PHOME")
//                },
                //左边图标,与文本之间无padding效果
                suffix = {
                    Image(imageVector = Icons.Default.Phone,
                        contentDescription = "IS PHOME")
                },
                //右边图标
//                trailingIcon = {
//                    Image(imageVector = Icons.Default.Phone,
//                        contentDescription = "IS PHOME")
//                },
                textStyle = outlinedTextFieldTextSize,
                singleLine = true,
                colors = getTextFieldColors(),
            )
            
            CustomOutlinedTextField(
                value = password,
                onValueChange = { password = it },
                hintPadding = PaddingValues(40.dp, 0.dp, 0.dp, 0.dp),
                isHint = password.isNullOrBlank(),
                hint = {
                    Text(
                        text =stringResource(R.string.login_input_hint_user_pwd),
                        color = Color.Gray,
                        fontSize = labelTextSize
                    )
                },
                placeholder = {
                    Text(
                        text =stringResource(R.string.login_input_hint_user_pwd),
                        color = Color.Gray,
                        fontSize = labelTextSize
                    )
                },
                prefix = {
                    Image(imageVector = Icons.Default.Lock,
                        contentDescription = "IS LOCK")
                },
                textStyle = outlinedTextFieldTextSize,
                visualTransformation = PasswordVisualTransformation(),
                modifier = Modifier
                    .fillMaxWidth(),
                colors = getTextFieldColors(),
                singleLine = true,
            )
            Spacer(modifier = Modifier.height(60.dp))
            Button(
                onClick = {
                    isToLogin = true
                },
                modifier = Modifier
                    .fillMaxWidth()
                    .height(50.dp),
                shape = shapeRoundedButton
            ) {
                Text(text = "Login", fontSize = labelTextSize, color = Color.White)
            }
        }

        if (isToLogin) {
            keyboardController?.hide()
            Box(
                modifier = Modifier
                    .fillMaxSize()
                    .background(transparentBackgroundModifier)
            ) {
                username = ""
                password = ""
            }
        }

    }
}


 

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Jetpack Compose 是一种用于构建 Android UI 的现代工具包。要实现吸顶效果,可以使用 Jetpack Compose 的 ConstraintLayout 组件。 首先,在你的布局文件中引入 ConstraintLayout 组件。然后,在需要实现吸顶效果的视图组件前方放置一个占位符组件,作为吸顶效果的起点。 接下来,使用 ConstraintLayout 的 createModifier 函数来创建一个修饰符(Modifier),并将其应用到需要实现吸顶效果的视图组件上。在修饰符中,通过调用该组件的位置限制函数来设置视图组件的约束条件。 例如,使用 Modifier.offset() 函数将吸顶组件固定在布局的顶部: ```kotlin val modifier = Modifier.constrainAs(view) { top.linkTo(parent.top) } ``` 或者,使用 Modifier.padding() 函数来设置视图组件距离父布局顶部的间距: ```kotlin val modifier = Modifier.padding(top = offset) ``` 其中,offset 可以是一个动态的数值,用于实现吸顶效果的变化。你可以根据滚动位置来调整 offset 的值,实现吸顶视图随滚动而变化的效果。 最后,将该修饰符应用到你的视图组件上: ```kotlin Box( modifier = Modifier .fillMaxSize() .wrapContentSize() .offset { IntOffset(0, offset) } ) { // 吸顶视图组件 } ``` 这样,你就可以实现吸顶效果了。通过调整约束条件或距离顶部的间距,你可以自定义吸顶效果的具体表现。注意,吸顶效果通常与滚动视图组件(如 ListView 或 ScrollView)结合使用,以便根据滚动位置来动态调整吸顶视图的位置和显示状态。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值