Material: fix placeholder text y position when control is too small
Ensure that it's sensibly positioned despite its size. Fixes: QTBUG-111515 Pick-to: 6.5 6.5.0 Change-Id: I71816c461ff1d2f85e010bf871ab1b7ef2ccaf6e Reviewed-by: Oliver Eftevaag <oliver.eftevaag@qt.io>
This commit is contained in:
parent
ee3d11f70b
commit
4f5b4f81b0
|
@ -50,6 +50,7 @@ T.TextArea {
|
|||
controlHasActiveFocus: control.activeFocus
|
||||
controlHasText: control.length > 0
|
||||
controlImplicitBackgroundHeight: control.implicitBackgroundHeight
|
||||
controlHeight: control.height
|
||||
}
|
||||
|
||||
background: MaterialTextContainer {
|
||||
|
|
|
@ -50,6 +50,7 @@ T.TextField {
|
|||
controlHasActiveFocus: control.activeFocus
|
||||
controlHasText: control.length > 0
|
||||
controlImplicitBackgroundHeight: control.implicitBackgroundHeight
|
||||
controlHeight: control.height
|
||||
}
|
||||
|
||||
background: MaterialTextContainer {
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <QtGui/qpainterpath.h>
|
||||
#include <QtQml/qqmlinfo.h>
|
||||
#include <QtQuickTemplates2/private/qquicktheme_p.h>
|
||||
#include <QtQuickTemplates2/private/qquicktextarea_p.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
|
@ -100,13 +101,25 @@ bool QQuickMaterialPlaceholderText::shouldAnimate() const
|
|||
: !m_controlHasText && !text().isEmpty();
|
||||
}
|
||||
|
||||
void QQuickMaterialPlaceholderText::updateY()
|
||||
{
|
||||
setY(shouldFloat() ? floatingTargetY() : normalTargetY());
|
||||
}
|
||||
|
||||
qreal QQuickMaterialPlaceholderText::normalTargetY() const
|
||||
{
|
||||
auto *textArea = qobject_cast<QQuickTextArea *>(parentItem());
|
||||
if (textArea && m_controlHeight >= textArea->implicitHeight()) {
|
||||
// TextArea can be multiple lines in height, and we want the
|
||||
// placeholder text to sit in the middle of its default-height
|
||||
// (one-line) if its explicit height is greater than or equal to its
|
||||
// implicit height - i.e. if it has room for it. If it doesn't have
|
||||
// room, just do what TextField does.
|
||||
return (m_controlImplicitBackgroundHeight - m_largestHeight) / 2.0;
|
||||
}
|
||||
|
||||
// When the placeholder text shouldn't float, it should sit in the middle of the TextField.
|
||||
// We could just use the control's height minus our height instead of the members, but
|
||||
// that doesn't work for TextArea, which can be multiple lines in height and hence taller.
|
||||
// In that case, we want the placeholder text to sit in the middle of its default-height (one-line).
|
||||
return (m_controlImplicitBackgroundHeight - m_largestHeight) / 2.0;
|
||||
return (m_controlHeight - height()) / 2.0;
|
||||
}
|
||||
|
||||
qreal QQuickMaterialPlaceholderText::floatingTargetY() const
|
||||
|
@ -142,10 +155,34 @@ void QQuickMaterialPlaceholderText::setControlImplicitBackgroundHeight(qreal con
|
|||
return;
|
||||
|
||||
m_controlImplicitBackgroundHeight = controlImplicitBackgroundHeight;
|
||||
setY(shouldFloat() ? floatingTargetY() : normalTargetY());
|
||||
updateY();
|
||||
emit controlImplicitBackgroundHeightChanged();
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
|
||||
Exists so that we can call updateY when the control's height changes,
|
||||
which is necessary for some y position calculations.
|
||||
|
||||
We don't really need it for the actual calculations, since we already
|
||||
have access to the parent item, from which the property comes, but
|
||||
it's simpler just to use it.
|
||||
*/
|
||||
qreal QQuickMaterialPlaceholderText::controlHeight() const
|
||||
{
|
||||
return m_controlHeight;
|
||||
}
|
||||
|
||||
void QQuickMaterialPlaceholderText::setControlHeight(qreal controlHeight)
|
||||
{
|
||||
if (qFuzzyCompare(m_controlHeight, controlHeight))
|
||||
return;
|
||||
|
||||
m_controlHeight = controlHeight;
|
||||
updateY();
|
||||
}
|
||||
|
||||
qreal QQuickMaterialPlaceholderText::verticalPadding() const
|
||||
{
|
||||
return m_verticalPadding;
|
||||
|
@ -185,8 +222,7 @@ void QQuickMaterialPlaceholderText::controlGotActiveFocus()
|
|||
|
||||
m_focusInAnimation->start(QAbstractAnimation::DeleteWhenStopped);
|
||||
} else {
|
||||
const int newY = shouldFloat() ? floatingTargetY() : normalTargetY();
|
||||
setY(newY);
|
||||
updateY();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -212,16 +248,14 @@ void QQuickMaterialPlaceholderText::controlLostActiveFocus()
|
|||
|
||||
m_focusOutAnimation->start(QAbstractAnimation::DeleteWhenStopped);
|
||||
} else {
|
||||
const int newY = shouldFloat() ? floatingTargetY() : normalTargetY();
|
||||
setY(newY);
|
||||
updateY();
|
||||
}
|
||||
}
|
||||
|
||||
void QQuickMaterialPlaceholderText::maybeSetFocusAnimationProgress()
|
||||
{
|
||||
const bool shouldWeFloat = shouldFloat();
|
||||
setY(shouldWeFloat ? floatingTargetY() : normalTargetY());
|
||||
setScale(shouldWeFloat ? floatingScale : 1.0);
|
||||
updateY();
|
||||
setScale(shouldFloat() ? floatingScale : 1.0);
|
||||
}
|
||||
|
||||
void QQuickMaterialPlaceholderText::componentComplete()
|
||||
|
|
|
@ -34,6 +34,7 @@ class QQuickMaterialPlaceholderText : public QQuickPlaceholderText
|
|||
Q_PROPERTY(qreal verticalPadding READ verticalPadding WRITE setVerticalPadding NOTIFY verticalPaddingChanged FINAL)
|
||||
Q_PROPERTY(qreal controlImplicitBackgroundHeight READ controlImplicitBackgroundHeight
|
||||
WRITE setControlImplicitBackgroundHeight NOTIFY controlImplicitBackgroundHeightChanged FINAL)
|
||||
Q_PROPERTY(qreal controlHeight READ controlHeight WRITE setControlHeight FINAL)
|
||||
QML_NAMED_ELEMENT(FloatingPlaceholderText)
|
||||
QML_ADDED_IN_VERSION(6, 5)
|
||||
|
||||
|
@ -54,6 +55,9 @@ public:
|
|||
qreal controlImplicitBackgroundHeight() const;
|
||||
void setControlImplicitBackgroundHeight(qreal controlImplicitBackgroundHeight);
|
||||
|
||||
qreal controlHeight() const;
|
||||
void setControlHeight(qreal controlHeight);
|
||||
|
||||
qreal verticalPadding() const;
|
||||
void setVerticalPadding(qreal verticalPadding);
|
||||
|
||||
|
@ -69,6 +73,7 @@ private:
|
|||
bool shouldFloat() const;
|
||||
bool shouldAnimate() const;
|
||||
|
||||
void updateY();
|
||||
qreal normalTargetY() const;
|
||||
qreal floatingTargetY() const;
|
||||
|
||||
|
@ -85,6 +90,7 @@ private:
|
|||
int m_largestHeight = 0;
|
||||
qreal m_verticalPadding = 0;
|
||||
qreal m_controlImplicitBackgroundHeight = 0;
|
||||
qreal m_controlHeight = 0;
|
||||
QPointer<QParallelAnimationGroup> m_focusInAnimation;
|
||||
QPointer<QParallelAnimationGroup> m_focusOutAnimation;
|
||||
};
|
||||
|
|
|
@ -7,6 +7,7 @@ import QtTest
|
|||
import QtQuick.Templates as T
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Controls.Material
|
||||
import QtQuick.Controls.Material.impl as MaterialImpl
|
||||
|
||||
TestCase {
|
||||
id: testCase
|
||||
|
@ -953,4 +954,40 @@ TestCase {
|
|||
verify(item)
|
||||
compare(item["__isDiscrete"], data.expectTickmarks)
|
||||
}
|
||||
|
||||
Component {
|
||||
id: textFieldComponent
|
||||
TextField {}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: textAreaComponent
|
||||
TextArea {}
|
||||
}
|
||||
|
||||
function test_placeholderText() {
|
||||
{
|
||||
// The non-floating placeholder text should be in the middle of TextField regardless of its height.
|
||||
let textField = createTemporaryObject(textFieldComponent, testCase, { placeholderText: "TextField" })
|
||||
verify(textField)
|
||||
let placeholderTextItem = textField.children[0]
|
||||
verify(placeholderTextItem as MaterialImpl.FloatingPlaceholderText)
|
||||
compare(placeholderTextItem.y, (textField.height - placeholderTextItem.height) / 2)
|
||||
textField.height = 10
|
||||
compare(placeholderTextItem.y, (textField.height - placeholderTextItem.height) / 2)
|
||||
textField.destroy()
|
||||
}
|
||||
|
||||
{
|
||||
// The non-floating placeholder text should be near the top of TextArea while it has room, but when it
|
||||
// doesn't have room, it should start behaving like TextField's.
|
||||
let textArea = createTemporaryObject(textAreaComponent, testCase, { placeholderText: "TextArea" })
|
||||
verify(textArea)
|
||||
let placeholderTextItem = textArea.children[0]
|
||||
verify(placeholderTextItem as MaterialImpl.FloatingPlaceholderText)
|
||||
compare(placeholderTextItem.y, (placeholderTextItem.controlImplicitBackgroundHeight - placeholderTextItem.largestHeight) / 2)
|
||||
textArea.height = 10
|
||||
compare(placeholderTextItem.y, (textArea.height - placeholderTextItem.height) / 2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue