is there a way to get a textfield to display the placeholder text next to an icon like in the picture below.
I tried doing it by setting the padding, but that only works for the actual text not the placeholder text.
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
}
}
It looks ok if the textfield is focused. If it is out of focus, the text is overlapped by the icon (see password field):
But I want it to look like this:
The TextField
in Material style uses Material.textFieldHorizontalPadding
(source code). And since textFieldHorizontalPadding
is read-only and there is no alias defined for placeholder
, you cannot change the placeholder's x
position directly.
There are two options here:
You can either copy and paste the source code from material/TextField.qml
and modify it, as shown below:
T.TextField {
// ...
+ property real holderPadding: control.Material.textFieldHorizontalPadding
// ...
FloatingPlaceholderText {
// ...
+ x: control.holderPadding
- x: control.Material.textFieldHorizontalPadding
// ...
}
}
Or, you can access the placeholder
using the children
property (or visibleChildren
).
The current placeHolder
object is located at visibleChildren[0]
. By using Binding
, you can bind the placeholder's x
position to a custom property (e.g., holderPadding
). You can then change that property based on the TextField
's activeFocus
. The changes can be seen in the following code:
TextField {
id: input
property alias iconSource: image.source
property real spacing: 5
property real holderPadding: activeFocus ? Material.textFieldHorizontalPadding : leftPadding
Binding { target: input.visibleChildren[0]; property: 'x'; value: input.holderPadding }
Behavior on holderPadding { NumberAnimation {} }
selectByMouse: true
height: 40; width: 250
placeholderText: 'placeholder'
leftPadding: image.x + image.width + spacing
Image {
id: image
x: 10; y: (parent.height - height) / 2
height: width; width: parent.height * 0.5
source: "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 483.1 482.7'%3E%3Cpath fill='%235f6469' d='M93 364.4c88.9-67.4 208-67 296.8 0 105-124.6 15.1-316.6-148.4-316.1C78.2 47.6-11 239.7 93 364.4zm148.4-99c-75.2 1.5-112.9-92.4-59.7-144.2 31.5-32.5 88.8-33.1 120.1 0 52.2 51.8 15.1 147-60.4 144.2zm0 217.2a239.3 239.3 0 0 1-222-147.2C-48.1 176.9 68.9.4 241.4 0A241.7 241.7 0 0 1 464 335.4c-36.9 87.7-126.3 148.9-222.6 147.2zm0-48.2a180 180 0 0 0 112.2-36.2A190.4 190.4 0 0 0 241.4 362c-41-.2-79.7 13-112.2 36.2 32.3 23.9 71 37.2 112.2 36.2zm0-217.2a35.1 35.1 0 0 0 36.2-36.2 35.1 35.1 0 0 0-36.2-36.2 35.3 35.3 0 0 0-36.2 36.2 35.1 35.1 0 0 0 36.2 36.2z'/%3E%3C/svg%3E"
sourceSize{ width: 50; height: 50 }
}
}
Note
There are also some issues if you want to use it with RTL, which you can fix by adding some conditions.