The Overlay View feature is excellent for items like Share buttons which
can remain in one place as the images scroll, but customizations cannot
be added that scroll with the images being viewed. Additionally, the
scrolling images themselves cannot be customized beyond what can be done
in the ImageLoader and the background/padding/etc. options provided in
StfalconImageViewer.Builder.
To enable additional use cases, this commit allows applications to
subclass the ViewHolders used internally, providing full control over
the scrolling views. Subclasses are passed the PhotoView used in the
default ViewHolder. Subclasses might simply adjust the style or layout
parameters of the PhotoView. Subclasses might incorporate the PhotoView
within a Layout and include other Views (e.g. a "New Image!" icon
overlaid in the corner, or a caption). Subclasses might include other,
alternative Views (e.g. a VideoView) and display one or the other
depending on the item bound to the ViewHolder. Subclasses might ignore
the PhotoView altogether and insert their own Views.
This is achieved without affecting the existing use cases or requiring
existing apps to modify their usage.
A new constructor is added to StfalconImageViewer.Builder allowing
applications a pass an additional argument, an implementation of
ViewHolderLoader. This contains a single function, accepting a PhotoView
and returning a subclass of DefaultViewHolder. When this new
constructor is not used, a DefaultViewHolderLoader is used, which
returns a DefaultViewHolder (which is the ViewHolder that was used
before, extracted to its own file and enhanced for extensibility).
Through a custom ViewHolderLoader and the DefaultViewHolder constructor
and bind() methods overridden in the subclass, applications have
complete control of the Views presented in the ViewPager.
My use cases involves displaying both photos and videos taken with the
camera function in my app, so my ViewHolderLoader creates a FrameLayout
containing the default PhotoView and a VideoView, and my ViewHolder
switches between these two views depending on the Uri it receives in
bind(). To allow applications such as my own to play/pause videos as
they come on or off the screen, I added two methods to
DefaultViewHolder, onDialogClosed() and setIsVisible(), to allow videos
to be paused when scrolled off-screen, resumed when scrolled on-screen,
and stopped entirely when the dialog begins to close.
A demo of custom ViewHolders will be posted at
https://github.com/svank/Custom-ViewHolders-Demo