问题
Since GalleryView
deprecated we should immigrate to some alternative widgets, In my case ViewFlipper
is the best but I have faced with several issues, as you can see in the following screenshot I have designed a carousel ImageGallery
with GalleryView
:
With ViewFlipper
everything works as I expected, But I'm not able to implement two things:
1- ViewFlipper
always shows one item; however I need to display three items (or even more) at once.
2- ViewFlipper
is non-touchable widget and it's not what I want!
As FlávioFaria mentioned about ViewPager
in the following post, It's a great case too but I can't pass my scale up animation to it!
I've done everything with ViewPager
, now it's working great but I have missed one functionality and that is infinity scrolling!
Added my PagerAdapter
class
public class CarouselAdapter extends PagerAdapter
{
private Context mContext;
private ImageLoader imageLoader;
private String[] bannerUri;
public CarouselAdapter (Context c, String[] bannerArray)
{
this.mContext = c;
this.bannerUri = bannerArray;
// Setup image loader
this.imageLoader = ImageLoader.getInstance();
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(c)
.threadPoolSize(2)
.memoryCache(new WeakMemoryCache())
.discCacheFileNameGenerator(new Md5FileNameGenerator())
.build();
this.imageLoader.init(config);
}
@Override
public Object instantiateItem(ViewGroup container, int position)
{
if (position >= bannerUri.length)
position %= bannerUri.length;
ImageView i = new ImageView(mContext);
displayImage(i, bannerUri[position]);
i.setScaleType(ScaleType.FIT_XY);
container.addView(i);
return i;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object)
{
container.removeView((View)object);
}
@Override
public int getCount()
{
return Integer.MAX_VALUE;
}
@Override
public boolean isViewFromObject(View view, Object object)
{
return (view == object);
}
private void displayImage(final ImageView mImage, String ImageUri)
{
DisplayImageOptions defaultOptions = new DisplayImageOptions.Builder()
.showStubImage(R.drawable.border)
.showImageForEmptyUri(R.drawable.border)
.imageScaleType(ImageScaleType.EXACTLY)
.bitmapConfig(Bitmap.Config.RGB_565)
.resetViewBeforeLoading()
.cacheOnDisc()
.displayer(new FadeInBitmapDisplayer(740))
.build();
imageLoader.loadImage(ImageUri, defaultOptions, new SimpleImageLoadingListener()
{
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage)
{
mImage.setImageDrawable(new BitmapDrawable(mContext.getResources()
, getDesiredBitmap(loadedImage, 12)));
}
});
}
private Bitmap getDesiredBitmap(Bitmap originalImage, int roundValue)
{
// Create required bitmaps
Bitmap shadowBitmap = BitmapFactory.decodeResource(mContext.getResources()
, R.drawable.samsungapps_thumb_shadow);
Bitmap outputBitmap = Bitmap.createBitmap(originalImage.getWidth()
, originalImage.getHeight() + 80, Bitmap.Config.ARGB_8888);
// Create canvas and pass bitmap to it
Canvas mCanvas = new Canvas(outputBitmap);
// And finally draw the shaodw
mCanvas.drawBitmap(Bitmap.createScaledBitmap(shadowBitmap, originalImage.getWidth()
, (int)(shadowBitmap.getHeight() / 2.3), false), 0, originalImage.getHeight(), null);
mCanvas.drawBitmap(originalImage, 0, 0, null);
return outputBitmap;
}
}
Any idea about how to accomplish these two things?
回答1:
after going through your code i found that CarouselAdapter is behaving in circular manner(infinite scrolling) part of code is which causes this is:-
@Override
public int getCount()
{
return Integer.MAX_VALUE;
}
and
@Override
public Object instantiateItem(ViewGroup container, int position)
{
if (position >= bannerUri.length)
position %= bannerUri.length;
.
.
.
}
However you are doing
ImageView i = new ImageView(mContext);
displayImage(i, bannerUri[position]);
i.setScaleType(ScaleType.FIT_XY);
container.addView(i);
return i;
in instantiateItem, so for each page in your ViewPager, you are allocating memory for ImageView and ViewPager is getting run out of memory because of this.
ViewPager has method public void setOffscreenPageLimit (int limit)
which will limit the memory allocated by destroying idle pages in view hierarchy..
See below from the android documentation
Set the number of pages that should be retained to either side of the current page in the view hierarchy in an idle state. Pages beyond this limit will be recreated from the adapter when needed.
This is offered as an optimization. If you know in advance the number of pages you will need to support or have lazy-loading mechanisms in place on your pages, tweaking this setting can have benefits in perceived smoothness of paging animations and interaction. If you have a small number of pages (3-4) that you can keep active all at once, less time will be spent in layout for newly created view subtrees as the user pages back and forth.
You should keep this limit low, especially if your pages have complex layouts. This setting defaults to 1.
As mentioned above, If do not specify any value to it , it will use default value 1 and ViewPager will destroy idle pages from view hierarchy. So you need to pass optimised value to it, according to your memory requirements(number of images and average image size), that will solve your Out of memory issue..
回答2:
Consider using a ViewPager with multiple pages:
http://commonsware.com/blog/2012/08/20/multiple-view-viewpager-options.html
回答3:
Ok, here's one thing you can do:
Use a horizontal list view solution (example here)
Make sure each item takes about 1/3 of the width of the screen. Maybe a bit more.
For the stickiness of the center item, handle touch events so that it will smooth scroll to the middle item, for example as shown on samsung's sample "circle launcher" .
For more fancy effects, make the size/location properties of the views change similar to the sample i've written about on #3 .
来源:https://stackoverflow.com/questions/8379261/make-carousel-with-viewflipper-or-viewpager