I'm implementing a application that allows user to drag pages though a Gallery to read a newspaper.
I wrote a Adapter that returns ImageViews with some Bitmaps loaded on application.
My problem is, the first image shows perfectly, the next ones has a gray foreground that make the image looks darker. After dragging somewhere the first one also get this foreground. How can I avoid my views getting this foreground?
Now I realized that the ImageViews are getting some value on alpha channel, this is why together with my black background the images look darker. How can I avoid it?
As solicited, here it's my code:
Gallery view = new Gallery(context);
view.setSpacing(10);
view.setAdapter(new PageAdapter(context, pages));
LayoutParams params = new LayoutParams(600, 300);
layout.addView(view, params);
And the Page Adapter
private class PageAdapter extends ArrayAdapter {
private List pages;
public PageAdapter(Context c, List<Page> pages) {
super(c, 0);
this.pages = pages;
}
public View getView(int position, View convertView, ViewGroup parent) {
Page page = getItem(position);
ImageView image;
if (convertView != null)
image = (ImageView) convertView;
else
image = new ImageView(context);
image.setImageBitmap(ImageUtils.rgb(page.loadNormal()));
return image;
}
public int getCount() {
return pages.size();
}
public Page getItem(int position) {
return pages.get(position);
}
}
This ImageUtils.rgb was created to create a copy of any Bitmap into a Bitmap.RGB_586, but the same behaviour occurs.
You need to specify the unselectedAlpha property on the Gallery.
Either via your java (as per your example)
view.setUnselectedAlpha(1.0);
Of if you are using xml to declare the Gallery, add
android:unselectedAlpha="1.0"
Related
In my fragment, I have a ListView of items which contain some text and an image that takes the entire width of the screen. The images are loaded from a URL and I'm using Android-Universal-Image-Loader for that.
I'm using a custom adapter (extends BaseAdapter) and assigning it to the list this way:
public class MyAdapter extends BaseAdapter {
private LayoutInflater inflater;
private List<Offer> offers;
private Context context;
public MyAdapter(Context context, List<Offer> offers) {
super();
this.context = context;
this.inflater = LayoutInflater.from(context);
this.offers = offers;
}
#Override
public int getCount() {
return offers.size();
}
#Override
public Object getItem(int position) {
return offers.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final View view;
if (convertView == null) {
view = inflater.inflate(R.layout.offer_list_view, parent, false);
} else {
view = convertView;
}
final Offer offer = offers.get(position);
ImageView image = (ImageView) view.findViewById(R.id.offer_list_item_image);
MyImageLoader.getInstance(context).displayImage(offer.getImageUrl(), image); //load the image using the universal image loader
TextView offerTitle = (TextView) view.findViewById(R.id.offer_list_item_title);
offerTitle.setText(offer.getTitle());
return view;
}
}
Typically ~2.5 items fit to the screen height. When I scroll down the adpater's getView method is called and the next images are loaded. This isn't the nicest user behavior and I want more than 2-3 items to load every time.
For instance, I want that the itmes/images #3 & #4, that aren't visible at the beginning, will be loaded too so that when I scroll to it, they will already be there.
How can I extends the number of calls to getView so that items that aren't currently visible will be populated too?
That is what the adapter does , it loads only the visile items and recycles these views again and again .. the universal image loader has a cache mechanism ,, so one workaround would be if you ,, load all the images in a for loop once after setting the adapter , your problem will be solved ,,,!!!!.. (obviously the images will apear only after they have been fetched ..so it will obviously take as much time it takes to fetch and display those images , but if once they have been from internet , the next time universal image loader loads them from ur local sd card ,,which will happen instantly ,,,,make sure u have permissions to write to sd card while using universal image loader )
try using memory and/or disk caching, the image will be downloaded only the first time you scroll to a row. this will make scrolling very smooth
DisplayImageOptions displayDefaultOptions = new DisplayImageOptions.Builder()
.cacheInMemory(true).cacheOnDisc(true).considerExifParams(true)
.build();
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)
.threadPriority(Thread.NORM_PRIORITY - 2).denyCacheImageMultipleSizesInMemory()
.defaultDisplayImageOptions(displayDefaultOptions)
.discCacheFileNameGenerator(new Md5FileNameGenerator())
.build();
ImageLoader.getInstance().init(config);
I have a gridview which displays two column imageviews. I am loading these images with an async task (see this post Lazy load of images in ListView )
But when i am scrolling gridview , the images in positions are mixing. For example 14th image shows 1th image , i think view is trying to show old image before async task finishes.
My code :
public Content getItem(int position) {
return contents.get(position);
}
public long getItemId(int position) {
return position;
}
#Override
public boolean hasStableIds() { return true; }
public View getView(int position, View convertView, ViewGroup parent) {
Thumbnail contentView;
Content current = contents.get(position);
if (convertView == null) {
contentView = new Thumbnail(mContext);
}
else {
contentView = (Thumbnail) convertView;
}
contentView.title = current.getTitle();
contentView.image = current.getImage();
contentView.link = current.getLink();
contentView.init();
return contentView;
}
Init function
TextView titleText = (TextView)super.findViewById(R.id.titleText);
titleText.setText(title);
ImageView imageControl = (ImageView)super.findViewById(R.id.thumbImage);
DrawableManager loadImage = new DrawableManager(); loadImage.fetchDrawableOnThread(imgUrl, imageControl);
Waiting for your help
Thanks
It happens because of resource reusing. What you should do:
First, just set some kind of default image to your imageView (contentView.image.setImageResource(DEFAULT_RESOURCE)) inside getView method (transitional default picture is better than wrong one).
Set unique tag to your image, for example, position or url of image to load (contentView.image.setTag(url)).
When AsyncTask finishes, you can use some checks like
String url=(String)imageView.getTag();
if (url.equals(mUrl)) { //mUrl can be transmitted to AsyncTask instance separately
mActivity.runOnUiThread(new Runnable() {
#Override
public void run() {
imageView.setImageDrawable(bmp);
});
});
}
It's needed because Adapter does not allocate memory for all N ImageView for N items. It stores just required amount for visible items and some reserved ImageViews. So there is no warranty that ImageView reference that you store will be actual within several seconds cause it can became invisible and be reused by visible ones.
Don't load images yourself. Use Universal Image Loader . It can cache, images and loaded bitmaps. Making your problem go away. It also supports showing stub images and automatic pause on scrolling and so on.
It solves your specic problems by only loading an image for the last instance of an imageView if you reuse it.
imageLoader.displayImage(imageUri, imageView);
Is all that is needed to asynchronously load an image.
I'm looking for some advice on how to do this.
I want to have an activity where the user select from android gallery, then the image will be added into a grid view on the activity. I have successfully implemented both separately, but when I have to combine them I'm at a loss. Grid View tutorial is here. Problem is that grid view tutorial uses images from res/drawable, so the uri i obtain from gallery doesn't exactly work.
How should I set the image inside the ImageAdapter class? I've been trying to do imageView.setImageBitmap(bitmap) with the uri address of one of the images in my phone, but it didn't work.
I'm thinking of creating an ArrayList of String that contains uri for the images obtained from the gallery. This way i can add, delete, and store the images with ease.
Other questions along with this is that if i get the images displayed, will it refresh if i simply call setAdapter again? would delete work automatically if i delete from the source ArrayList?
Thank you
The following is the code from grid view tut that i edited:
public class ImageAdapter extends BaseAdapter {
private Context mContext;
public ImageAdapter(Context c) {
mContext = c;
}
public int getCount() {
return imageId.size();
}
public Object getItem(int position) {
return null;
}
public long getItemId(int position) {
return 0;
}
// create a new ImageView for each item referenced by the Adapter
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
if (convertView == null) { // if it's not recycled, initialize some attributes
imageView = new ImageView(mContext);
imageView.setLayoutParams(new GridView.LayoutParams(85, 85));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setPadding(8, 8, 8, 8);
} else {
imageView = (ImageView) convertView;
}
Uri targetUri = Uri.parse(tests.get(0));
//tests contains the uri of the photo i'm trying to import from my phone gallery in string form
Bitmap bitmap;
bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(targetUri));
imageView.setImageBitmap(bitmap);
return imageView;
}
}
Answer to the first part : If your tests contains the Uri of the image that you have selected, simply use imageView.setImageURI(targetUri).
Answer to second part : To refresh a GridView, just call mGridView.invalidateViews() and your whole GridView will be redrawn and thus any changes that have taken place in your source would be reflected here. No need to call setAdapter() again. setAdapter() will be called only once initially, when you are drawing the grid for the first time. After that, just invalidateViews() to refresh it.
I have a gallery in my android application when I clicked on gallery item I want to display image and grid view. I done when i have only three images in gallery and in click it displayed correctly. But now I have seven images in gallery and each gallery item there are four images to display gallery.In this I m using array of drwawable images only.In this time I got an exception as Java.lang.OutOfMemory
I use below code
public ImageThemeAdapter(Context c, Integer[] mImageIds) {
imagesId=mImageIds;
bitmap=new Bitmap[imagesId.length];
mContext = c;
TypedArray ta=obtainStyledAttributes(R.styleable.Gallery1);
imageBackground=ta.getResourceId(R.styleable.Gallery1_android_galleryItemBackground, 1);
ta.recycle();
for (int i = 0; i <imagesId.length; i++) {
bitmap[i]=BitmapFactory.decodeResource(mContext.getResources(),imagesId[i]);
}
}
public int getCount() {
return bitmap.length;
}
public Object getItem(int position) {
return bitmap[position];
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
ImageView i = new ImageView(mContext);
i.setImageBitmap(bitmap[position]);
i.setScaleType(ImageView.ScaleType.FIT_XY);
i.setLayoutParams(new Gallery.LayoutParams(130, 120));
// i.setLayoutParams(new Gallery.LayoutParams((ScreenWidth*80)/100, android.view.ViewGroup.LayoutParams.WRAP_CONTENT));
i.setBackgroundResource(imageBackground);
return i;
}
please provide any suggestions. Thanks in advance.
I have have a requirement like this
Please repeat the steps using Allocation Tracker(Windows -> Shows View -> Other -> Android -> Allocation Tracker) and find out the memory allocation to different objects.
The main reason could be due the layout of custom view as you are creating GridView and at runtime you will be creating thumbinals of images of gallery. we might have to create a gridview with minimum number of images available at one time.
Folks -
I'm trying to implement a Gallery widget that displays an ArrayList of images, and I have started with the Hello, Gallery example on the dev site. This part is all working great.
I need to have the gallery display an empty view (a special view when the ArrayList has no contents), but I cannot seem to get the Gallery to do this. I have done this with ListView and other AdapterViews in the past, but I cannot get it to work with Gallery. What do I need to override/implement in the Adapter, Gallery, or both to get an empty view displayed? This is my adapter code:
public class ImageAdapter extends BaseAdapter {
int mGalleryItemBackground;
private Context mContext;
private ArrayList<Drawable> images;
public ImageAdapter(Context c) {
mContext = c;
TypedArray a = c.obtainStyledAttributes(R.styleable.Gallery1);
mGalleryItemBackground = a.getResourceId(R.styleable.Gallery1_android_galleryItemBackground, 0);
a.recycle();
images = new ArrayList<Drawable>();
}
public void addImage(Drawable d) {
images.add(d);
}
public boolean isEmpty() {
return getCount() == 0;
}
public int getCount() {
return images.size();
}
public Drawable getItem(int position) {
return images.get(position);
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View contentView, ViewGroup parent) {
ImageView i = new ImageView(mContext);
i.setImageDrawable(images.get(position));
i.setLayoutParams(new Gallery.LayoutParams(160, 120));
i.setScaleType(ImageView.ScaleType.FIT_XY);
i.setBackgroundResource(mGalleryItemBackground);
return i;
}
}
When the view is to be displayed with an empty ArrayList, getCount() does get called (returning 0), but the Gallery never checks isEmpty, and when I had defined getEmptyView() in the Gallery, it was never called either. Did I miss another required method in BaseAdapter to properly notify the empty state?
Thanks!
With the assistance of this article, I found the answer:
Correct use of setEmtpyView in AdapterView
The key to the issue was that (once I got the Gallery/AdapterView to properly call the empty status check using the addendum information) AdapterView is designed only to switch the View visibility settings between the content and empty views (swapping View.GONE and View.VISIBLE). Therefore, if you didn't do the legwork of properly creating and laying out both the content and empty views in the parent layout, they will not display properly.
In may case, I had created the empty view programmatically (just a TextView) and used setEmptyView() to attach it to the adapter view. The TextView was never attached to the LinearLayout that represented the Activity, so it didn't show up even after the AdapterView so kindly set it View.VISIBLE.