带有图标和占位符文本的文本字段

问题描述 投票:0回答:1

有没有办法让文本字段在图标旁边显示占位符文本,如下图所示。

我尝试通过设置填充来做到这一点,但这仅适用于实际文本,不适用于占位符文本。

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
    }
}

如果文本字段获得焦点,看起来不错。如果焦点未对准,文本会与图标重叠(请参阅密码字段):

enter image description here

但我希望它看起来像这样:

enter image description here

qt qml qtquickcontrols2
1个回答
0
投票

您想要实现的目标记录在 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
    }
}

渲染如下(分别为无焦点和有焦点):
User field without focus User field with focus


奖金

现在,如果您使用 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
    }
}

QML 原生渲染的另一个文本字段旁边的渲染是: Rounded Material text field

© www.soinside.com 2019 - 2024. All rights reserved.