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.
Related
I'm trying to make an app that takes videos and then displays the videos in a gridview. I have gotten to the point where all the video thumbnails are showing up in the gridview like they should. However, my problem is that the method I am using has a lot of lag time. It takes some time to get the gridview loaded and when I try to scroll there is always some sort of lag. This is most likely due to the fact that I'm using bit maps for every video thumbnail.
I was wondering what I could do to make this a lot quicker and smoother. My code is posted below.
class VideoAdapter extends BaseAdapter {
Context context;
ArrayList<String> videopathlist;
Bitmap bmthumb;
VideoAdapter(Context c, ArrayList<String> filepathlist){
context = c;
videopathlist = new ArrayList<String>();
this.videopathlist.addAll(filepathlist);
Log.i(TAG, "" + videopathlist);
}
#Override
public int getCount() {
return videopathlist.size();
}
#Override
public Object getItem(int position) {
return videopathlist.get(position);
}
#Override
public long getItemId(int arg0) {
return 0;
}
#Override
public View getView(int posiiton, View arg1, ViewGroup arg2) {
ImageView imageview = new ImageView(context);
bmthumb = ThumbnailUtils.createVideoThumbnail(videopathlist.get(posiiton), MediaStore.Video.Thumbnails.MINI_KIND);
if (bmthumb != null) {
Log.i(TAG1, "There is a thumbnail");
imageview.setImageBitmap(bmthumb);
} else {
Log.i(TAG1, "There is NOT a thumbnail");
}
imageview.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageview.setLayoutParams(new GridView.LayoutParams(160, 160));
return imageview;
}
Thanks for your help
2 things:
Use a ViewHolder to cache everything, as described here: Making ListView Scrolling Smooth (applies to GridViews too)
Also, use an ImageLoader to load images dynamically. There are many available or you can build your own. Here are some:
Volley
Android-Universal-Image-Loader
ImageLoader
All these loaders make use of Bitmap caches as described here: Caching Bitmaps
Also, you could potentially be actually creating the thumbnail bitmaps when returning the view. This strikes me as very expensive. I would do this as a seperate step, unrelated to displaying them. For example, kick off an AsyncTask when your activity is first created to generate any new thumbnails. Then in your adapter just query the MediaStore to get the generated thumbnails.
I am using the sample ImageAdpater provided in the google documentation to populate a gridview with drawables. What I'm trying to do is populate the gridview with an array of drawables in an xml file.
I use TypedArray imgs = getResources().obtainTypedArray(R.array.log_type_icons); to access the array from my main activity, but that doesn't work within the ImageAdapter class.
The array:
<string-array name="log_type_icons">
<item>#drawable/ic_launcher</item>
<item>#drawable/ic_headache</item>
<item>#drawable/ic_man</item>
<item>#drawable/ic_woman</item>
<item>#drawable/ic_kneel</item>
</string-array>
The working ImageAdapter:
public class ImageAdapter extends BaseAdapter {
private Context mContext;
public ImageAdapter(Context c) {
mContext = c;
}
public int getCount() {
return mThumbIds.length;
}
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;
Log.i("log tag", "gotten resources: " + mThumbIds);
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;
}
imageView.setImageResource(mThumbIds[position]);
return imageView;
}
// references to our images
private Integer[] mThumbIds = { R.drawable.ic_headache,
R.drawable.ic_kneel, R.drawable.ic_man, R.drawable.ic_woman,
R.drawable.ic_launcher };
}
I know I could manually add the drawable references to the Integer array, but I reference the xml array from my main activity as well, so it would be ideal to be able to add to the xml and not have to change the code.
Does anyone have any insight into this? Am I doing something wrong or missing Something obvious?
Any help would be appreciated,
Thank you
I ended up solving this problem by using 'getResources().obtainTypedArray(R.array.log_type_icons);' to get the array in my main activity, then passed it to the image adapter instead of using 'getResources()' within the adapter
I think this is the thread which is similar to your question. please check this.
Here they used custom array of drawables. you can try your resource drawable array in place of it
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"
I try to develop an Android App which allows the user to fetch data from flickr and show it in a GridView (with some nice 3D-Animation). After some adventures i got it almost running, but now I'm stuck.
Here's the problem:
I got a UI Thread "LoadPhotosTask" which gets the pictures from flickr, just like the open source application photostream. In the method onProgressUpdate(LoadedPhoto... value) of that subclass I call addPhoto(). Until now everythings fine - I got some nice Bitmap and Flickr.photo data with all the information I need.
#Override
public void onProgressUpdate(LoadedPhoto... value) {
addPhoto(value);
}
On the other hand I have got a GridView. Now I want to fill it with the Photos. It has got an adapter called ImageAdapter (which extends BaseAdapter, see this tutorial). If I use an array inside the ImageAdapter class I can populate the GridView with some sample images. But if I want to populate it at runtime, I don't know what to do.
How do I have to set up the getView method in the ImageAdapter? I was trying to fill the array inside the ImageAdapter class with my values in addPhoto, but it doesn't display anything.
So first of all I was setting up the array with the amount of Photos i wanted to display in the grid like that (code is inside the ImageAdapter class):
// class variable
private ImageView[] mThumbIds;
[...]
public void setupArray(int count) {
this.mThumbIds = new ImageView[count];
}
Then I call this method with the lenght of my photolist:
final Flickr.PhotoList list = params[0];
final int count = list.getCount();
int helper = 0;
imagead.setupArray(count);
Afterwards I call the getView method manually inside the addPhoto method:
private void addPhoto(LoadedPhoto... value) {
ImageView image = (ImageView) mInflater.inflate(
R.layout.grid_item_photo, null);
image.setImageBitmap(value[0].mBitmap);
image.setTag(value[0].mPhoto);
imagead.setmThumbIds(image, value[0].mPosition);
imagead.getView(value[0].mPosition, null, mpicturesGrid);
}
That is the getView method inside ImageAdapter:
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) { // if it's not recycled, initialize some
// attributes
imageView = new ImageView(mContext);
imageView.setLayoutParams(new GridView.LayoutParams(EDGE_LENGTH,
EDGE_LENGTH));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setPadding(0, 0, 0, 0);
imageView.setVisibility(View.VISIBLE);
} else {
imageView = (ImageView) convertView;
}
imageView.setImageDrawable(mThumbIds[position].getDrawable());
imageView.setTag(mThumbIds[position].getTag());
return imageView;
}
You are missing a key part.
When you use an Adapter you have a method called notifyDataSetChanged().
The logic you are missing there is the following:
When creating the Adapter for the GridView stay with a reference for the list that the adapter will use. Something like:
private ArrayList<Photo> mPhotos;
private BaseAdapter mAdapter;
private GridView mGridView;
onCreate:
/* other things here */
mAdapter = new MyAdapter(mPhotos);
mGridView.setAdapter(mAdapter);
What you addPhoto should do is the following:
mPhotos.add(photo);
mAdapter.notifyDataSetChanged();
That's it.
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.