为了实现一种较复杂的Row, 该Row在整个屏幕是居中的, Row里面有2个Text A、B和一个分隔符(图片). B的长度取决于A的长度以及三个部件的总长度. 总长度是720而Text A优先显示, 则B可显示长度为720-A长度-分隔符,Text B显示不下则显示“...”. 大概效果是(第一行):
Text B显示得下效果是:
为了实现出上述需求, QML代码如下:
Row {anchors.horizontalCenter: parent.horizontalCenterspacing: Skin.MARGIN_8SLText {id: subLabelwidth: Math.min(implicitWidth, Skin.CALL_INFO_WIDTH)visible: text != ""}SLSeparatorDot {anchors.verticalCenter: parent.verticalCentervisible: subLabel.visible && hgLabel.visible}SLText {id: hgLabelwidth: getHgWidth(subLabel.implicitWidth, hgLabel.implicitWidth)elide: Text.ElideRightonImplicitWidthChanged: {console.log("!!!hgLabel onImplicitWidthChanged:"+implicitWidth);}onContentWidthChanged: {console.log("!!!hgLabel onContentWidthChanged:"+contentWidth);}onWidthChanged: {console.log("!!!hgLabel onWidthChanged:"+width);}function getHgWidth(subImplicitWidth, hgImplicitWidth) {var hgWidth = 0;console.log("!!!getHgWidth0 subImplicitWidth:"+subImplicitWidth+",hgImplicitWidth:"+hgImplicitWidth);if (hgImplicitWidth > 0 && subImplicitWidth > 0) {hgWidth = Math.min(hgImplicitWidth, Skin.CALL_INFO_WIDTH - subImplicitWidth - Skin.SEPARATOR_DOT_WIDTH - Skin.MARGIN_8 * 2)}else if (hgImplicitWidth > 0) {hgWidth = Math.min(hgImplicitWidth, Skin.CALL_INFO_WIDTH)}return hgWidth;}}}SLText {id: demoanchors.horizontalCenter: parent.horizontalCentertext: "xxxxxxxx"onImplicitWidthChanged: {console.log("!!!demo onImplicitWidthChanged:"+implicitWidth);}onContentWidthChanged: {console.log("!!!demo onContentWidthChanged:"+contentWidth);}onWidthChanged: {console.log("!!!demo onWidthChanged:"+width);}}
由于项目中的Text内容是动态加载的,时序和固定内容的Text有些许区别. 我特意加了一个普通Text作为对比,并在每个要关注的signal的响应的slot(onXxxChanged)中打出log去观察时序:
8104 DEB Mar 16 16:00:53.586844 (25414-25414) guiapp-!!!demo onWidthChanged:101.5
8105 DEB Mar 16 16:00:53.586912 (25414-25414) guiapp-!!!demo onImplicitWidthChanged:101.5
8106 DEB Mar 16 16:00:53.586966 (25414-25414) guiapp-!!!demo onContentWidthChanged:101.5
8107 DEB Mar 16 16:00:53.587004 (25414-25414) guiapp-!!!demo onImplicitWidthChanged:101.58103 DEB Mar 16 16:00:53.585190 (25414-25414) guiapp-!!!getHgWidth0 subImplicitWidth:0,hgImplicitWidth:0
8128 DEB Mar 16 16:00:53.637086 (25414-25414) guiapp-!!!getHgWidth0 subImplicitWidth:172.6875,hgImplicitWidth:0
8129 DEB Mar 16 16:00:53.637427 (25414-25414) guiapp-!!!hgLabel onImplicitWidthChanged:201.203125
8130 DEB Mar 16 16:00:53.637477 (25414-25414) guiapp-!!!getHgWidth0 subImplicitWidth:172.6875,hgImplicitWidth:201.203125
8131 DEB Mar 16 16:00:53.637527 (25414-25414) guiapp-!!!hgLabel onWidthChanged:201.203125
8132 DEB Mar 16 16:00:53.637640 (25414-25414) guiapp-!!!hgLabel onContentWidthChanged:201.203125
可以看到,
对于动态内容Text, width被getHgWidth绑定, 故function一定先调用, 不论implicitWidth和contentWidth是否为0. 一旦有text动态更新,先变化的属性是implicitWidth, 这将trigger function再次调用,这将导致width更新, 而最后更新的是contentWidth.
对于固定内容Text, witdh未设置, 从log来看width先变化, 然后是implicitWidth最后是contentWidth. 一些资料对于Text的实际文字长度选用contentWidth可能是有问题的. 在此我们得知,如果要尽早得知Text的实际文字长度的更新应该使用implicitWidth.
说句题外话,我之前getHgWidth想用Text A和Text B的visible属性来作为function参数来更新witdh,但发现虽然每次visible更新但是implicitWidth/contentWidth可能为0(我一旦在onVisible里面打log去print implicitWidth/contentWidth则函数体内implicitWidth/contentWidth就被更新了). 可见QML内部这些属性的更新有自己的时序, 而且getHgWidth函数体内即便有implicitWidth和contentWidth但拿到的值并不是最新的. 因此尝试使用implicitWidth/contentWidth作为参数去 trigger function, 结果是达到预期的. 因此推断QML中function是由参数而非函数体内变量去trigger的.