I have got a Gridview in my app. I then added a OnItemLongClickListener to that GridView. Check out this code:
myGridView.setOnItemLongClickListener(new OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view,
int position, long id) {
view.setBackgroundResource(R.drawable.image_border);
return true;
}
});
Now, all I want to do is set a border to an image in my gridview. The problem with my code is that it sets the border to an image but when I start scrolling up and down, suddenly an other image has got the border although it was never clicked.
How come that the border gets set to other images as well. Any idea how I can fix this?
Your Adapter class does this internally to reduce memory consumption and to efficiently use device resources.
In your Adapter class you should do
public View getView (int position, View convertView, ViewGroup parent){
// convertView is reused from previously scrolled out view to reduce memory consumption
if( convertView == null ){
//We must create a View:
convertView = inflater.inflate(R.layout.my_list_item, parent, false);
}
// Set border to the image if it is selected otherwise set it to default
// keep in mind when you add any condition here, else should also be addressed
return convertView;
}
Related
What I'm trying to do is to have all the rows in the listview translate to the right in order to expose a checkbox for multi-selection. And actually it works ok beside this:
the animation on the visible rows is ok, but there are like 2-3 rows, created in advance (before starting to recycle them) so the scroll is smooth, in which the translation starts when those become visible (onscreen).
I know this is normal behaviour but could there be any way to have those rows translated before they become onscreen? I was thinking of something like setting the translation time to those to 1 but can't know where the returned view will be used by the list.
public View getView(int position, View convertView, ViewGroup viewGroup) {
View view = convertView;
if (view == null) {
view = LayoutInflater.from(context).inflate(R.layout.item_conversation, null);
}
final AQuery aq = new AQuery(view);
// multiSelect
if(multiSelect) {
aq.id(R.id.row);
if((int) aq.getView().getX() == 0) {
animate(aq.getView())
.translationX(marginLeftWhenMultiSelect)
.setDuration(300);
}
} else {...
I have listview with hundred of items. Every item had a couple of LinearLayouts but ONE of them is Visibility.GONE! Every item has textviews and an image. On Image Click i want to set the LinearLayout with visibility.Gone to View.VISIBLE. It works fine until you scroll down the listview, then every 4th item has the same layout set to VISIBLE but i only need the Clicked one! Here is the getView method:
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ImageView imgForClick;
View vi = convertView;
if (convertView == null)
vi = inflater.inflate(R.layout.custom_row, null);
final LinearLayout hiddenLayout = (LinearLayout)vi.findViewById(R.id.hiddenLayout);
imgForClick = (ImageView)vi.findViewById(R.id.imageView3);
imgForClick.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
hiddenLayout.setVisibility(View.VISIBLE);
}
});
return vi;
}
That's because you are recycling the views, so the layout gets changed on a click and then that layout is used in your other rows to save memory.
You need to remember the state of each of the rows to know whether or not the layout should be visible or not
Have something like this:
public View getView(final int position, View convertView, ViewGroup parent) {
...
if (shouldBeVisible.get(position)) {
hiddenLayout.setVisibility(View.VISIBLE);
} else {
hiddenLayout.setVisibility(View.GONE);
}
That way the layout will always be set one way or another.
shouldBeVisible is a List of something that lets you know which rows should have that layout visible or not.
EDIT--
An alternative is to remove view recycling, however this will dramatically hurt performance and should NOT be done, but I'm just explaining to list all your options.
You would remove the line
if (convertView == null)
Making Android always inflate a new view, instead of using the recycled one when possible.
I am making an android gallery. I want to be able to extend it's basic behavior so the view that its centered to be most visible (it's alpha value to be 1.0) and the views that are from the left and to the right to have some minimum visibility which will increase if the user scrolls and positions a particular view in the center.
I am wondering if someone has done this before, or has an idea how I should try and do this.
I haven't done this, but did something similar utilizing data from the central item in the gallery. What I did was simply create my own adapter
YourAdapter extends BaseAdapter{...}
Now you can set a externel listener or have the adapter listen to the gallery
//listen for user events on Gallery
gallery.setOnItemSelectedListener(YourAdapter);
in the adapter create these functions
public void onItemSelected(AdapterView<?> parent, View v, int position, long id) {
selectedItem = position;
}
public View getView(int position, View convertView, ViewGroup parent) {
//change according if selected or not
if(position == selectedItem)
//set the alpha for selected
else
//set the alpha for other items
}
I am developing an application in which I have to show ratings depending on the values that I am receiving after parsing the XML response in listview. I have implemented it using the Custom Adapter and showing the images in the getView() method like :
String rating = Constants.menuRatingList.get(position);
if (rating.equals("1")) {
rateImg1.setImageResource(R.drawable.stary);
}
The problem is when I scroll the down to the last item and again move upwards, it is redrawing the list row.
Someone please suggest me approach to stop the redrawing the list row and set the image value permanently.
How do you create the rateImg1 variable?
Maybe you should get it from the view that is passed to the getView() method?
Something like this:
public View getView(int position, View view, ViewGroup parent) {
if (view == null) {
view = LayoutInflater.from(ctx).inflate(R.layout.my_layout, parent, false);
}
((ImageView) view.findViewById(R.id.my_image)).setImageResource(R.drawable.some_drawable);
return view;
}
Also you can implement getViewTypeCount() and getItemViewType() and check them in the above method not to redraw the same image if it is already set.
Can someone explain this issue to me ?
I have a listview that holds more rows than the screen can show, so scrolling.
If I click on one item, I replace an icon that is part of each row. That all works.
The issue I have is that when I click on lets say the first item, I change the icon for that first row. When I now scroll down I see that the first row outside the visible viewport also changed the icon.
Why is that happening and how can I avoid this issue ?
Thanks in advance,
Mozzak
Just to make sure, you are using a class that implements ListAdapter or extends some other sort of adapter right?
When using an adapter, you will have to keep in mind that the views in the ListView are recycled to save memory. Because of this, you will need to store the state in a separate variable.
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null)
{
LayoutInflater inflator = (LayoutInflater)parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflator.inflate(R.layout.listitem, null);
}
// Retreive my image that may or may not change
ImageView myIcon = (ImageView) convertView.findViewById(R.id.iconView);
// Checking my stored boolean for this position to see if I need to use icon2 or icon
if (myItem[position].needsIconChanged)
{
// I have set my boolean, so use icon2
myIcon.setImageResource(R.drawable.icon2);
}
else
{
// I have not set my boolean, or set it to false so set it to icon
myIcon.setImageResource(R.drawable.icon);
}
return convertView;
}
You will also have to remember to set that boolean in your onItemCLick
public void onItemClick(AdapterView<?> myAdapter, View myView, int position, long arg3) {
// Retreive your item and set a boolean or icon state (depending on what you do)
myAdapter.getItemAtPosition(position).needsIconChanged = true;
}