using gridview with images in android - java

this is the problematic code:
public class Level1 extends Activity {
int[] logos = {
R.drawable.arutz8,
R.drawable.channel1,
R.drawable.doctor_gav,
R.drawable.foxgroup3,
R.drawable.careline,
R.drawable.golfnew,
R.drawable.haaretz,
R.drawable.hafenix,
/*R.drawable.hando,
R.drawable.bankleumi,
R.drawable.jerusalempostred,
R.drawable.laisha,
R.drawable.logo,
R.drawable.logodelta,
R.drawable.maariv,
R.drawable.pelephone,
R.drawable.ravbariah,
R.drawable.renuar,
R.drawable.reshet_tv,
R.drawable.sano,
R.drawable.shilav,
R.drawable.sport5,
R.drawable.srigamish,
R.drawable.steimatzky,
R.drawable.superpharm,
R.drawable.supersal,
R.drawable.tambur,
R.drawable.tzometsfarim,
R.drawable.walla,
R.drawable.yediot,*/
};
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.level1);
ListAdapter adapter = (new ArrayAdapter<Integer>(this, R.layout.level1));
GridView grid = (GridView) findViewById(R.id.gridview1);
grid.setAdapter(new ImageAdapter(this));
}
private class ImageAdapter extends BaseAdapter
{
private Context context;
public ImageAdapter(Context c)
{
context = c;
}
//---returns the number of images---
public int getCount() {
return logos.length;
}
//---returns the ID of an item---
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
//---returns an ImageView view---
public View getView(int position, View convertView, ViewGroup parent)
{
ImageView imageView;
if (convertView == null) {
imageView = new ImageView(context);
imageView.setLayoutParams(new GridView.LayoutParams(90, 90));
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
imageView.setPadding(5, 5, 5, 5);
} else {
imageView = (ImageView) convertView;
}
imageView.setImageResource(logos[position]);
return imageView;
}
}
}
This program works perfectly as long as the size of all images is about 60px per each image. The problem in that size of image is that every image got constricted and its ugli!.
I tried to use in bigger images and for some reason only the first five images appears on the screen and when i try to load the rest images, the app crashes.
I thought that happens because of the size of the images but than i realized that all the images are in the same big size and still 5 of them were drawn on the screen.
Any ideas?
Those are the logs from logCat:
logs
and this is the result when i press on the level 1 button:
result

There is a problem in your public View getView(...) method in your ImageAdapter.
When the convertView == null, you never link the convertView to your imageView. So there will be a problem in the else-statement.
You can do this in two ways:
By defining your ImageView in code like you did, in your case this will be the best choice:
ImageView imageView = (ImageView) convertView;
if (convertView == null) {
convertView = new ImageView(context);
imageView = (ImageView) convertView;
// Set other parameters
}
// Set resource
return convertView;
By defining your layout in a xml-layout file an using a layout inflater:
Handler handler;
if (convertView == null) {
LayoutInflater li = (LayoutInflater) c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = li.inflate(yourLayoutResourceId, parent, false);
handler = new Handler();
handler.itemIV = (ImageView) convertView.findViewById(imageViewLayoutId);
convertView.setTag(handler);
} else {
handler = (Handler) convertView.getTag();
}
handler.imageView.setImageResource(...);
return convertView;
Where yourLayoutResourceId is the id of the created xml-layout file (R.layout.exmaple), and imageViewLayoutId is the id of your imaeView in the layout (R.id.exmapleIV).
As last step define an inner class Handler in your ImageAdapter:
class Handler {
ImageView imageView;
}
Good luck!
Have nice development.
Kr

Related

Load images in ImageView in ListView before they appear on screen

I am developing an app similar to what 9gag is doing.
https://play.google.com/store/apps/details?id=com.ninegag.android.app&hl=en
I have already implemented most of it but when I run the app the images that get loaded from the internet are not loaded in the ImageView until it comes on screen. I know that this is how ListView works with recycling but it doesnt seem smooth since i have to wait for each list item to load its image every time its shown on screen.
What do you suggest I could do to improve this issue?
My CustomAdapter class:
public class CustomAdapter extends BaseAdapter implements ResultsListener{
Context context;
Holder holder;
int postItemsLength=0;
ArrayList<PostItem> postItems;
PlaceholderFragment activity;
private static LayoutInflater inflater=null;
public CustomAdapter(PlaceholderFragment activity, ArrayList<PostItem> postItems) {
// TODO Auto-generated constructor stub
this.activity=activity;
this.context=activity.getContext();
this.postItems = postItems;
inflater = ( LayoutInflater )context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
Log.d("FOUND","entered constructor");
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return postItems.size();
}
#Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return position;
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
#Override
public void onResultsSucceeded(Bitmap image, int position) {
holder.img.setImageBitmap(image);
CustomAdapter.this.notifyDataSetChanged();
holder.progressBar.setVisibility(View.GONE);
}
public class Holder
{
TextView tv;
TextView imgName;
ImageView img;
WebView wView;
TextView likes;
TextView comments;
TextView op;
ProgressBar progressBar;
FrameLayout webViewLayout;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
final Holder holder;
Log.d("FOUND","entered GetView");
// Check if the item's view is recycled
if(convertView == null)
{
Log.d("FOUND","convertView is not null");
// The item's view doesn't exist
// Create the item's view
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
convertView = inflater.inflate(R.layout.list_item, parent, false);
holder = new Holder(); // Create the holder
holder.tv=(TextView) convertView.findViewById(R.id.titleTextView);
holder.img=(ImageView) convertView.findViewById(R.id.imageView);
holder.likes=(TextView) convertView.findViewById(R.id.likeNumTextView);
holder.comments=(TextView) convertView.findViewById(R.id.commentNumTextView);
holder.imgName = (TextView) convertView.findViewById(R.id.imageNameTextView);
holder.op=(TextView) convertView.findViewById(R.id.opTextView);
holder.webViewLayout = (FrameLayout) convertView.findViewById(R.id.webViewLayout);
holder.progressBar = (ProgressBar) convertView.findViewById(R.id.progressBar);
// Store the holder with the view.
convertView.setTag(holder);
}
else
{
// The item's view already exist
// Retrieve the older
holder = (Holder) convertView.getTag();
Log.d("FOUND","alreay exists");
}
holder.img.setImageResource(R.drawable.empty_img);
holder.tv.setText(postItems.get(position).getTitle());
holder.imgName.setText(postItems.get(position).getImageName());
holder.op.setText(postItems.get(position).getUploader());
holder.likes.setText(postItems.get(position).getLikeNum()+"");
holder.comments.setText(postItems.get(position).getCommentNum()+"");
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(getDpWidth(), adjustHeight(postItems.get(position).getWidth(), postItems.get(position).getHeight()));
holder.webViewLayout.setLayoutParams(lp);
DownloadImageTask dTask = new DownloadImageTask(holder.img);
dTask.setOnResultsListener(CustomAdapter.this);
dTask.execute("http://torifi.net/images/" + postItems.get(position).getImageName());
Log.d("FOUND","entered");
//holder.likes.setText(likeNum.get(position));
// holder.comments.setText(commentNum.get(position));
/*
convertView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO impl
}
});
*/
return convertView;
}
public int getDpWidth()
{
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
return Math.round(displayMetrics.widthPixels);// / displayMetrics.density);
}
public int adjustHeight (float imageWidth, float imageHeight)
{
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
float dpHeight = displayMetrics.heightPixels;// / displayMetrics.density;
float dpWidth = displayMetrics.widthPixels;// / displayMetrics.density;
return Math.round((imageHeight/imageWidth)*dpWidth);
}
}
Use Glide to load your images, which cache your images until their uri changes, and gives very fast and smooth loading experience.
you can load images as simple as following example.
ImageView imageView = (ImageView) findViewById(R.id.my_image_view);
Glide.with(this).load("image url").into(imageView);
I think the best solution is to seperate download and view creation.
You know the data to display in your ListView, so download the images onto the device (for example into the apps cache-dir like shown in this answer).
You don't have to eagerly download the images of all the ListViews entries. Just keep track of the users scrolling status and start downloading the next few images.
When initializing the ImageView set the Image-Source to your local file like shown in this answer.

Android different Row layout only for first row in BaseAdapter

I am making an Custom listview with Custom Adapter extending BaseAdapter. Now I want to set a different layout only for first row and another layout for all other rows. I am using this code but it sets the special layout for 1st row and also repeats it after every 5/6 rows. How can I fix it and can set it only for 1st row and another layout for all other rows.
public class NewsAdapter extends BaseAdapter {
private Context context;
List<News> newsList;
private Typeface customBanglaFont;
private LayoutInflater inflater;
ImageLoader imageLoader = AppController.getInstance().getImageLoader();
public NewsAdapter(Context context, List<News> newsList){
this.context = context;
this.newsList = newsList;
}
#Override
public int getCount() {
return newsList.size();
}
#Override
public Object getItem(int arg0) {
return newsList.get(arg0);
}
#Override
public long getItemId(int arg0) {
return arg0;
}
#Override
public View getView(int position, View convertView, ViewGroup viewGroup) {
View row;
row = convertView;
ViewHolder holder=null;
if(row == null){
if(position == 0){
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row =inflater.inflate(R.layout.row_single_big_view,viewGroup,false);
}
else{
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row =inflater.inflate(R.layout.row_single_default,viewGroup,false);
}
holder = new ViewHolder(row);
row.setTag(holder);
}
else{
holder = (ViewHolder) row.getTag();
}
if (imageLoader == null){
imageLoader = AppController.getInstance().getImageLoader();
}
final News news = newsList.get(position);
customBanglaFont = Typeface.createFromAsset(viewGroup.getContext().getAssets(), "fonts/SolaimanLipi.ttf");
holder.newsTitleView.setTypeface(customBanglaFont);
holder.newsTitleView.setText(news.getTitle());
holder.thumbNail.setImageUrl(news.getFeaturedImgSrc(), imageLoader);
return row;
}
}
/**
* Custom View Holder Class
* #author Tonmoy
*
*/
class ViewHolder{
TextView newsTitleView;
NetworkImageView thumbNail;
public ViewHolder(View v) {
// TODO Auto-generated constructor stub
newsTitleView = (TextView) v.findViewById(R.id.news_title);
thumbNail = (NetworkImageView) v.findViewById(R.id.news_image);
}
}
Why don't you use the Header functionality already built into ListView for this specific thing.
The docs:
http://developer.android.com/reference/android/widget/ListView.html#addHeaderView%28android.view.View,%20java.lang.Object,%20boolean%29
or a SO question:
Using ListView : How to add a header view?
your attempting is wrong. Your way you will be able to inflate just one layout. In fact, after the method returns the first time, convertView is not null. To fix quickly you could override getViewTypeCount and getItemViewType. This way you will get convertViews eqaul to the return value of getViewTypeCount, or you could just add the first item as header view for the ListView

ListView items reordering and repeating using baseadapter

I am trying to implement a listview that displays a list of directories. and under each directory is a gridview with associated adapter (shown below) showing a list of image thumbnails (see below image). I have it working great except whenever the list item is off the screen then brought back on screen, the images are reloaded. I am using an asynctask to download the thumbnails and replace the placeholder image for each imageview so it is not acceptable that everytime an item is offscreen, all of its thumbnails are downloaded again. Does anyone have an example of this type of implementation (gridview adapter within a listview adapter) where the imageview (or images) are stored? What is the proper way to do this?
Thanks in advance for your help.
Gallery Adapter
public class GalleryAdapter extends BaseAdapter {
private Context mContext;
ArrayList<GalleryItem> GalleryList;
//MediaAdapter adapter;
public GalleryAdapter(Context c,ArrayList<GalleryItem> l) {
mContext = c;
GalleryList = l;
}
public int getCount() {
return GalleryList.size();
}
public Object getItem(int position) {
return GalleryList.get(position);
}
public long getItemId(int position) {
return 0;
}
public View getView(int position, View convertView, ViewGroup parent) {
GalleryViewHolder viewHolder = null;
if(convertView==null){
// inflate the layout
LayoutInflater inflater = ((Activity) mContext).getLayoutInflater();
convertView = inflater.inflate(R.layout.gallery_item, parent, false);
viewHolder = new GalleryViewHolder();
viewHolder.title = (TextView) convertView.findViewById(R.id.title);
viewHolder.folder_settings = (ImageView) convertView.findViewById(R.id.folder_settings);
viewHolder.mediaGrid = (GridView) convertView.findViewById(R.id.imagegrid);
viewHolder.gridHolder = (LinearLayout) convertView.findViewById(R.id.gridholder);
convertView.setTag(viewHolder);
}
else{
viewHolder = (GalleryViewHolder) convertView.getTag();
}
viewHolder.title.setText(GalleryList.get(position).getTitle());
//Formatting the gridView to fit the screen dim.
ImageTools mWidth = new ImageTools(mContext);
viewHolder.mediaGrid.setColumnWidth(mWidth.imageSize());
int rows = (int) Math.ceil((GalleryList.get(position).getMedia().size() / mWidth.columnNumber)+1);
LinearLayout.LayoutParams labelLayoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, mWidth.imageSize()*rows);
viewHolder.gridHolder.setLayoutParams(labelLayoutParams);
viewHolder.mediaGrid.setLayoutParams(labelLayoutParams);
viewHolder.mediaGrid.setMinimumHeight(mWidth.imageSize()*rows);
//Set Adapter for image views
viewHolder.mediaGrid.setAdapter(new MediaAdapter(convertView.getContext(),GalleryList.get(position).getMedia()));
viewHolder.folder_settings.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Dialogs.createListDialog(mContext,"Folder Actions", R.array.gallery_action_array).show();
}
});
viewHolder.mediaGrid.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,int position, long id) {
}
});
return convertView;
}
private class GalleryViewHolder {
private TextView title;
private ArrayList<ImageView> imageList;
private GridView mediaGrid;
private ImageView folder_settings;
private LinearLayout gridHolder;
private int position;
}
}
Media Adapter
public class MediaAdapter extends BaseAdapter {
private Context mContext;
ArrayList<MediaItem> mediaitems;
public MediaAdapter(Context c,ArrayList<MediaItem> l) {
mContext = c;
mediaitems = l;
}
public int getCount() {
return mediaitems.size();
}
public Object getItem(int position) {
return mediaitems.get(position);
}
public long getItemId(int position) {
return 0;
}
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.setImageResource(R.drawable.loading);
imageView.setTag(R.integer.path,mediaitems.get(position).getPath().toString());
imageView.setTag(R.integer.fullsize,"false");
imageView.setTag(R.integer.parentpath,mediaitems.get(position).getParentPath().toString());
imageView.setTag(R.integer.index , String.valueOf(position));
try {
new thumbDownload(mContext).execute(imageView);
} catch (DbxException e) {
e.printStackTrace();
}
ImageTools mWidth = new ImageTools(mContext);
imageView.setLayoutParams(new GridView.LayoutParams(mWidth.imageSize(), mWidth.imageSize()));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
} else {
imageView = (ImageView) convertView;
}
//imageView.setImageBitmap(mediaitems.get(position).getBitmap());
return imageView;
}
}
Try with this..may be its silly way, but its worked for me. Just add a line of code inside your method like this for gallery adapter:
public View getView(int position, View convertView, ViewGroup parent) {
GalleryViewHolder viewHolder = null;
// Add this line.
convertView = null;
if(convertView==null){
// inflate the layout
LayoutInflater inflater = ((Activity) mContext).getLayoutInflater();
convertView = inflater.inflate(R.layout.gallery_item, parent, false);
viewHolder = new GalleryViewHolder();
viewHolder.title = (TextView) convertView.findViewById(R.id.title);
viewHolder.folder_settings = (ImageView) convertView.findViewById(R.id.folder_settings);
viewHolder.mediaGrid = (GridView) convertView.findViewById(R.id.imagegrid);
viewHolder.gridHolder = (LinearLayout) convertView.findViewById(R.id.gridholder);
convertView.setTag(viewHolder);
}
else{
viewHolder = (GalleryViewHolder) convertView.getTag();
}
// rest of your code
}
You can use StickyGridHeaders to implement your UI and Android-Universal-Image-Loader for flexible asynchronous image loading.
StickyGridHeaders is an Android library that provides a GridView that shows items in sections with headers. By default the section headers stick to the top like the People app in Android 4.x but this can be turned off.
Android-Universal-Image-Loader aims to provide a reusable instrument for asynchronous image loading, caching and displaying.
I ended up Using a HashMap<String,Bitmap> to store the images once they were downloaded. I made the hashMap static in my mediaAdapter so I could add the bitmap from my asynctask when it was downloaded. Then in my media Adapter getView(), I added a if statement to check if the image had already been downloaded. If it had, I used setImageBitmap(myHash.get(key)).

my images get shuffled or changed when i scroll in list view

my images get shuffled or changed when i scroll in list view.......
Images get shuffled when i scroll down and keep on changing own its own...............
public class CustomListAdapter extends BaseAdapter {
private ArrayList<NewsItem> listData;
private LayoutInflater layoutInflater;
public CustomListAdapter(Context context, ArrayList<NewsItem> listData) {
this.listData = listData;
layoutInflater = LayoutInflater.from(context);
}
#Override
public int getCount() {
return listData.size();
}
#Override
public Object getItem(int position) {
return listData.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = layoutInflater.inflate(R.layout.activity_list_search, null);
holder = new ViewHolder();
holder.headlineView = (TextView) convertView.findViewById(R.id.title);
holder.reporterNameView = (TextView) convertView.findViewById(R.id.reporter);
holder.reportedDateView = (TextView) convertView.findViewById(R.id.date);
holder.imageView = (ImageView) convertView.findViewById(R.id.thumbImage);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
NewsItem newsItem = (NewsItem) listData.get(position);
holder.headlineView.setText(newsItem.getHeadline());
holder.reporterNameView.setText("Model: " + newsItem.getReporterName());
holder.reportedDateView.setText(newsItem.getDate());
if (holder.imageView != null) {
new ImageDownloaderTask(holder.imageView).execute(newsItem.getUrl());
}
return convertView;
}
static class ViewHolder {
TextView headlineView;
TextView reporterNameView;
TextView reportedDateView;
ImageView imageView;
}
}
The problem is very generic for new Android developers.
Your ImageDownloaderTask should take care of whether the downloaded image should still be posted on screen.
For example, after ImageDownloaderTask finishes one image downloading task (e.g. for index 15), it should make sure the 15th item is still displaying on screen. Since ListView is reusing all the item views, if you directly set the bit map to the original referenced view, your imageview will be shuffled.

GridView CustomAdapter loads one imagebutton only

I have setup a custom gridView adapter, which looks like this
public class ImageAdapter extends BaseAdapter {
String[] urls = new String[10];
//....some code
class MyTask extends AsyncTask<Void,Void,Void>{
#Override
protected Void doInBackground(Void... arg0) {
//perform a get request and fill up the "urls" array by 10 values..
return null;
}
}
public View getView(int position, View convertView, ViewGroup parent) {
new MyTask().execute(); //execute AsyncTask
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View gridView = null;
if (convertView == null) {
gridView = new View(context);
// get layout from grid_layout.xml
gridView = inflater.inflate(R.layout.grid_layout, null);
final ImageButton grid_art = (ImageButton) gridView.findViewById(R.id.grid_art);
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context).build();
imageloader = ImageLoader.getInstance();
imageloader.init(config);
imageloader.loadImage(blog_urls[position], new SimpleImageLoadingListener() {
#Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
grid_art.setImageBitmap(loadedImage);
}
});
} else {
gridView = (View) convertView;
}
return gridView;
}
#Override
public int getCount() {
return urls.length;
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
the adapter loads 10 image url's in an asynctask and stores it into the urls array.
I am using universal image loader to download and load images found at the urls into an imagebutton as background,
however only one imagebutton gets the background and the rest are blank.
Change your getView method like this:
public View getView(int position, View convertView, ViewGroup parent) {
new MyTask().execute(); // execute AsyncTask
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
//View gridView = null;
MyView myView;
if (convertView == null) {
myView= new MyView();
//gridView = new View(context);
// get layout from grid_layout.xml
convertView = inflater.inflate(R.layout.grid_layout, null);
myView.grid_art = (ImageButton) convertView.findViewById(R.id.grid_art);
convertView.setTag(myView);
} else {
myView= (MyView) convertView.getTag();
//gridView = (View) convertView;
}
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(
context).build();
imageloader = ImageLoader.getInstance();
imageloader.init(config);
imageloader.loadImage(blog_urls[position],
new SimpleImageLoadingListener() {
#Override
public void onLoadingComplete(String imageUri, View view,
Bitmap loadedImage) {
myView.grid_art.setImageBitmap(loadedImage);
}
});
return convertView;
}
Where MyView is:
class MyView {
ImageButton grid_art;
}
Hope it helps...

Categories