I am building a forum-ish app, and need to display the forumposts in a hierarchical manner so that people can easily see which post are responding to (children of) which. Each forumpost has its own object, and this object contains an (int) depth variable which is intended to use for defining its position related to its parent.
I have a BroadcastReciever which takes in the data and sets a listadapter based on the data.
My plan was now to use getListAdapter().getChildAt(position).setLeft(pixels); method for each entry, however i get a nullpointerexception at the setLeft method. My code for this is:
#Override
public void onReceive(Context context, Intent intent) {
String jsonEmner = intent
.getStringExtra(RestService.PARAM_OUT_MSG);
emner = gson.fromJson(jsonEmner, EmneItem[].class);
Log.e(this.getClass().getSimpleName(), jsonEmner);
populateEmner();
int firstID = getListView().getFirstVisiblePosition();
int listSize = getListView().getCount();
for (int count = firstID; count < listSize; count++) {
EmneItem e = (EmneItem) getListView().getItemAtPosition(count);
getListView().getChildAt(count).setLeft(e.getDepth());
}
}
This code is inside the BroadCastReciever method inside the ListFragment class. I was hoping someone could point me in the right direction how to do this :)
I feel a bit stupid answering my own question, but I managed to find a workaround in case anyone gets in a similar situation.
I created my own custom ArrayAdapter, and an XML file which defines the layout for the rows. ArrayAdapter has a getView() method which lets you customize each entry, and based on my entries "depth" variable, i set the textviews LayoutParams.
In case anyone wants to see how its done:
class CustomAdapter extends ArrayAdapter<EmneItem> {
CustomAdapter() {
super(getActivity(), R.layout.row, emner);
}
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
//Reusing convertView if possible, if not then inflating a new
if(row == null) {
LayoutInflater inflater = getActivity().getLayoutInflater();
row = inflater.inflate(R.layout.row, parent, false);
}
TextView postedby = (TextView) row.findViewById(R.id.postedbytextview);
postedby.setText("Posted by: " + emner[position].getPosted_by());
TextView argument = (TextView) row.findViewById(R.id.argumentTextView);
argument.setText(emner[position].getArgument());
TextView procontratextview = (TextView) row.findViewById(R.id.procontratextview);
int procontra = emner[position].getProcontra();
if (procontra == EmneItem.PRO) {
procontratextview.setText("PRO");
}
if (procontra == EmneItem.CONTRA) {
procontratextview.setText("CONTRA");
}
LinearLayout.LayoutParams llp = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
if(emner[position].getDepth() == 1) {
llp.setMargins(10, 0, 0, 0);
procontratextview.setLayoutParams(llp);
argument.setLayoutParams(llp);
} else if (emner[position].getDepth() == 2) {
llp.setMargins(20, 0, 0, 0);
procontratextview.setLayoutParams(llp);
argument.setLayoutParams(llp);
} else if (emner[position].getDepth() == 3) {
llp.setMargins(30, 0, 0, 0);
procontratextview.setLayoutParams(llp);
argument.setLayoutParams(llp);
} else if (emner[position].getDepth() >= 4) {
llp.setMargins(40, 0, 0, 0);
procontratextview.setLayoutParams(llp);
argument.setLayoutParams(llp);
}
return (row);
}
}
This is mostly based on an article i found at http://commonsware.com/Android/excerpt.pdf
Cheers
Related
I'm very confusing with this.
Question is simple, I'm trying to resize the ImageView height, to do, I get the display width and add on it 0.25 of percentage.
Problem, if I set the new value of height outside of the post() ImageView method, the position parameter is deliver in getView() wrong. If I do it inside post() the first elements showed are not rescaled.
Read comments inside code.
public static class ViewHolder {
ImageView imgAvatar;
public void loadAvatar(SocialService socialService, long userId) {
try {
// SocialService.loadAvatar(..) is working with UniversalImageLoader.
socialService.loadAvatar(this.imgAvatar, userId, true, false);
} catch (Exception ex) {
Log.e("APPERROR", ex.getMessage());
}
}
}
#Override
public View getView(int position, View view, ViewGroup parent) {
ViewHolder holder;
final User user = this.users.get(position);
if (view == null) {
holder = new ViewHolder();
view = inflater.inflate(R.layout.adapter_list, parent, false);
holder.imgAvatar = (ImageView) view.findViewById(R.id.people_list_avatar);
// With this commented snippet of code, the first 4 elements (showed in the top of the listview) are not rescaled.
// Position is deliver ok.
// The rest of elements that are going showing while scrolling works pretty fine.
// If scroll down and come back to the top then the 4 top first elements are showing rescaled.
/*final ImageView imgAvatarAux = holder.imgAvatar;
holder.imgAvatar.post(new Runnable() {
#Override
public void run() {
imgAvatarAux.getLayoutParams().height =
(int) ((Display.deviceWidth(PeopleAdapter.this.context) / 2) * 1.25F);
}
});*/
view.setTag(holder);
// HERE IS THE QUESTION.
// If I remove this line of code, position is deliver ok, but if it works, position is deliver senseless. WHY?
holder.imgAvatar.getLayoutParams().height = (int) ((Display.deviceWidth(PeopleGridAdapter.this.context) / 2) * 1.25F);
holder.loadAvatar(this.socialService, user.getId());
}
holder = (ViewHolder) view.getTag();
...
if (position == 0) {
// An interface method for another purposes...
this.waitFinish.onFinish();
}
return view;
}
Post your ListView Item layout adapter_list. Code fix [operations on list items outside if(){}else{}]:
// HERE IS THE QUESTION.
// If I remove this line of code, position is deliver ok, but if it works, position is deliver senseless. WHY?
holder.imgAvatar.getLayoutParams().height = (int) ((Display.deviceWidth(PeopleGridAdapter.this.context) / 2) * 1.25F);
view.setTag(holder);
} else {
holder = (ViewHolder) view.getTag();
}
holder.loadAvatar(this.socialService, user.getId());
this is the code in my custom adapter (THE CODE IN BROWN COLOR) when initially list is build proper margin is applied to valid items when i scroll down and again scroll up all the rows in list shifts the margin left by 20 what i'm doing wrong please reply soon
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
// getting data
final ViewMovieDetailsModel_ViewComments movies = getItem(position);
if (convertView == null)
{
convertView = View.inflate(context, R.layout.comment_row, null);
holder = new ViewHolder();
//getting handles
holder.comments_linearLayout = (LinearLayout) convertView.findViewById(R.id.comments_linearLayout);
holder.commenter_textView = (TextView) convertView.findViewById(R.id.comment_row_commenter);
holder.commented_on_textView = (TextView) convertView.findViewById(R.id.comment_row_comment_time);
holder.comment_text_textView = (TextView) convertView.findViewById(R.id.comment_row_comment_text);
holder.reply_button = (Button) convertView.findViewById(R.id.comment_row_reply_button);
convertView.setTag(holder);
}
else
{
holder = (ViewHolder)convertView.getTag();
}
if (movies != null)
{
if (((movies.getParent_comment_id()).toString().equals("null")) && session.isLoggedIn()==true) {
holder.reply_button.setVisibility(View.VISIBLE);
}else{
holder.reply_button.setVisibility(View.INVISIBLE);
}
`if (!((movies.getParent_comment_id()).toString().equals("null")))
{
LayoutParams params = new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT);
params.setMargins(20, 0, 0, 0);
holder.comments_linearLayout.setLayoutParams(params);
}`
holder.commenter_textView.setText(movies.getUsername_commentor());
holder.commenter_textView.setTag(movies.getUser_id_commentor());
return convertView;
}
because you are setting margins (the brown font) in 'if' statement:
if (movies != null)
just take it out of this if block (for example put it just before the return point)
Right now this code is probably not executed at the first view load, since the movie is null. When the getView is called second time, the movie is not null, and the marigin is set according to your 'brown' code.
if this is not the solution - maybe the inside if statement condition is not true (the one that is in first 'brown' row). so.. your own logic prevents the marigins to be set as you want :)
Please let me know if it helps.
One way you could go about solving this problem is instead of using LayoutParams.setMargins(20, 0, 0, 0), you could create an empty TextView whose width is 20 dp by default and whose position will be to the left of your rows contents. It will be View.GONE by default, but when if (!((movies.getParent_comment_id()).toString().equals("null"))) happens, you can set that to View.VISIBLE
HI all,
I have this "search results" ListView.
The search results can be of different "kinds" (different sections, call it).
To separate the "kinds" I add a row with a title. (I know about the expandable list, but can't use it for other reasons).
In my getView(), I check for a property, and if it's set, I change the background color of the row.
The problem: when I run a query that returns just a few rows (say 15), everything is fine. But when I run another that returns, say 600 rows, something goes wacko and it changes the background randomly, at a somewhat regular interval. Same thing happens when I'm running in debug mode and stop things in the middle.
So, it's definitely a timing issue.
I'm thinking this might be due to having to re-render the big list as the on-screen keyboard closes.
So, is the Adapter to blame? Is there any solution for this?
If the keyboard is the problem, is there a mechanism to tell the list "wait until the thing closes" before start rendering? (Not sure I like that, but it's better than getting a cute little rainbow...)
Thanks!
Llappall
--
Here's the adapter and the element layout (below):
private class ElementAdapter extends ArrayAdapter<Element> {
private ArrayList<Element> rows;
private Element.typeEnum type;
public ElementAdapter(Context context, int textViewResourceId, ArrayList<Element> rows) {
super(context, textViewResourceId, rows);
this.rows = rows;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.element, null);
}
Element row = rows.get(position);
if (row == null) {
return v;
}
v.setTag(row);
type = row.getType();
boolean isSectionType = type == Element.typeEnum.DIV118SECTION || type == Element.typeEnum.APPASECT ||
type == Element.typeEnum.APPBSECT || type == Element.typeEnum.AZSECT;
TextView title = (TextView) v.findViewById(R.id.title);
TextView body = (TextView) v.findViewById(R.id.body);
if (isSectionType) {
body.setMaxLines(5000);
}
title.setText(row.getTitle());
if (row.getBody() != null) {
body.setText(row.getBody());
}
if (type == Element.typeEnum.SEARCHLISTHEADER) {
v.setBackgroundColor(Color.rgb(230, 230, 250));
title.setBackgroundColor(Color.rgb(230, 230, 250));
body.setBackgroundColor(Color.rgb(230, 230, 250));
star.setBackgroundColor(Color.rgb(230, 230, 250));
}
return v;
}
}
==ELEMENT LAYOUT==
<TextView
android:id="#+id/body"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
style="#style/ListItemSubTitle" />
</LinearLayout>
It would be much easier if you would post a getView() method here.
From what I can tell, you might be using recycled views wrong.
Check if background is changed to something if property is not set.
For example:
if (peoperty.isSet()) {
changeBackGround();
}
Just by itself will be wrong if you are reusing convertView, since the background will stay the same color how it was, when this view was used for a different row.
must be something like:
if (peoperty.isSet()) {
changeBackGround();
} else {
changeBackgroundToSomethingNeutral()
}
I took a liberty to rewrite that code for you, since you make too much weird stuff. Here's what I think is a optimized working code for your situation (didn't test any of it, but should work):
private class ElementAdapter extends ArrayAdapter<Element> {
public ElementAdapter(Context context, int textViewResourceId, ArrayList<Element> rows) {
super(context, textViewResourceId, rows);
this.rows = rows;
}
private final ArrayList<Element> rows;
#Override
public View getView(final int position, View convertView, final ViewGroup parent) {
ViewsHolder holder = null;
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.element, parent, false);
holder = new ViewsHolder();
holder.title = (TextView) v.findViewById(R.id.title);
holder.body = (TextView) v.findViewById(R.id.body);
convertView.setTag(holder);
} else {
holder = (ViewsHolder) convertView.getTag();
}
final Element row = rows.get(position);
final Element.typeEnum type = row.getType();
if (type.equals(Element.typeEnum.DIV118SECTION) || type.equals(Element.typeEnum.APPASECT) ||
type.equals(Element.typeEnum.APPBSECT) || type.equals(Element.typeEnum.AZSECT)) {
body.setMaxLines(5000);
}
holder.title.setText(row.getTitle());
if (row.getBody() != null) {
holder.body.setText(row.getBody());
} else {
holder.body.setText("");
}
if (type == Element.typeEnum.SEARCHLISTHEADER) {
convertView.setBackgroundColor(Color.rgb(230, 230, 250));
holder.title.setBackgroundColor(Color.rgb(230, 230, 250));
holder.body.setBackgroundColor(Color.rgb(230, 230, 250));
//star.setBackgroundColor(Color.rgb(230, 230, 250)); // Where did that come from?
}
return convertView;
}
private final class ViewsHolder {
public TextView title;
public TextView body;
}
}
Couple of notes on the original code:
if (row == null) {
return v;
}
is wrong. You shouldn't have any null elements in your list for any position in the list. Even if you have, you shouldn't just throw some random view for the row. What you are doing here, is returning "v", that can very well be (and probably will be) some recycled old row, that still displays old data, and that's going to confuse the user. I made an assumption that you won't have any empty elements when wrote the code.
if (row.getBody() != null) {
body.setText(row.getBody());
}
Is almost ok, but again, if you are reusing convertView (which is some random previous row that isn't displayed anymore), then if body is actually null you will just be displaying the old data, which again will confuse the user. If body is null, just set the string empty.
P.S.
I recommend you to watch this for tips and tricks about how to work with ListView: The world of ListView
I have a GridView which is pretty similar to the Google tutorial, except that I want to add the ImageViews on runtime (via a subactivity). The results are okay, but the layout of the View is messed up: The GridView doesn't fill the content of its parent, what do I have to do to design it properly?
Here the code of adding the children:
public void initializeWorkbench(GridView gv, Vector<String> items) {
Prototype.workbench.setDimension(screenWidth, divider.height()+workbenchArea.height());
Prototype.workbench.activateWorkbench();
// this measures the workbench correctly
Log.d(Prototype.TAG, "workbench width: "+Prototype.workbench.getMeasuredWidth());
// 320
Log.d(Prototype.TAG, "workbench height: "+Prototype.workbench.getMeasuredHeight());
// 30
ImageAdapter imgAdapter = new ImageAdapter(this.getContext(), items);
gv.setAdapter(imgAdapter);
gv.measure(screenWidth, screenHeight);
gv.requestLayout();
gv.forceLayout();
Log.d(Prototype.TAG, "gv width: "+gv.getMeasuredWidth());
// 22
Log.d(Prototype.TAG, "gv height: "+gv.getMeasuredHeight());
// 119
Prototype.workbench.setDimension(screenWidth, divider.height()+workbenchArea.height());
}
}
activateWorkbench, setDimension and measure in the workbench (LinearLayout above the GridView):
public void activateWorkbench() {
if(this.equals(Prototype.workbench)) {
this.setOrientation(VERTICAL);
show = true;
measure();
}
}
public void setDimension(int w, int h) {
width = w;
height = h;
this.setLayoutParams(new LinearLayout.LayoutParams(width, height));
this.invalidate();
}
private void measure() {
if (this.getOrientation() == LinearLayout.VERTICAL) {
int h = 0;
int w = 0;
this.measureChildren(0, 0);
for (int i = 0; i < this.getChildCount(); i++) {
View v = this.getChildAt(i);
h += v.getMeasuredHeight();
w = (w < v.getMeasuredWidth()) ? v.getMeasuredWidth() : w;
}
if (this.equals(Prototype.tagarea))
height = (h < height) ? height : h;
if (this.equals(Prototype.tagarea))
width = (w < width) ? width : w;
}
this.setMeasuredDimension(width, height);
}
The ImageAdapter constructor:
public ImageAdapter(Context c, Vector<String> items) {
mContext = c;
boolean mExternalStorageAvailable = false;
boolean mExternalStorageWriteable = false;
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
// We can read and write the media
mExternalStorageAvailable = mExternalStorageWriteable = true;
} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
// We can only read the media
mExternalStorageAvailable = true;
mExternalStorageWriteable = false;
} else {
// Something else is wrong. It may be one of many other states, but
// all we need
// to know is we can neither read nor write
mExternalStorageAvailable = mExternalStorageWriteable = false;
}
if (mExternalStorageAvailable && mExternalStorageWriteable) {
for (String item : items) {
File f = new File(item);
if (f.exists()) {
try {
FileInputStream fis = new FileInputStream(f);
Bitmap b = BitmapFactory.decodeStream(fis);
bitmaps.add(b);
files.add(f);
} catch (FileNotFoundException e) {
Log.e(Prototype.TAG, "", e);
}
}
}
}
}
And the xml layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:gravity="bottom"
android:paddingLeft="0px"
android:paddingTop="0px"
android:paddingRight="0px">
<com.unimelb.pt3.ui.TransparentPanel
android:id="#+id/workbench"
android:layout_width="fill_parent"
android:layout_height="10px"
android:paddingTop="0px"
android:paddingLeft="0px"
android:paddingBottom="0px"
android:paddingRight="0px">
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/gridview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:columnWidth="90dp"
android:numColumns="auto_fit"
android:verticalSpacing="10dp"
android:horizontalSpacing="10dp"
android:stretchMode="columnWidth"
android:gravity="center" />
</com.unimelb.pt3.ui.TransparentPanel>
</LinearLayout>
the GridView has an invalidateViews() method.
when you call this method: "all the views to be rebuilt and redrawn."
http://developer.android.com/reference/android/widget/GridView.html
i think this is what you need:)
You must, first tell the adapter to notify that the data has changed and set the adapter again to the grid
adapter.notifyDataChanged();
grid.setAdapter(adapter);
This may be helpful.
I refresh a gridview of book image thumbnails after a delete is executed on an item.
Using adapter.notifyDataChanged(); as mentioned above didn't work for me as it's called in my adapter.
//this is a call that retrieves cached data.
//your constructor can be designed and used without it.
final Object data = getLastNonConfigurationInstance();
I essentially just reload the adapter and bind it to the same view.
//reload the adapter
adapter = new BooksAdapter(MyBooks.this, MyBooks.this, data, show_collection );
grid.invalidateViews();
grid.setAdapter(adapter);
#flyerz #snagnever
Together you guys have got it. It should be:
adapter.notifyDataChanged();
grid.invalidateViews();
This will flag the adapter that its data has changed, which will then be propagated to the grid whenever after the invalidateViews() method is called.
Glad I found this question because I could not figure out how to add items to the grid after its been rendered.
None of these answers actually worked for me and I had to mash all of them together. To actually get the GridView to update, you need to do this:
adapter.notifyDataChanged();
grid.invalidateViews();
grid.setAdapter(adapter);
Hope this helps anyone who couldn't get the other solutions to work.
You should not call invalidateViews and setAdapter to refresh your grid view. This is not a good idea to keep your grid view updated, if you update in that way it would cost a lot of time and memory.
If you have a chance to look at getView method you will see that convertView is created just once. When you call notifyDataChanged, it will update this view. Whereas if you call invalidateViews, previously created views will be recreated. This is not a good solution.
Your getView method is called when you call notifyDataChanged. So your getView method should look something like the code below.
public List list;
public class SimpleItemViewHolder extends Object
{
public TextView textView;
public ImageView imageView;
}
public View getView(int position, View convertView, ViewGroup parent){
View itemView = convertView;
SimpleItemViewHolder viewHolder;
if(convertView==null)
{
viewHolder = (SimpleItemViewHolder)itemView.getTag();
}else{
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
itemView = inflater.inflate(R.layout.layout_name, null);
TextView labelField = (TextView) itemView.findViewById(R.id.label_field);
labelField.setText(list.get(position).Name);
//Typeface boldFont = Typeface.createFromAsset(context.getAssets(), "fonts/Font-Bold.ttf");
//labelField.setTypeface(boldFont);
ImageView imageView = (ImageView) itemView.findViewById(R.id.image_view);
//Bitmap bitmap = init your bitmap here;
//imageView.setImageBitmap(bitmap);
viewHolder = new SimpleItemViewHolder();
viewHolder.imageView = imageView;
viewHolder.textView = labelField;
itemView.setTag(viewHolder);
}
//don't create new views, instead use previous ones and update them.
viewHolder.textView.setText(list.get(position).Name);
//viewHolder.imageView.setImageBitmap(your_bitmap);
return itemView;
}
adapter.notifyDataChanged();
may not works just because data for the adapter is stale (if Activity or fragment was not destroyed and have been sitting in the back stack for instance).
So, if firstly refresh data, then after it will be working.
You are placing the GridView inside com.unimelb.pt3.ui.TransparentPanel which is 10px tall.
You shouldn't use px, you should use dp.
Change com.unimelb.pt3.ui.TransparentPanel's android:layout_height="10px" to android:layout_height="fill_parent"
In your adapter :
class MAdapter extends BaseAdapter{
List<Objects> mObjects;
...
public void clearAdapter(){
mObjects.clear();
}
public void addNewValues(List<Objects> mObjects){
this.mObjects = mObjects;
}
...
}
adapter.clearAdapter(); // clear old values
adapter.addNewValues(MObjects);
adapter.notifyDataChanged();
I have a listview with a custom arrayadapter that handles about 15 strings. The style of each row alternates (between labels and values for those labels--for example row 1 could be "email address" and row 2 would be the actual email address). I'm changing the style of each row to alternate like this in the arrayadapter's getView() method. So if the item at the current position is a label, I'll change the styling from the default row style (which is what the values have applied to them). When the listview first loads, the styling is perfect and just how I want it to be. If I scroll the list slowly up or down, it stays that way. However, if I scroll the list fast up and down, the styling of the value rows starts changing to that of the label ones until all of the rows have the styling of a label row. Does anyone know why this would be happening? I've used custom adapters on other listviews in the app with no problems like this.
Edit: Found out that it also changes all of the rows to the label styling on portrait->landscape orientation changes. Doesn't do this on landscape->portrait changes. Below is the adapter I'm using. Am I missing something?
public class DetailsAdapter extends ArrayAdapter<String> {
private TextView text = null;
private String item = null;
public DetailsAdapter(Context context, int resource, int textViewResourceId, String[] objects) {
super(context, resource, textViewResourceId, objects);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
text = (TextView) super.getView(position, convertView, parent);
item = getItem(position);
if (item.equals("Name") || item.equals("Mobile") || item.equals("Home") || item.equals("Email") || item.equals("Address")) {
text.setBackgroundColor(0xFF575757);
text.setTextSize(15);
text.setTypeface(null, Typeface.BOLD);
text.setPadding(8, 5, 0, 5);
} else {
text.setPadding(15, 15, 0, 15);
}
return text;
}
#Override
public boolean isEnabled(int position) {
item = getItem(position);
if (item.equals("Name") || item.equals("Mobile") || item.equals("Home") || item.equals("Email") || item.equals("Address")) {
return false;
} else {
return true;
}
}
}
Android reuses views fairly aggressively, and it is quite possible that a view that was used as an email address row gets reused on a row that's supposed to display a label, and vice-versa.
As a result, you cannot rely on "default" values. Set your padding, typeface, text size and background color in all cases:
if (item.equals("Name") || item.equals("Mobile") || item.equals("Home") || item.equals("Email") || item.equals("Address")) {
text.setBackgroundColor(0xFF575757);
text.setTextSize(15);
text.setTypeface(null, Typeface.BOLD);
text.setPadding(8, 5, 0, 5);
} else {
text.setBackgroundColor(DEFAULT_BACKGROUND);
text.setTextSize(DEFAULT_TEXT_SIZE);
text.setTypeface(null, DEFAULT_TYPEFACE);
text.setPadding(15, 15, 0, 15);
}
Don't need to do anything. I too faced the same problem and solved it like this:
Just inside the getView method add a first line
convertView=null;
It wont redraw the view immediately destroyed but instead would create new ones each time based on your logic (even odd or whatever)