I would like to create a list of about 200 ImageViews (random heights) with the following layout in a ‘collage’ fashion:

Normally I would do this in a ListView for the peformance gained by using Adapters but since i want the images to be displayed in columns, and with different height (See picture Example ) depending on the pictures, I cannot use a single listview for this purpose.
I have tried implementing this layout with:
- Three ListViews with synchronized scrolling = Slow
- Single ListView with each row containing three images = Not allowing different heights
- GridView = Not allowing different heights
- GridLayout = Difficult to implement different heights programmatically. Because of no adapter, OutOfMemoryErrors are common
- FlowLayout = Because of no adapter, OutOfMemoryErrors are common
- ScrollView with three Vertical LinearLayouts = Best solution so far, but OutOfMemoryErrors are common
I have ended up using three LinearLayouts in a ScrollView, but this is far from optimal. I would rather use something with an Adapter.
EDIT
I have been looking at the StaggeredGridView, as in a response below, but I find it quite buggy. Are there any implementations of this that are more stable?
I think I have a working solution for you.
The main files mentioned here are also on PasteBin at http://pastebin.com/u/morganbelford
I basically implemented a simplified equivalent of the github project mentioned, https://github.com/maurycyw/StaggeredGridView, using a set of excellent LoopJ
SmartImageViews.My solution is not nearly as generic and flexible as the
StaggeredGridView, but seems to work well, and quickly. One big difference functionally is that we layout the images always just left to right, then left to right again. We don’t try to put the next image in the shortest column. This makes the bottom of the view a little more uneven, but generates less shifting around during initial load from the web.There are three main classes, a custom
StagScrollView, which contains a customStagLayout(subclassedFrameLayout), which manages a set ofImageInfodata objects.Here is our layout, stag_layout.xml (the 1000dp initial height is irrelevant, since it will get recomputed in code based on the image sizes):
Here is our main Activity’s
onCreate, which uses the layout. TheStagActivityjust basically tells theStagLayoutwhat urls to use, what the margin should be between each image, and how many columns there are. For more modularity, we could have passed these params to the StagScrollView (which contains the StagLayout, but the the scroll view would have just had to pass them down the layout anyway):Before we get to the meat of the solution, here is our simple
StagScrollViewsubclass. His only special behavior is to tell his main child (ourStagLayout) which the currently visible area is, so that he can efficiently use the smallest possible number of realized subviews.Here then is the most important class
StagLayout.First,
setUrlssets up our data structures.Our main data structure is
ImageInfo. It is a kind of lightweight placeholder that allows us to keep track of where each image is going to be displayed, when it needs to be. When we layout our child views, we will use the information in the ImageInfo to figure out where to put the actual view. A good way to think about ImageInfo is as a “virtual image view”.See comments inline for details.
The rest of the magic happens in
StagLayout'sonMeasureandonLayout.Ok, now let’s see how we actually arrange all the ImageInfos.
And, now let’s see how we create, resuse and dispose of real
SmartImageViewsduringonLayout.Remember that _viewportTop and _viewportBottom are set every time the user scrolls.