2016-06-23 13 views
0

Ich habe eine WML-Anwendung mit einem ScrollView und einem ListView innerhalb. Die Elemente aus der ListView haben eine variable Höhe.ListView in einer ScrollView: Wie Scroll-Position zu wissen (ist es unten?)

Ich muss wissen, wenn die Bildlaufleiste bewegt wird, in der Tat, wenn es unten ist und wenn es nicht ist. Mein Ziel ist es, Scroll am unteren Rand (positionViewAtEnd()) zu halten, wenn ich ein Element nur dann zur ListView hinzufüge, wenn die Rolle unten ist. Wenn nicht unten, wird positionViewAtEnd() nicht verwendet.

Ich habe versucht, mit Höhe, contentHeigh & contentY "spielen". Manchmal funktioniert es (wenn scroll ist unten: contentHeight == contentY + height), aber zu anderen Zeiten contentY Wert ändert sich in negative Werte, und mein Code schlägt fehl ...

Irgendwelche Hilfe?

Vielen Dank

Diego


Dank JP Nurmi,

Ich habe in mehreren Eigenschaftsänderungen mit 'atYEnd' versucht, zu erkennen, wenn Scroll unten ist oder nicht

Es scheint zu funktionieren, und dann verwende ich das in 'onCountChanged', um die Schriftrolle an der Unterseite

01 zu setzen (oder nicht)

Das funktioniert, sobald die gesamte ListView-Höhe voller Nachrichten ist, aber NICHT in EINEM Fall: wenn die eingehende Nachricht die ListView-Höhe (das erste Mal, dass contentY NICHT '0' ist) ausfüllt.

Ich weiß nicht, ob es klar ist ...

ich meinen Code (einschließlich der Delegierten) zu testen vereinfacht, und es scheint nun wie folgt aus:

FocusScope { 
     clip: true 

     id: focusScopeView 

     width: parent.width; height: parent.height 

     ScrollView { 

      width: parent.width; height: parent.height 

      ListView { 
       id: listTexts 

       width: parent.width; height: parent.height 

       property bool bScrolled: false 

       model: textsModel 
       delegate: Text { text: "Contact:\t" + eventText } 

       onCountChanged: { 

        if (!bScrolled) 
         positionViewAtEnd(); 
     } 

       onContentYChanged: { 
        bScrolled = !atYEnd; 

        if (atYEnd) 
         positionViewAtEnd() 
     } 

       onContentHeightChanged: { 
        if (!bScrolled) 
         positionViewAtEnd(); 
      } 
      } 
     } 
    } 

Danke und Grüße !

Diego

Antwort

0

Der Grund, warum die Berechnung fehlschlägt, ist, dass ListView seinen Ursprung hatte aufgrund Delegierten mit variabler Höhe einzustellen. Einschließlich originY zur Berechnung würde helfen, den richtigen Wert zu erhalten, aber es gibt eine viel bequemere Möglichkeit zu überprüfen, ob FlickableatYEnd ist.

EDIT: Dies ist ein kleiner Trick, aber eine andere Möglichkeit zum automatischen Scrollen (oder besser, um das Scrollen zu vermeiden) ist die Verwendung von ListView.BottomToTop als vertical layout direction. Wenn Sie stattdessen an das Ende anhängen, fügen Sie am Anfang des Modells neue Nachrichten ein. Auf diese Weise bleibt der Inhalt nach unten ausgerichtet, wenn neue Nachrichten ankommen, ohne dass eine manuelle Positionierung erfolgt. Es gibt jedoch einen kleinen Haken. Der Inhalt wird auch nach unten ausgerichtet, wenn weniger Inhalt vorhanden ist als in der Ansicht angezeigt wird.

+0

Danke, aber neue eingehende Nachrichten müssen an der Unterseite hinzugefügt ... – Diego

+0

Ja, das ist, was 'verticalLayoutDirection: ListView.BottomToTop' tut, wenn Sie am Anfang des Modells einsetzen, zum Beispiel' listModel.insert (0, {text: "foo"}) '. – jpnurmi

0
ListView { 
     onContentYChanged: { 
      if (contentY === contentHeight - height) { 
       console.log("scrolled to bottom"); 
      } 
     } 
    } 


    ScrollView { 
      flickableItem.onContentYChanged: { 
       if (flickableItem.contentY === flickableItem.contentHeight - viewport.height) { 
        console.log("scrolled to bottom"); 
       } 
      } 
     } 
+0

Sie sollten Ihren Code ein wenig erklären – moritzg