我有一个Flickable
,其中包含大量TextField
个对象,这些对象布在一列中,每个TextField都锚定在前一个TextField的底部。一切都工作得很好,除了当我使用tab键浏览这些字段时,最终焦点转移到Flickable
的可见矩形之外的TextField,然后用户无法看到光标直到它们手动向下滚动Flickable。
基本上我正在寻找某种“.ensureVisible()”方法,这样当TextField接收焦点时,Flickable会自动滚动,以便刚刚聚焦的TextField完全可见。
答案 0 :(得分:2)
您是否考虑过更具模范性的方法?我的意思是,如果您使用类似ListView
的内容,则只需更改currentItem
,如果视图超出可见范围,视图将自动滚动到该视图。
此外,它只会加载可见范围内的文本元素,从而节省了一些内存。
但即使使用您当前的方法,确保可见性也不会那么复杂。
Flickable {
id: flick
anchors.fill: parent
contentHeight: col.height
function ensureVisible(item) {
var ypos = item.mapToItem(contentItem, 0, 0).y
var ext = item.height + ypos
if ( ypos < contentY // begins before
|| ypos > contentY + height // begins after
|| ext < contentY // ends before
|| ext > contentY + height) { // ends after
// don't exceed bounds
contentY = Math.max(0, Math.min(ypos - height + item.height, contentHeight - height))
}
}
Column {
id: col
Repeater {
id: rep
model: 20
delegate: Text {
id: del
text: "this is item " + index
Keys.onPressed: rep.itemAt((index + 1) % rep.count).focus = true
focus: index === 0
color: focus ? "red" : "black"
font.pointSize: 40
onFocusChanged: if (focus) flick.ensureVisible(del)
}
}
}
}
解决方案快速而且粗糙,但将其投入生产形状将是微不足道的。映射到contentItem
而不是flickable很重要,因为后者会给出错误的结果,将当前滚动的数量考虑在内。使用映射将使解决方案与您可能使用的任何定位方案无关,并且还将支持任意级别的嵌套对象。
答案 1 :(得分:1)
function ensureVisible(item) {
if (moving || dragging)
return;
var xpos = item.mapToItem(contentItem, 0, 0).x
var ext = item.width + xpos
if ( xpos < contentX // begins before
|| xpos > contentX + width // begins after
|| ext < contentX // ends before
|| ext > contentX + width) { // ends after
// don't exceed bounds
var destinationX = Math.max(0, Math.min(xpos - width + item.width, contentWidth - width))
ensureVisAnimation.to = destinationX;
ensureVisAnimation.from = contentX;
ensureVisAnimation.start();
}
}
//This animation is for the ensure-visible feature.
NumberAnimation on contentX {
id: ensureVisAnimation
to: 0 //Dummy value - will be set up when this animation is called.
duration: 300
easing.type: Easing.OutQuad;
}