I have a problem by selecting CheckBoxes in my ListItems. Each ListItem has a CheckBox in it's layout and when the ListItem is clicked the CheckBox should be activated. The problem is that the CheckBoxes are randomly activated. For example: When i have 2 ListItems and click on ListItem1, it's CheckBox is activated. When i click again, CheckBox of ListItem2 is activated, too. When i click again, CheckBox of ListItem1 is deactivated. When i click again, CheckBox of ListItem2 is deactivated. When i click again it all starts from the beginning. I understand ListView reuses the Items and that i have to use getView() method, but i just can't make it work. I have to mention that I'm a bloody beginner, so please forgive me if some code doesn't make sense at all.
You need to create a Custom Array Adapter and all set.
Here is the Activity Class I created for ListView for ChekBoxList
ActivityGamesList.java
package com.rdc.gameListApp;
import java.util.List;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.CheckBox;
import android.widget.ListView;
import android.widget.Toast;
public class ActivityGamesList extends Activity {
private ListView listGames = null;
private DBAdapter database = null;
private Context context = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.list_of_games);
final CheckBox favBox = (CheckBox) findViewById(R.id.favbuttonInList);
listGames = (ListView) findViewById(R.id.listViewGame);
context = getApplicationContext();
database = new DBAdapter(context);
//here I am getting the data from database and putting in to List
List<String> gamelistArrayR = database.selectAllName();
// custom adapter for adding fav box
//make sure here "gamelistArrayR" is List and type is String
listGames.setAdapter(new CustomAdapter(this, gamelistArrayR));
//listener for list view
listGames.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Toast.makeText(getApplicationContext(), "You have selected: " +
position+" no row", Toast.LENGTH_SHORT).show();
}
});
}
}
and below is the Custom Array Adapter
CustomAdapter.java
package com.rdc.gameListApp;
import java.util.List;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.TextView;
import android.widget.Toast;
public class CustomAdapter extends ArrayAdapter<String> {
private final Context context;
private final List<String> values;
public CustomAdapter(Context context, List<String> gamelistArrayR) {
super(context, R.layout.list_row_custom, gamelistArrayR);
this.context = context;
this.values = gamelistArrayR;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.list_row_custom, parent, false);
//Game Name Text in list
TextView textView = (TextView) rowView.findViewById(R.id.txtGameNameInList);
// Check Box in list
CheckBox favBox = (CheckBox) rowView.findViewById(R.id.favbuttonInList);
textView.setText(values.get(position));
//listener for check box
favBox
.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) {
Boolean flag = isChecked;
if(flag){
Log.v("Debug", "step no 1");
Toast.makeText(context, "Marked as Favorite Game!", 1).show();
}
}
});
return rowView;
}
}
and i got the output like this way..
Edit:
When you scroll list, the chekboxrs gets uncheked because or recreate view.
so you need to store the state of checkbox for that you should check below links
this So thread or
this tutorial
Try using setOnItemSelectedListener instead of setOnItemClickListener . I believe the click event is getting invoked more often that you need.
You need to store the item states in your Adapter, not in the View itself, because it could be a reused one, just like you say. Your call to super.getView() will fill in the correct text for you, but not change the checkbox state. Keep a bool array reflecting the state of each checkbox, and in getView() apply the state before returning your view:
CheckBox cb = (CheckBox) view.findViewById(R.id.cb);
cb.setChecked(cbStates[position]);
Related
New android programmer is here.
First : I dont know many things about list view and as I found out , its complicated to work with it.
So , I want to put my database data (Contains Id , Name) to a listview and get the Id of the item is clicked.
I have searched many but i just found this :
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
public class test extends Activity {
String[] wordlist = new String[] { "a", "b", "c" };
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
wordlist[2] = "abds";
ListView list = new ListView(this);
list.setAdapter((ListAdapter) new MyAdapter(test.this, wordlist));
list.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
Object entry= parent.getItemAtPosition(position);
Toast.makeText(test.this, entry.toString(), Toast.LENGTH_SHORT).show();
}
});
setContentView(list);
}
private class MyAdapter extends ArrayAdapter<String> {
public MyAdapter(Context context, String[] strings) {
super(context, -1, -1, strings);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LinearLayout listLayout = new LinearLayout(test.this);
listLayout.setLayoutParams(new AbsListView.LayoutParams(AbsListView.LayoutParams.WRAP_CONTENT,
AbsListView.LayoutParams.WRAP_CONTENT));
listLayout.setId(5000);
TextView listText = new TextView(test.this);
listText.setId(5001);
listLayout.addView(listText);
listText.setText(super.getItem(position));
return listLayout;
}
}
}
Just i can show strings , not Id.
Use SimpleCursorAdapter to populate ListView with data from database, for example - https://thinkandroid.wordpress.com/2010/01/09/simplecursoradapters-and-listviews/ (first link from google).
How to get the item id in an onItemClick handler
Read more about ListView and Adapters, your code is awful )
I have made a custom View which contains an ImageView, a TextView and a delete Button.
I want to reset the particular View when I click the delete Button associated with it.
Please tell how to implement this.
Here is my MainActivity.java
package com.khurana.nikhil.list1;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends ActionBarActivity {
ListView lv;
TextView tv1, tv2;
View v1;
public String[] s = {"nikhil", "mukul", "kunal"};
public int[] img = {R.drawable.rty, R.drawable.sf, R.drawable.rty};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView lv = (ListView) findViewById(R.id.listView);
CustomAdapter cad = new CustomAdapter(MainActivity.this, s, img);
lv.setAdapter(cad);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener()
{
public void onItemClick(AdapterView<?> parent,View v,int position,long id)
{
Toast.makeText(MainActivity.this,"You clicked "+s[position],Toast.LENGTH_SHORT).show();
}
});
}
}
Here is CustomAdapter.java
package com.khurana.nikhil.list1;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
public class CustomAdapter extends ArrayAdapter<String>{
Context c1;
String s1[];
int s2[];
CustomAdapter(Context c,String s[],int s3[])
{
super(c,R.layout.tcustom,s);
this.c1=c;
this.s1=s;
this.s2=s3;
}
public View getView(int position,View v,ViewGroup parent)
{
LayoutInflater li=(LayoutInflater) c1.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v=li.inflate(R.layout.tcustom,null);
TextView tv=(TextView)v.findViewById(R.id.textView);
ImageView im=(ImageView)v.findViewById(R.id.imageview);
tv.setText(s1[position]);
im.setImageResource(s2[position]);
Button bt=(Button)v.findViewById(R.id.button);
return v;
}
}
((LinearLayout)yourView.getParent()).removeView(yourView);
or you can call from the layout directly
yourRelativeLayout.removeView(yourView)
I would recommend to use an ArrayList instead of a String[] in your Adapter class. It makes it a lot easier to delete or edit a View and the associated data behind it. I used this post to convert your String[] to an ArrayList, delete the item and convert back to String[].
This should work on button click:
In your Adapter class:
public View getView(int position,View v,ViewGroup parent)
{
LayoutInflater li=(LayoutInflater) c1.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v=li.inflate(R.layout.tcustom,null);
TextView tv=(TextView)v.findViewById(R.id.textView);
ImageView im=(ImageView)v.findViewById(R.id.imageview);
tv.setText(s1[position]);
im.setImageResource(s2[position]);
Button bt=(Button)v.findViewById(R.id.button);
bt.setTag(position); //important so we know which item to delete on button click
bt.setOnClickListener(new View.OnClickListener() {
public void onClick(View v)
{
int positionToRemove = v.getTag(); //get the position of the view to delete stored in the tag
removeItem(positionToRemove); //remove the item
}
});
return v;
}
public void removeItem(int position){
//convert array to ArrayList, delete item and convert back to array
ArrayList<String> a = new ArrayList<>(Arrays.asList(s1));
a.remove(i);
strings = new String[a.size()];
s1= a.toArray(strings);
notifyDataSetChanged(); //refresh your listview based on new data
}
#Override
public int getCount() {
return s1.length;
}
#Override
public String getItem(int position) {
return s1[position];
}
View visibility to GONE will not delete your view from memory as well. Please be specific, do you want to retain your view for future?
If you are working in a listview you should call notifyDataSetChanged() the adapter. your getView() method can be like:
action on button can be like this
Button bt=(Button)v.findViewById(R.id.button);
bt.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
s1 = ArrayUtils.remove(s1, position);
s2 = ArrayUtils.remove(s2, position);
notifyDataSetChanged();
}
});
If you want the view to disappear:
yourView.setVisibility(View.GONE);
EDIT: To get the parent view of the button: Android: Making changes to a button's parent view
I need help on how I list my data in the ListView alphabetical. If I add more data to foldeData it would be nice if I didn't have to manually move the existing data in order to list them alphabetical.
I have copied part of the code from MainActivity:
import java.util.concurrent.TimeUnit;
import android.support.v7.app.ActionBarActivity;
import com.google.android.gms.ads.*;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.os.Build;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Toast;
public class MainActivity extends ActionBarActivity implements OnClickListener {
TextView minPastaTimer, maxPastaTimer, tv_start, tv_stop, choice;
int minTid, maxTid;
private ListView listViewArticles;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
Folder[] folderData = new Folder[4];
folderData[0] = new Folder(R.drawable.icon_music_folder, "Acomo Pepe", (getString(R.string.acomo_pepe)), "Kogetid 9-10min");
folderData[1] = new Folder(R.drawable.icon_music_folder, "Bucatini", (getString(R.string.Bucatini)),"Kogetid 9-10min");
folderData[2] = new Folder(R.drawable.icon_music_folder, "Bumbola", (getString(R.string.Bumbola)),"Kogetid 9-10min");
folderData[3] = new Folder(R.drawable.icon_music_folder, "Cannelloni", (getString(R.string.Cannelloni)),"Kogetid 9-10min");
FolderAdapter adapter = new FolderAdapter(this,
R.layout.listview_item_row, folderData);
listViewArticles = (ListView) findViewById(R.id.listView1);
listViewArticles.setAdapter(adapter);
minPastaTimer = (TextView) findViewById(R.id.minPastaTimer);
minPastaTimer.setText("00:00:00");
maxPastaTimer = (TextView) findViewById(R.id.maxPastaTimer);
choice = (TextView) findViewById(R.id.tv_choice);
maxPastaTimer.setText("00:00:00");
Button btn_italy = (Button) findViewById(R.id.btn_italy);
Button btn_danish = (Button) findViewById(R.id.btn_danish);
tv_start = (TextView) findViewById(R.id.tv_start);
tv_start.setOnClickListener(this);
tv_stop = (TextView) findViewById(R.id.tv_stop);
tv_stop.setOnClickListener(this);
listViewArticles.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
String listItemText = ((TextView) view
.findViewById(R.id.textViewFolderName))
.getText()
.toString();
Toast.makeText(MainActivity.this,
"You clicked: " + listItemText, Toast.LENGTH_LONG)
.show();
if (listItemText.equals("Acomo Pepe")){
minTid=10000;
maxTid=20000;
choice.setText("Acomo Pepe: " + (getString(R.string.acomo_pepe)));
minPastaTimer.setText("00:08:00");
maxPastaTimer.setText("00:09:00");
}
else if (listItemText.equals("Bucatini")){
minTid=540000;
maxTid=600000;
choice.setText("Bucatini - Kogetid: " + (minTid/60/1000) + ("-") +(maxTid/60/1000) + ("min"));
minPastaTimer.setText("00:09:00");
maxPastaTimer.setText("00:10:00");
}
else if (listItemText.equals("Bumbola")){
minTid=15000;
maxTid=30000;
minPastaTimer.setText("00:10:00");
maxPastaTimer.setText("00:11:00");
}
else if (listItemText.equals("Cannelloni")){
minTid=15000;
maxTid=30000;
minPastaTimer.setText("00:11:00");
maxPastaTimer.setText("00:12:00");
}
}
});
FolderAdapter:
import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
public class FolderAdapter extends ArrayAdapter<Folder> {
Context mContext;
int layoutResourceId;
Folder data[] = null;
// #mContext - app context
// #layoutResourceId - the listview_item_row.xml
// #data - the ListItem data
public FolderAdapter(Context mContext, int layoutResourceId, Folder[] data) {
super(mContext, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.mContext = mContext;
this.data = data;
}
// #We'll overried the getView method which is called for every ListItem we have.
// #There are lots of different caching techniques for Android ListView to
// achieve better performace especially if you are going to have a very long ListView.
// #convertView - the cache of list item row layout, if it is null, inflate new
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView==null){
// inflate the listview_item_row.xml parent
LayoutInflater inflater = ((Activity) mContext).getLayoutInflater();
convertView = inflater.inflate(layoutResourceId, parent, false);
}
// get the elements in the layout
ImageView imageViewFolderIcon = (ImageView) convertView.findViewById(R.id.imageViewFolderIcon);
TextView textViewFolderName = (TextView) convertView.findViewById(R.id.textViewFolderName);
TextView textViewFolderDescription = (TextView) convertView.findViewById(R.id.textViewFolderDescription);
TextView textViewFolderBoilTime = (TextView) convertView.findViewById(R.id.textViewFolderBoilTime);
// Set the data for the list item. You can also set tags here if you want.
Folder folder = data[position];
imageViewFolderIcon.setImageResource(folder.folderIcon);
textViewFolderName.setText(folder.folderName);
textViewFolderDescription.setText(folder.folderDescription);
textViewFolderBoilTime.setText(folder.folderBoilTime);
return convertView;
}
}
I think best practice would be sorting the list before the calling adaptor.notifyDataChanged() method. Good thing is you do not have to do it manually, just use comparator for sorting.
You can see a comparator example in this link
Instead of using an array as datasource for the list, first use a List. At least, this class extends Collection.
You can define a comparator (e.g define compareTo() on your custom type) and sort your collection before you show it:
Collections.sort(<your_list>);
EDIT: For general collection ordering, see Guava
I learned that in order to modify row in a listView I need to gain access eg via adapter.getItem(position) but I have no idea how to work this around. Should I post any code please let me know.
Here is my EditListItemDialog file:
package com.example.classorganizer;
import java.util.ArrayList;
import java.util.List;
import com.example.classorganizer.Monday.DiaryAdapter;
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
class EditListItemDialog extends Dialog implements View.OnClickListener {
private View editText;
private DiaryAdapter adapter;
// public EditListItemDialog(Context context, List<String> fragment_monday) { //first constructor
// super(context);
// this.fragment_monday = fragment_monday;
// }
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.edit_text_dialog);//here is your xml with EditText and 'Ok' and 'Cancel' buttons
View btnOk = findViewById(R.id.button_ok);
editText = findViewById(R.id.edit_text);
btnOk.setOnClickListener(this);
}
private List<String> fragment_monday;
public EditListItemDialog(Context context, DiaryAdapter adapter) {
super(context);
this.fragment_monday = new ArrayList<String>();
this.adapter = adapter;
}
#Override
public void onClick(View v) {
fragment_monday.add(((TextView) v).getText().toString());//here is your updated(or not updated) text
adapter.notifyDataSetChanged();
dismiss();
}
}
You will have to implement an OnItemClickListener which will be able to tell you what item has been clicked. For example:
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//Position is the number of the item clicked
//You can use your adapter to modify the item
adapter.getItem(position); //Will return the clicked item
}
See the official Android documentation for more information.
package com.example.classorganizer;
import java.util.ArrayList;
import java.util.List;
import com.example.classorganizer.Monday.DiaryAdapter;
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
public class EditListItemDialog extends Activity {
ListView listView ;
private View editText;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.edit_text_dialog);
View btnOk = findViewById(R.id.button_ok);
editText = findViewById(R.id.edit_text);
btnOk.setOnClickListener(this);
listView = (ListView) findViewById(R.id.list)
String[] values = new String[] { "Automotive", "Banking", "Consumer Electronics",
"Education", "HealthCare and Life Sciences","Industrial Automation","Printing and
Imaging","Manufacturing","Media and
Entertainment","Networking","Retail","Telecom"
};
// Define a new Adapter
// First parameter - Context
// Second parameter - Layout for the row
// Third parameter - ID of the TextView to which the data is written
// Forth - the Array of data
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_expandable_list_item_1, values);
// Assign adapter to ListView
listView.setAdapter(adapter);
}
}
Use This code for simple Listview..
Following is some test code , done to recreate a strange bug: After deleting some items from a ListView , it stops refreshing when data is invalidated. More items are deleted but list does not refresh. Even Log cat does not show debug messages for deletion. I will appreciate if any one could find out what's wrong.
Item Layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal">
<TextView android:id="#+id/nameTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<Button android:id="#+id/deleteButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Delete"
/>
</LinearLayout>
Item class:
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class Item implements View.OnClickListener {
private String name;
private View itemView;
private MyActivity owner;
//--- getters--
public String getName() {
return name;
}
public View getView() {
return itemView;
}
public Item(String n, Context c , MyActivity o)
{
//---store the name given--
name = n;
//---store reference to the owner activity--
owner = o;
//--- create a View for this item----
LayoutInflater inflater = (LayoutInflater) c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
itemView = inflater.inflate(R.layout.item,null);
//---set up data to show--
TextView nameTextView = (TextView) itemView.findViewById(R.id.nameTextView);
Button deleteButton = (Button) itemView.findViewById(R.id.deleteButton);
nameTextView.setText(name);
//---set up events to be handled--
deleteButton.setOnClickListener(this);
Log.d("My_Test","Item: Hello world, my name is " + name);
}
//----request owner to delete this item---
#Override
public void onClick(View view) {
Log.d("My_Test","Item:"+name+" requesting owner to delete me");
owner.deleteItem(this);
}
Activity layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<ListView android:id="#+id/myListView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</LinearLayout>
Activity class:
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import java.util.ArrayList;
public class MyActivity extends Activity {
private ArrayList<Item> myItems;
private ListView myListView;
private ArrayAdapter<Item> myArrayAdapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//-----adapter for item list----
//----since each item has its own view , it just returns the same---
myArrayAdapter = new ArrayAdapter<Item>(this,0){
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
Item item = getItem(position);
Log.d("My_Test","Adapter : View for Item: " + item.getName() +"is requested." );
return item.getView();
}
};
//-----set up my list view with the adapter------
myListView = (ListView) findViewById(R.id.myListView);
myListView.setAdapter(myArrayAdapter);
//------add items-------
//----each item has its own view and a reference to this activity as their owner----
myArrayAdapter.add(new Item("Sunday", this, this));
myArrayAdapter.add(new Item("Monday", this, this));
myArrayAdapter.add(new Item("Tuesday", this, this));
myArrayAdapter.add(new Item("Wednesday", this, this));
myArrayAdapter.add(new Item("Thursday", this, this));
myArrayAdapter.add(new Item("Friday", this, this));
myArrayAdapter.add(new Item("Saturday", this, this));
myArrayAdapter.notifyDataSetChanged();
}
//----- called by items requesting to be deleted from the item list----
public void deleteItem(Item item) {
myArrayAdapter.remove(item);
Log.d("My_Test","Owner : Deleted item :" + item.getName());
myArrayAdapter.notifyDataSetChanged();
}
}
Looks like ListView stops re-drawing it self. Even when List Item is no more in the item array, and myAdapter.notifyDataSetInvalidated(); is called, The List Item stays visible , with further code execution some how blocked.
Use an ArrayAdapter to do this. Try something like this instead...
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
public class MyActivity extends Activity{
private ListView myListView;
private ArrayAdapter<Item> myArrayAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
myArrayAdapter = new ArrayAdapter<Item>(this,R.layout.item){
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View returnedView = convertView;
//inflate your view here
if(returnedView == null){
LayoutInflater inflater = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
returnedView = inflater.inflate(R.layout.item,null);
}
final Item item = getItem(position);
//set the views
if(returnedView != null){
TextView nameTextView = (TextView) returnedView.findViewById(R.id.nameTextView);
nameTextView.setText(item.getName());
Button deleteButton = (Button) returnedView.findViewById(R.id.deleteButton);
deleteButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
remove(item);
notifyDataSetChanged();
}
});
}
return returnedView;
}
};
myArrayAdapter.add(new Item("Sunday"));
myArrayAdapter.add(new Item("Monday"));
myArrayAdapter.add(new Item("Tuesday"));
myArrayAdapter.add(new Item("Wednesday"));
myArrayAdapter.add(new Item("Thursday"));
myArrayAdapter.add(new Item("Friday"));
myArrayAdapter.add(new Item("Saturday"));
myListView = (ListView) findViewById(R.id.myListView);
myListView.setAdapter(myArrayAdapter);
}
}
public class Item{
private String name;
public Item(String n){
this.name = n;
}
public String getName() {
return name;
}
}
Looking inside the working of ListViews and ListAdapters, I came to know there's a lot of recycling of objects, specifically List View Item Objects which adapters produce. Here are the lessons learnt along with solution to Original problem:
When a ListView has to draw/show a list item, it requests a View from ListAdapter, and some times (NOT ALWAYS) also provides an old View object to reuse. This reuse of objects is there so as to increase performance,there's an in built Re-Cycler in ListView to do this, why inflate new layouts for each new list item, when there are already some whose properties can be modified so that they look like the new view item. Until this point , its OK for adapter to change some text on old views and give them back, or create new ones if no recycled views are available, or even discard recyclable views and always create new one.
However, If your List Item's state is more than just some text in a TextView , that is, another object is registered as an onClickListener for your list item, or your list item has a reference to some object somewhere and vice-verca; it is NOT OK for adapter to just change appearance of the reusable Views or simply discard them. Adapter has to update entire state of a reusable item. that includes de-registering old event listeners, re-registering new ones and updating all reference to external objects that may be there.
Changed getView() method for adapter to:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
Item item = getItem(position);
Log.d("My_Test","Adapter : View for Item: " + item.getName() +"is requested." );
if(convertView != null)
{
(convertView.findViewById(R.id.deleteButton))
.setOnClickListener(item);
((TextView)convertView.findViewById(R.id.nameTextView))
.setText(item.getName());
return convertView;
}
else
{
return item.getView();
}
}
NOTE: While always creating new items in this case does not cause any errors, the ListView fails to detect changes and redraw. Making use of recycled items seems to solve this.