2015-06-25 15 views
6

Co muszę zrobić: muszę utworzyć okno czat użyciu ListView w QML że przechowuje chat-wiadomości. Ustawię listView.positionViewAtEnd(), aby śledzić ostatnie wiadomości. Wyłączam positionViewAtEnd kiedy przewijam w górę tak, że mogę czytać poprzednie wiadomości bez skakania na końcu za każdym razem, gdy otrzymuję nową wiadomość.Jak zatrzymać ListView dla „skoki”, gdy model został zmieniony

Problem Po przewijania w górę, za każdym razem otrzymam nową wiadomość skacze na początku listy. Aby rozwiązać że udaje mi się Przechowywać contentY listy i zresetować go za każdym razem onCountChanged obsługi nazywa (patrz poniższy kod):

ListView { 
    id: messagesList 
    model: contact? contact.messages: [] 
    delegate: delegate 
    anchors.fill: parent 
    anchors.bottomMargin: 20 
    height: parent.height 
    anchors.margins: 10 

    property int currentContentY 

    onMovementEnded: { 
     currentContentY = contentY 
    } 

    onCountChanged: { 
     contentY = currentContentY 
    } 
    onContentYChanged: { 
     console.log(".....contentY: " + contentY) 
    } 
} 

Problem polega na tym, że chociaż mogę ustawić ostatnią contentY miałem , zanim model został zmieniony, lista wciąż przeskakuje nieco (kilka pikseli, a nie na końcu lub na początku) i nie przeskakuje zawsze. A kiedy przejdę na początek listy i wydrukuję contentY, otrzymam wartości ujemne. Teoretycznie, contentY na początku listy powinno być 0.

Czy ktoś może mi powiedzieć, co się dzieje? A może zasugerować inne rozwiązanie do utworzenia mojej listy wiadomości?

Niż z góry! :)

+0

Jak wypełnić/zmienić 'contact.messages'? – GrecKo

+0

Jest to lista wyeksponowana z C++ przy użyciu qqmllistproperty. Kiedy jest modyfikowany z C++ (po dodaniu wiadomości) wysyłam sygnał, a widok listy z qml wie, aby zaktualizować swój model –

+0

Czy ten 'ręczny' MovementEnded' jest spójny? Nigdy nie używał 'QQmlListProperty' jako modelu, ale wydaje się działać [całkiem dobrze] (http://stackoverflow.com/a/28534291/2538363). W każdym razie, podklasa 'QAbstractListModel' wykonałaby to zadanie doskonale. – BaCaRoZzo

Odpowiedz

1

Dlaczego nie skorzystać z gniazda OnCountChanged, aby ustawić ListView na końcu?

onCountChanged: { 
    messagesList.positionViewAtEnd() 
} 
+0

Użyłem tego, ale nie chcę skakać na końcu, jeśli otrzymam nową wiadomość, gdy nie jestem na końcu (przewijam w górę, kiedy jestem na środku listy) –

+0

W tym przypadku możesz wyłączyć positionViewAtEnd() na podstawie jakiegoś zdarzenia i włącz go na innym wydarzeniu. Uważam, że twoje wymagania są raczej sprzeczne. –

+0

To nie jest odpowiedź. I dlaczego moje pytanie jest sprzeczne? Weź przykład skype. Chcę stworzyć coś podobnego. positionViewAtEnd rozwiązuje problem tylko wtedy, gdy znajduję się na samym dole listy! I Kiedy jestem na środku listy, nie chcę skakać pod koniec, chcę tam zostać. –

1

Jednym z możliwych rozwiązań schould być insert ListView do Flickable i wyłączyć interaktywną flagę ListView

Flickable { 
     id: fparent 
     anchors.fill: parent 
     anchors.bottomMargin: 20 
     anchors.margins: 10 

     interactive: true 
     clip: true 
     flickableDirection: Flickable.VerticalFlick 
     contentHeight: messagesList.height 

     ListView { 
      id: messagesList 
      width: parent.width 
      height: childrenRect.height 
      clip: true 
      model: contact? contact.messages: [] 
      delegate: delegate 
      interactive: false 
      onCountChanged: { 
       fparents.returnToBounds(); 
      } 
     } 
    } 
Powiązane problemy