有没有办法让文本字段在图标旁边显示占位符文本,如下图所示。
我尝试通过设置填充来做到这一点,但这仅适用于实际文本,不适用于占位符文本。
import QtQuick
import QtQuick.Controls
TextField {
property alias iconSource: image.source
selectByMouse: true
leftPadding: iconSource.toString() ? 32 : 16
Image {
id: image
anchors.verticalCenter: parent.verticalCenter
width: parent.height * 0.5
height: width
sourceSize.width: width
sourceSize.height: height
}
}
如果文本字段获得焦点,看起来不错。如果焦点未对准,文本会与图标重叠(请参阅密码字段):
但我希望它看起来像这样:
您想要实现的目标记录在 Customizing Qt Quick Controls 帮助页面上:您需要将
TextField
的背景属性设置为某个矩形并绑定该矩形的 radius
。
下面是一个演示。我假设您在 qtquickcontrols2.conf 文件中定义了应用程序颜色,如下所示:
[Controls]
Style=Universal
[Universal]
Accent="#0267ff"
[Material]
Theme=Light
Accent=Blue
Primary=Gray
你的控制权变成了这样的东西:
TextField {
id: textField
verticalAlignment: Text.AlignVCenter
leftPadding: image.x + image.width + 2
placeholderText: qsTr("User name")
background: Rectangle {
anchors.fill: parent
border.color: textField.activeFocus ? Material.accent : Material.primary
border.width: 1
radius: textField.height / 2
}
Image {
id: image
x: (textField.height - width) / 2 /* Set the center of the image to be the same as the center of the rounded border */
y: 5
width: textField.height - 10
height: textField.height - 10
source: "../account_circle.svg"
fillMode: Image.PreserveAspectFit
}
}
现在,如果您使用 Material 样式尝试了上述代码,您一定已经注意到,当文本字段具有活动焦点时,占位符会移动到顶部边框。显然,这并不理想,因为边界不会让路。
由于插图、边距和动画,这需要更多的工作;做到这一点的一种方法(有一点硬编码的东西,我留给你解决,因为这不是问题的主题)是有一个边框:
RoundedBorderShape.qml
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Shapes 1.8
Shape {
property int placeholderLeft: 0
property int placeholderLength: 0
property color fill: "transparent"
property real pathExtraLength: parent.activeFocus ? 0.0 : placeholderLength / 2
anchors.fill: parent
anchors.bottomMargin: -parent.topInset
/* Add layer properties for antialiasing */
layer {
enabled: true
samples: 4
}
ShapePath {
id: shapePath
fillColor: fill
strokeColor: parent.activeFocus ? Material.accent : Material.primary
strokeWidth: parent.activeFocus ? 1.5 : 0.75
startX: placeholderLeft + placeholderLength - pathExtraLength
startY: parent.topInset + 1
Behavior on startX {
NumberAnimation {
duration: 250
}
}
PathLine {
x: width - (height - parent.topInset) / 2 + 1
y: parent.topInset + 1
}
PathArc {
x: width - (height - parent.topInset) / 2 + 1
y: height - parent.topInset - 2
radiusY: height / 2 - parent.topInset - 2
radiusX: radiusY
}
PathLine {
x: (height - parent.topInset) / 2 - 1
y: height - parent.topInset - 2
}
PathArc {
x: (height - parent.topInset) / 2 - 1
y: parent.topInset + 1
radiusY: height / 2 - parent.topInset - 2
radiusX: radiusY
}
PathLine {
x: placeholderLeft + pathExtraLength
y: parent.topInset + 1
Behavior on x {
NumberAnimation {
duration: 250
}
}
}
}
}
文本字段变为:
TextField {
id: textField
x: 406
y: 258
width: 250
height: 60
topInset: 5
bottomInset: -5
verticalAlignment: Text.AlignVCenter
leftPadding: image.x + image.width + 2
placeholderText: qsTr("User name")
background: RoundedBorderShape {
placeholderLeft: 0.8 * textField.height
placeholderLength: 75 /* Hardcoded, to be replaced by actual text length in pixels */
}
Image {
id: image
x: (textField.height - width) / 2 /* Set the center of the image to be the same as the center of the rounded border */
y: 5 + textField.topInset
width: height
height: textField.height - textField.topInset - 10
source: "../account_circle.svg"
fillMode: Image.PreserveAspectFit
}
}