On Friday, November 13, 2015 14:32:34 Lubomir I. Ivanov wrote:
> >>>> It's coming along. How hard will it be to swipe sideways from dive to
> >>>> dive
> >>>> when in dive detail mode? So I tap on one of the dives and I just swipe
> >>>> left and right to get to the previous / next dive instead of having to
> >>>> go
> >>>> back to the dive list between dives?
> >>>
> >>> Not entirely trivial as the dives are currently not items next to each
> >>> other.
> >>> Adding previous/next in general shouldn't be too hard, and we could hook
> >>> it up
> >>> to swipe gestures, but it won't look completely natural since we're not
> >>> having
> >>> dives as separate items next to each other. I'll give it some more
> >>> thinking.
> >>>
> >>
> >> hello,
> >>
> >> here is a concept with some QML source code (attached), which can help
> >> you get started.
> >> basically you need two 2 dive containers (dive details) - the current
> >> one which is displayed and another one which is the one which comes
> >> after the user swipes.
> >> the one which comes as new, can be populated with data on the go. if
> >> this is slow, some sort of buffering is an option - e.g. 2 dives ahead
> >> and 2 behind.
> >>
> >>
https://dl.dropboxusercontent.com/u/1627980/subsurface/mobile_dive_details_concept.gif
> >>
> >> what i don't like in this experiment is that i have a SwipeArea that
> >> handles the swipe gestures, inside a Flickable and the 2 Dives are
> >> inside the SwipeArea. normally you would want a Flickable per Dive,
> >> because if the user Flicks a dive (say, to look at the dive notes at
> >> the bottom) and then decides to swipe to the next dive the next dive
> >> Flickable contentY should be at 0, while the old Dive flickable
> >> contentY should be where the user left it.
> >>
> >> i couldn't get a Flickable inside a SwipeArea to work - no matter the
> >> usage of preventStealing and propagateComposedEvents.
> >> my current solution is to simply reset the single Flickable contentY
> >> to 0 on each swipe, which creates a bit of a glitch.
> >>
> >
> > alright...
> >
> > so here is the visual of the working POC:
> >
https://dl.dropboxusercontent.com/u/1627980/subsurface/mobile_dive_details_concept2.gif
> >
> > i restructured the classes a little and now it works the following way:
> > - one DiveContainer that defines a navigation callback (i.e.
> > left/right) and includes 2 Dives
> > - each Dive contains a SwipeArea inside a Flickable. the actual dive
> > details are inside the SwipeArea itself.
> >
> > this is a workaround as i would have preferred to have one SwipeArea
> > over the whole DiveContainer and not for each Dive; the solution is
> > tolerable as long as we don't have thousands of Dive instances. one
> > Flickable per Dive is desired though, like seen in the visual/GIF.
> >
> > attached is the updated source (with comments this time).
> > hope that helps, Sebastian.
> >
>
> latest iteration of the test project here.
>
> in the previous version stuff inside the SwipeArea was not clickable -
> so we can't have a dive details pane with buttons inside of it, which
> obviously isn't acceptable.
> the challenge here is that we have a scroll area (Flickable), inside
> of which there is an area which captures swipes (SwipeArea) and inside
> of it there could be buttons.
> ...a bit of a complicated mess, but it's doable in QML.
>
> this modification adds single touch support for that via tracking if
> the mouse is still over the last pressed element  - e.g. see
> 'diveDetailsMouseArea' in DiveDetails.
> if so, the Dive class captures the click and emits the clicked()
> signal to 'diveDetailsMouseArea'
> there could be better solutions, but i don't know of them.
>
> this allows the the user to click, say on the dive details to execute
> some action, while he/she can still swipe or flick/scroll the dive.
>
> i've also cleaned up the SwipeArea a little.

Hah, nice!

For my taste, the code especially in SwipeArea is a bit low-level, making it
hard to maintain. The javascript running on the change notifier signals may
also slow down the whole thing. In my experience, especially input logic can
be quite brittle, not necessarily something you want to maintain for a long
time.

On the other hand, QtQuick's ListView provides already what we need. So here's
a slightly different approach: we use a listview will delegates sized to fit
exactly in the viewport. We re-use the divelist's model for this listview as
well, and we set the listview to snap to items when scrolling: pronto: we
a=have swiping.

This means that we show usually one item (and when swiping left/right between
items two partial items), so we can tell the listview to keep the number of
items rendered in check, ListView is equipped to do that with the
ListView.cacheBuffer property, which essentially says: "keep delegates for
this number of pixels left and right ready", so it will dynamically render
more items and delete the delegates as needed.
As a bonus, we don't have to copy a whole lot of data between divelist and
details view, we just set the detail's listview.currentItem to whatever the
user picked in the overview list (and possibly avoid animations).

Do I make sense to you? If not, proof-of-concept attached. It's quite minimal
and only shows the very basic mechanism.

I quite like what you have done in the delegate. I'd like to split viewing and
editing dives into separate UIs, one optimized for viewing, one optimized for
editing (e.g. showing the profile in the editing page is not very useful, on
the other hand the TextEdit widgets in the details view make it visually quite
heavy. We should probably do something like to the current details delegate
(and repurpose / cut down the current detailswidget purely for editing.

Love the profile.png by the way. :)

Cheers,
--
sebas

Sebastian Kügler    |    http://vizZzion.org    |     http://kde.org

import QtQuick 2.0

// example for a divedetails page done in a listview to allow
// navigation between dives by scrolling horizontally
ListView {
	id: listview

	width: 480
	height: 800

	orientation: Qt.Horizontal
	// Make sure we only scroll max one item
	snapMode: ListView.SnapOneItem

	// just a list of ints
	model: 5
	// initial page is...
	currentIndex: 3
	// the cache buffer controls how many delegates outside
	// of the view are kept in cache, value in px
	cacheBuffer: 0

	/*
	// The actual dive details page is a delegate that can be
	// reused and instantiated / deletes by the listview logic
	delegate: Component {
		Rectangle {
			// Make the delegate fill the whole viewport of the list
			width: listview.width
			height: listview.height

			anchors.margins: 4
			color: "lightgrey"

			Text {
				text: "Dive #" + index
				font.pointSize: 20
			}
			Text {
				text: "Here be dive details."
				anchors.centerIn: parent
			}
			// let's see when these delegate are created on the console
			Component.onCompleted: print("Created new dive details page " + index)
		}
	}
	*/
	delegate: DiveDetails {}
}

_______________________________________________
subsurface mailing list
subsurface@subsurface-divelog.org
http://lists.subsurface-divelog.org/cgi-bin/mailman/listinfo/subsurface

Reply via email to