textField占位图片

一、我们通常在设计登录界面时会用到UITextField,如下图所示:

通常想实现下面几点:

1、左边显示图片

2、textField中添加默认的占位符(提示文字),并且希望占位符和左边图片有一点的距离,或者让占位符居中,

3、点击textField输入时光标的位置应该紧在占位符左侧,并紧挨着占位符

最终实现效果如下图所示:

\

二、左边显示图片很简单下面几行代码搞定(右边显示图片同理):

UIImageView *passwordImage = [[UIImageView alloc] initWithImage:[UIImageimageNamed:@"passwordIcon"]];
    password.leftView = passwordImage;

    password.leftViewMode = UITextFieldViewModeAlways;

友情提示:上下两个图片的宽度要保持一致,不然会导致占位符的左边无法对其!

 

三、而设置占位符的位置和编辑状态时光标的位置试了很多方法感觉都不好使,最终找到一个方法,自定义一个basicTextField继承自UITextField;然后可以重写下面的几个方法:

- (CGRect)borderRectForBounds:(CGRect)bounds;
- (CGRect)textRectForBounds:(CGRect)bounds;
- (CGRect)placeholderRectForBounds:(CGRect)bounds;
- (CGRect)editingRectForBounds:(CGRect)bounds;
- (CGRect)clearButtonRectForBounds:(CGRect)bounds;
- (CGRect)leftViewRectForBounds:(CGRect)bounds;

- (CGRect)rightViewRectForBounds:(CGRect)bounds;

 

二、下面是具体的代码实现:

#import "basicTextField.h"


@implementation basicTextField

- (CGRect)leftViewRectForBounds:(CGRect)bounds{
    CGRect iconRect = [super leftViewRectForBounds:bounds];
    iconRect.origin.x += 10;
    return iconRect;
}

 

//  重写占位符的x值

- (CGRect)placeholderRectForBounds:(CGRect)bounds{
    CGRect placeholderRect = [super placeholderRectForBounds:bounds];
    placeholderRect.origin.x += 1;
    return placeholderRect;

}


//  重写文字输入时的X值
- (CGRect)editingRectForBounds:(CGRect)bounds{
    CGRect editingRect = [super editingRectForBounds:bounds];
    editingRect.origin.x += 20;
    return editingRect;
}

//  重写文字显示时的X值
- (CGRect)textRectForBounds:(CGRect)bounds{
    CGRect textRect = [super editingRectForBounds:bounds];
    textRect.origin.x += 20;
    return textRect;
}

@end

 

四、这里有一个坑:就是当你同时重写这三个方法时,同时设置他们X的偏移量时会发现运行结果如下图。

//  重写占位符的X值

- (CGRect)placeholderRectForBounds:(CGRect)bounds{

    CGRect placeholderRect = [super placeholderRectForBounds:bounds];

    placeholderRect.origin.x += 80;

    return placeholderRect;

}

\

看上图可以发现当点击textField使其处于输入状态时,光标和文字中间有间隔;这个间隔其实是占位符的偏移量80,因为我们设置了输入状态时光标的偏移量为20,占位符是80。而光标的偏移量是根据leftView的算的,占位符的偏移量是根据光标的位置算的。所以设置占位符偏移量为1是最合适的。至于其它的方法根据实际需要重写即可。

转载于:https://my.oschina.net/kaqijiang/blog/693294

<think>好的,用户现在需要实现一个QML的TextField,要求左侧和右侧都有图标,并且中间的输入文字靠近左侧图标。我之前已经回答过关于使用Fontello图标的问题,现在需要结合之前的经验来解决这个布局问题。 首先,用户可能想要类似常见的输入框设计,比如搜索框左侧有个放大镜图标,右侧可能有清除按钮,输入的文字从左侧图标旁边开始。这时候需要考虑如何将图标嵌入到TextField中,并控制文字的位置。 QML中的TextField本身并没有直接支持左右图标的属性,所以需要自定义。可能需要使用Item或者布局组件(如RowLayout)来组合TextField和其他元素。不过,直接修改TextField的内部结构可能比较复杂,所以应该考虑在外部包裹布局,将图标和输入框组合在一起。 接下来,用户提到中间的文字要靠近左侧图标。这意味着需要调整TextField的文本对齐方式,或者通过边距和填充来移动文本的位置。可能需要在TextField的leftPadding属性上做调整,留出左侧图标的空间,这样文字就会从左侧图标右侧开始显示。同时,右侧图标也需要调整位置,可能需要使用anchors或者Layout.align属性来定位。 需要考虑图标的点击事件,比如右侧图标可能是清除按钮,需要处理点击后的逻辑,如清空输入内容。左侧图标可能只是装饰性的,但如果有功能也需要处理。 另外,之前用户提到使用Fontello图标,所以可能需要将图标作为Text组件来显示,使用字体图标的方式。这样图标可以方便地调整颜色和大小,并且不需要导入图片资源。 在布局方面,可能需要使用Row或RowLayout来水平排列左侧图标、TextField和右侧图标。设置spacing属性来调整它们之间的间距。同时,需要确保TextField能够扩展填充剩余空间,所以可能需要设置Layout.fillWidth: true。 关于文字的对齐,TextField的horizontalAlignment属性可以设置为Text.AlignLeft,确保文字左对齐。同时,通过调整leftPadding,让文字从左侧图标之后开始显示,这样看起来更靠近左侧图标。 还需要考虑整体的样式,比如边框、背景颜色等,可能需要为整个组合组件添加Rectangle作为背景,使其看起来像一个整体的输入框。 测试时需要注意不同屏幕尺寸下的表现,确保图标和文字的位置正确,不会出现重叠或错位的情况。同时,考虑用户交互,如点击右侧图标时的反馈效果。 可能遇到的问题包括:图标无法正确显示,文字位置没有调整,布局在窗口缩放时变形等。需要逐一检查各个属性的设置是否正确,尤其是padding和anchors部分。 最后,提供一个可复用的组件,方便在项目中多次使用,可以通过创建一个自定义的QML组件,封装左侧图标、TextField和右侧图标,暴露必要的属性如图标编码、占位符文本、事件处理等。</think>以下是实现带左右图标且文字左对齐的QML输入框的详细解决方案: ### 自定义输入框实现(带完整交互逻辑) ```qml // TextFieldWithIcons.qml Item { id: root width: 300 height: 48 // 暴露接口 property alias text: inputField.text property string leftIcon: "\uE800" // 左侧图标Unicode property string rightIcon: "\uE801" // 右侧图标Unicode property string placeholder: "请输入..." property int iconSize: 24 property color iconColor: "#666" // 背景样式 Rectangle { anchors.fill: parent radius: 8 border.color: inputField.activeFocus ? "#4CAF50" : "#E0E0E0" border.width: 2 } Row { anchors.fill: parent spacing: 8 leftPadding: 12 // 左侧图标 Text { id: leftIcon anchors.verticalCenter: parent.verticalCenter text: root.leftIcon font { family: "fontello" // 确保已加载字体 pixelSize: root.iconSize } color: root.iconColor } // 输入区域 TextField { id: inputField width: parent.width - leftIcon.width - rightIconArea.width - 24 anchors.verticalCenter: parent.verticalCenter placeholderText: root.placeholder verticalAlignment: TextInput.AlignVCenter // 文本对齐控制 leftPadding: 8 // 增加左侧间隔 rightPadding: 8 // 增加右侧间隔 // 文字样式 font.pixelSize: 16 color: "#333" selectionColor: "#80CBC4" selectedTextColor: "#FFF" // 输入区域扩展样式 background: Rectangle { color: "transparent" } } // 右侧图标容器 Item { id: rightIconArea width: 32 height: parent.height // 右侧图标 Text { id: rightIcon anchors.centerIn: parent text: root.rightIcon font { family: "fontello" pixelSize: root.iconSize } color: root.iconColor visible: inputField.text.length > 0 // 有输入时显示 // 点击事件处理 MouseArea { anchors.fill: parent onClicked: inputField.clear() } } } } } ``` ### 实现原理说明 1. **布局架构** - 使用`Row`布局容器水平排列三个部分: - 左侧图标(固定宽度) - 输入区域(自动扩展) - 右侧图标容器(固定宽度) 2. **动态间距计算** - 输入框宽度计算:`parent.width - leftIcon.width - rightIconArea.width - 24` - 自动减去图标占位空间和边距 3. **文字对齐控制** - 通过`leftPadding`增加左侧间隔 - 设置`verticalAlignment: TextInput.AlignVCenter`垂直居中 - 移除默认背景实现透明效果 ### 使用示例 ```qml TextFieldWithIcons { width: 280 height: 48 leftIcon: "\uE802" // 搜索图标 rightIcon: "\uE806" // 清除图标 placeholder: "搜索商品..." iconColor: "#9E9E9E" } ``` ### 高级功能扩展 1. **图标点击反馈动画** ```qml // 在右侧图标区域添加: SequentialAnimation { id: clickAnim PropertyAnimation { target: rightIcon property: "scale" from: 1.0 to: 0.8 duration: 80 } PropertyAnimation { target: rightIcon property: "scale" from: 0.8 to: 1.0 duration: 120 } } MouseArea { // ... onClicked: { clickAnim.start() inputField.clear() } } ``` 2. **输入验证指示** ```qml // 在根Item中添加: property bool isValid: true // 修改背景矩形: Rectangle { // ... border.color: { if (!isValid) return "#FF5252" return inputField.activeFocus ? "#4CAF50" : "#E0E0E0" } } ``` ### 性能优化建议 1. **字体预加载**(在main.qml中): ```qml FontLoader { source: "qrc:/fonts/fontello.ttf" onStatusChanged: if (status == FontLoader.Ready) console.log("图标字体加载完成") } ``` 2. **重用组件实例** ```qml // 创建实例池 Component { id: textFieldPool TextFieldWithIcons {} } // 动态创建 function createInputField(parentItem) { return textFieldPool.createObject(parentItem, {"width": 300}) } ``` ### 常见问题排查 1. **图标显示异常** - 验证字体文件是否包含对应Unicode - 检查`font.family`是否与字体文件定义名称一致 - 确认字体加载时机(推荐预加载) 2. **布局错位** - 检查父容器的尺寸约束 - 验证`spacing`和`padding`的计算逻辑 - 使用`LayoutMirroring.enabled`处理RTL布局 3. **输入区域溢出** - 添加`clip: true`属性 - 设置`maximumLength`限制输入长度 - 使用`validator`进行格式过滤 该方案实现了: - 左右图标精确定位 - 动态宽度适配 - 点击交互反馈 - 样式可定制化 - 输入验证集成 可根据具体需求扩展更多功能(如密码可见切换、输入格式限制等)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值