Reputation: 99
I have been searching around and tried out solutions for almost a day but nothing worked, so I decide to post my code here and hope someone can give me some help, thanks!
I have a fragment which extends ListFragment.
The list has four items; For the bottom three, I just set their pictures and text in the getView()
method in my private ListAdapter class
. For the first one, I want to continuously change its picture. I have an array, promotion_image_array
, of Bitmap which contains three Bitmap I will use as the source for the first item. The following is the code of my getView()
and a screenshot of what I got right now:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
View myView = convertView;
System.out.println("in getView");
if (myView == null) {
myView = inflater.inflate(R.layout.home_category_item, null);
holder = new ViewHolder();
holder.item_image= (ImageView)myView.findViewById(R.id.item_image);
holder.res_name = (TextView)myView.findViewById(R.id.res_name);
if(position == 0){
holder.res_name.setVisibility(View.GONE);
promotion_image_view = holder.item_image;
System.out.println("position == 0");
}
else if(position == 1) {
holder.res_name.setText("Food");
holder.item_image.setBackgroundResource(R.drawable.restaurant_icon);
System.out.println("position == 1");
}
else if(position == 2) {
holder.res_name.setText("Shop");
holder.item_image.setBackgroundResource(R.drawable.shop_icon);
System.out.println("position == 2");
}
else if(position == 3) {
holder.res_name.setText("Groupon");
holder.item_image.setBackgroundResource(R.drawable.groupon_icon);
System.out.println("position == 3");
}
myView.setTag(holder);
}
else {
// View recycled, no need to inflate
holder = (ViewHolder) myView.getTag();
}
return myView;
}
}
I tried to use a handler and a runnable to continuously update the image of the first item in my onCreate() method of my fragment. I have a static variable promotion_image_view which I declared at the top of my fragment and I use this line of code to get the actual ImageView of the first item in my getView() method:(from the code piece above)
promotion_image_view = holder.item_image;
And then I tried to set promotion_image_view's background in my runnable's run() method, the following is the code of my runnable and handler in onCreate():
counter = 0;
mHandler = new MyHandler(this);
runnable = new Runnable() {
@Override
public void run() {
mHandler.postDelayed(runnable,3000);
// Repeatedly display three promotion images
Bitmap[] promotion_image_array = my_global_variables.city_config_object.config_promotion_image_array;
BitmapDrawable ob = new BitmapDrawable(my_resources, promotion_image_array[counter]);
if(promotion_image_view != null) {
promotion_image_view.setBackground(ob);
System.out.println("promotion_image_view != null");
}
System.out.format("in run: counter = %d%n", counter);
counter++;
if(counter == 3) counter = 0;
}
};
runnable.run();
Both promotion_image_view != null
and
in run: counter = %d%n
, counter
got printed out properly(continuously printed out at a constant rate) and counter's value is correct, too.(0,1,2,0,1,2,0.....). But the picture did not change at all.
I would really appreciate any help, thank you!!
******************************* AFTER READ SOME ANSWERS --- FIRST EDIT *******************************
Thanks for the people who answered, I tried the notifyDataSetChanged() method, but it is still not working; the image is not changed, but the printout looks correct.
The following is the revised code:
getView() method:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
View myView = convertView;
if (myView == null) {
myView = inflater.inflate(R.layout.home_category_item, null);
holder = new ViewHolder();
holder.item_image= (ImageView)myView.findViewById(R.id.item_image);
holder.res_name = (TextView)myView.findViewById(R.id.res_name);
if(position == 0){
holder.res_name.setVisibility(View.GONE);
Bitmap[] promotion_image_array = my_global_variables.city_config_object.config_promotion_image_array;
BitmapDrawable ob = new BitmapDrawable(my_resources, promotion_image_array[counter]);
holder.item_image.setBackground(ob);
System.out.format("in run: counter = %d%n", counter);
counter++;
if(counter == 3) counter = 0;
System.out.println("in getView: position == 0");
}
else if(position == 1) {
holder.res_name.setText("Food");
holder.item_image.setBackgroundResource(R.drawable.restaurant_icon);
System.out.println("position == 1");
}
else if(position == 2) {
holder.res_name.setText("Shop");
holder.item_image.setBackgroundResource(R.drawable.shop_icon);
System.out.println("position == 2");
}
else if(position == 3) {
holder.res_name.setText("Groupon");
holder.item_image.setBackgroundResource(R.drawable.groupon_icon);
System.out.println("position == 3");
}
myView.setTag(holder);
}
else {
// View recycled, no need to inflate
holder = (ViewHolder) myView.getTag();
}
return myView;
}
}
handler and runnable:
counter = 0;
mHandler = new MyHandler(this);
runnable = new Runnable() {
@Override
public void run() {
mHandler.postDelayed(runnable, 3000);
adapter.notifyDataSetChanged();
}
};
runnable.run();
And the following is the print out which looks correct to me:
I/System.out﹕ in run: counter = 0
I/System.out﹕ in getView: position == 0
I/System.out﹕ position == 1
I/System.out﹕ position == 2
I/System.out﹕ position == 3
I/System.out﹕ in run: counter = 1
I/System.out﹕ in getView: position == 0
I/System.out﹕ in run: counter = 2
I/System.out﹕ in getView: position == 0
I/System.out﹕ in run: counter = 0
I/System.out﹕ in getView: position == 0
I/System.out﹕ in run: counter = 1
I/System.out﹕ in getView: position == 0
I/System.out﹕ in run: counter = 2
I/System.out﹕ in getView: position == 0
I/System.out﹕ in run: counter = 0
I/System.out﹕ in getView: position == 0
Upvotes: 0
Views: 792
Reputation: 3497
Using a static variable "promotion_image_view " is not a good idea.
Beacuse, android listview recycles it's own listiem. See below:
https://stackoverflow.com/a/14108676/850347
Instead, how about use image slideshow library?
https://github.com/daimajia/AndroidImageSlider
Or, you can change your real data (not the generated data in the getView) and call notifyDataSetChanged() method like this.
runOnUiThread(new Runnable() {
@Override
public void run() {
notifyDataSetChanged();
}
});
Edit1:
The point is: if (myView == null)
You are updating your imageView, only if it is null.
So, how about move that code to outside of null check code?
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
View myView = convertView;
if (myView == null) {
myView = inflater.inflate(R.layout.home_category_item, null);
holder = new ViewHolder();
holder.item_image = (ImageView) myView.findViewById(R.id.item_image);
holder.res_name = (TextView) myView.findViewById(R.id.res_name);
} else {
// View recycled, no need to inflate
holder = (ViewHolder) myView.getTag();
}
if (position == 0) {
holder.res_name.setVisibility(View.GONE);
Bitmap[] promotion_image_array = my_global_variables.city_config_object.config_promotion_image_array;
BitmapDrawable ob = new BitmapDrawable(my_resources, promotion_image_array[counter]);
holder.item_image.setBackground(ob);
System.out.format("in run: counter = %d%n", counter);
System.out.println("in getView: position == 0");
counter = counter++ % 3;
} else if (position == 1) {
holder.res_name.setText("Food");
holder.item_image.setBackgroundResource(R.drawable.restaurant_icon);
System.out.println("position == 1");
} else if (position == 2) {
holder.res_name.setText("Shop");
holder.item_image.setBackgroundResource(R.drawable.shop_icon);
System.out.println("position == 2");
} else if (position == 3) {
holder.res_name.setText("Groupon");
holder.item_image.setBackgroundResource(R.drawable.groupon_icon);
System.out.println("position == 3");
}
myView.setTag(holder);
return myView;
}
Upvotes: 1