How to write the code that can pass data from one lisview to another listview like if i select BMW from the car brand list i will be able to choose a particular car series that in a listview
main.XML
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10dp"
android:textSize="20sp" >
</TextView>
CarActivity.JAVA
package car.brand.test;
package car.brand.test;
import android.app.ListActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
public class CarActivity extends ListActivity {
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
String[] values = new String[] { "BMW", "Mercedes","Nissan"};
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, values);
setListAdapter(adapter);
}
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
String item = (String) getListAdapter().getItem(position);
Toast.makeText(this, item + " selected", Toast.LENGTH_LONG).show();
}
}
You don't need to pass data to another ListView, only one ListView is needed to achieve what you desire. You will have to do the mapping yourself, i.e. BMW maps to a list(java.util.ArrayList) that contains all BMW car series models, and Mercedes maps to a list that contains all Mercedes car series models, etc.
When you select a car brand, you swap the underlying dataset for the ListView and call notifyDataSetChanged().
snippet:
MyAdapter myAdapter = ...;
Map<String, List<String>> carSeriesMap = ...;
protected void onListItemClick(ListView l, View v, int position, long id) {
String brand = (String) getListAdapter().getItem(position);
List<String> carSeriesList = carSeriesMap.get(brand);
// set carSeriesList as the underlying dataset for the adapter
myAdapter.setDataset(carSeriesList);
}
class MyAdapter extends BaseAdapter {
List<String> dataset;
public void setDataset (List<String> newDataset) {
dataset = newDataset;
notifyDataSetChanged();
}
public View getView(int position, ......) {
// get data from dataset
String text = dataset.get(position);
// other code here...
}
}
Related
while i am searching for examples to make list of answers in expandable list i found code which use 4 java classes and one xml with expand list but not use xml for parent and child and i want to change text color and check box color
XML
<Spinner
android:id="#+id/coursescomplaint"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:layout_margin="2dp"
android:layout_gravity="center"
android:spinnerMode="dialog"
style="#style/spinner_style"/>
<ExpandableListView
android:id="#+id/expandcomplaintcourse"
android:layout_height="wrap_content"
android:layout_width="match_parent"/>
<Button
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="#color/Button"
android:text="Submit"
android:layout_gravity="center"/>
JAVA
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ExpandableListView;
import android.widget.Spinner;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Complaint extends AppCompatActivity implements AdapterView.OnItemSelectedListener {
private static List<Answers> questions;
private ExpandableListView expandableListView;
private AnswersAdabter adapter;
private int lastExpandedPosition = -1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_complaint);
LoadQuestions();
expandableListView = (ExpandableListView)findViewById(R.id.expandcomplaintcourse);
adapter = new AnswersAdabter(this, questions);
expandableListView.setAdapter(adapter);
// The choice mode has been moved from list view to adapter in order
// to not extend the class ExpansibleListView
adapter.setChoiceMode(AnswersAdabter.CHOICE_MODE_SINGLE_PER_GROUP);
// Handle the click when the user clicks an any child
expandableListView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
#Override
public boolean onChildClick(ExpandableListView parent, View v,
int groupPosition, int childPosition, long id) {
adapter.setClicked(groupPosition, childPosition);
return false;
}
});
expandableListView.setOnGroupExpandListener(new ExpandableListView.OnGroupExpandListener() {
#Override
public void onGroupExpand(int groupPosition) {
if (lastExpandedPosition != -1 && groupPosition != lastExpandedPosition) {
expandableListView.collapseGroup(lastExpandedPosition);
}
lastExpandedPosition = groupPosition;
}
});
// Spinner element
Spinner spinner = (Spinner) findViewById(R.id.coursescomplaint);
// Spinner click listener
spinner.setOnItemSelectedListener(this);
// Spinner Drop down elements
List<String> categories = new ArrayList<String>();
categories.add("Course1");
categories.add("Course2");
categories.add("Course3");
// Creating adapter for spinner
ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(this, R.layout.spinner, categories);
// Drop down layout style - list view with radio button
dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
// attaching data adapter to spinner
spinner.setAdapter(dataAdapter);
}
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
// On selecting a spinner item
String item = parent.getItemAtPosition(position).toString();
// Showing selected spinner item
Toast.makeText(parent.getContext(), "Selected: " + item, Toast.LENGTH_LONG).show();
}
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
}
private void LoadQuestions() {
questions = new ArrayList<Answers>();
ArrayList<String> citiesAustralia = new ArrayList<String>(
Arrays.asList("Brisbane", "Hobart", "Melbourne", "Sydney"));
questions.add(new Answers("Australia", citiesAustralia));
ArrayList<String> citiesChina = new ArrayList<String>(
Arrays.asList("Beijing", "Chuzhou", "Dongguan", "Shangzhou"));
questions.add(new Answers("China", citiesChina));
ArrayList<String> citiesIndia = new ArrayList<String>(
Arrays.asList("Bombay", "Calcutta", "Delhi", "Madras"));
questions.add(new Answers("India", citiesIndia));
ArrayList<String> citiesNewZealand = new ArrayList<String>(
Arrays.asList("Auckland", "Christchurch", "Wellington"));
questions.add(new Answers("New Zealand", citiesNewZealand));
ArrayList<String> citiesRussia = new ArrayList<String>(
Arrays.asList("Moscow", "Kursk", "Novosibirsk", "Saint Petersburg"));
questions.add(new Answers("Russia", citiesRussia));
}
}
I am making an app in which i want to show some quotes and sayings in a list view and i want to Display each Quote in new layout File when user click on any item in ListView item.This my code for Main Activity with simple listview:-
import android.os.Bundle;
import android.app.Activity;
import android.widget.ArrayAdapter;
import android.widget.ListView;
public class ListActivity extends Activity {
private String[] quoteArray = { "Quote1", "Quote2", "Quote3", "Quote4", "Quote5" };
private ListView quoteListView;
private ArrayAdapter arrayAdapter;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list);
quoteListView = (ListView) findViewById(R.id.months_list);
// this-The current activity context.
// Second param is the resource Id for list layout row item
// Third param is input array
arrayAdapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, quoteArray);
quoteListView.setAdapter(arrayAdapter);
}
}
Add an onItemClickListener():
quoteListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//there you start new Activity
//you can choose quote by using position paramter
}
});
I have 2 listviews in 1 activity (1 on the left 1 on the right of screen). I want 2 strings extracted from both list views and use them else where in the code (either in the same activity but different class or different activity). I have tried assigning clicked items to a public variable and then posting them on a text view bit I see nothing. Please help or suggest another better way. Here is a sample of my code:
public class Tabs extends Activity {
String CF =""; //Convert To
String CT =""; //Convert From
populateListView(); //function that populates my listview (not shown here)
ListView listMassFrom = (ListView) findViewById(R.id.ListViewMassFrom);
ListView listMassTo = (ListView) findViewById(R.id.ListViewMassTo);
listMassFrom.setOnItemClickListener(new AdapterView.OnItemClickListener(){
#Override
public void onItemClick(AdapterView<?> parent, View viewClicked, int position, long id) {
String convFrom = ((TextView) viewClicked).getText().toString();
CF = convFrom;
}
});
listMassTo.setOnItemClickListener(new AdapterView.OnItemClickListener(){
#Override
public void onItemClick(AdapterView<?> parent, View viewClicked, int position, long id) {
String convTo = ((TextView) viewClicked).getText().toString();
CT = convTo;
}
});
//Test to see if the two string were extracted from the onItemClick method:
TextView t1 = (TextView) findViewById(R.id.test1);
t1.setText(CT);
TextView t2 = (TextView) findViewById(R.id.test2);
t2.setText(CF);
}
}
You should access items via adapters using the parameter position.
Supposing your adapter contains Strings (Otherwise adapt it to your data model):
public void onItemClick(AdapterView<?> parent, View viewClicked, int position, long id) {
CF = <listMassFrom_adapter>.getItem(position);
}
EDIT:
Example tested and working. You can see a toast when items are selected.
package com.example;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.Toast;
import com.example.testbutton.R;
public class Tabs extends Activity {
final static String[] MassUnits = { "kg", "g", "mg", "lb", "lbm", "slug" };
String CF = ""; // Convert To
String CT = ""; // Convert From
ListView listMassFrom, listMassTo;
ListAdapter adapterFrom, adapterTo;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.tabs);
// Find views
listMassFrom = (ListView) findViewById(R.id.lvFrom);
listMassTo = (ListView) findViewById(R.id.lvTo);
// Create list of items
adapterFrom = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, MassUnits);
listMassFrom.setAdapter(adapterFrom);
adapterTo = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, MassUnits);
listMassTo.setAdapter(adapterTo);
listMassFrom
.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent,
View viewClicked, int position, long id) {
String convFrom = (String) adapterFrom
.getItem(position);
Toast.makeText(getApplicationContext(),
"From: " + convFrom, Toast.LENGTH_SHORT).show();
}
});
listMassTo
.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent,
View viewClicked, int position, long id) {
String convTo = (String) adapterTo.getItem(position);
Toast.makeText(getApplicationContext(),
"To: " + convTo, Toast.LENGTH_SHORT).show();
}
});
}
}
Layout tabs.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ListView
android:id="#+id/lvFrom"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
<ListView
android:id="#+id/lvTo"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
</LinearLayout>
I think it is better to use spinners, but you can adapt the code if that's the case.
i try to make a list with Clickable strings from my string array.
By clicking on any String i want to get to a classes named after this string.
I tried with onListItemClick... but it doesnt work :S .. any suggestions for a solution?
Thank you for your time :)
I've got some Strings for example called "Title 1", "Title 2" and a little description under every title called "Description 1", "Description 2"... in a ListView. By clicking on "title" i want to get to a class named Title . How to do that with my construct?
Listview
Title 1
Description 1
Title 2
Description 2
Title 3
Description 3
ListviewEnd
package com.example.benice;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
public class Main extends Activity implements OnClickListener {
String[] titles; // String Array
String[] beschreibung; // String Array
ListView list;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Automatisch generierter Methodenstub
super.onCreate(savedInstanceState);
setContentView(R.layout.listview);
Resources res = getResources();
titles = res.getStringArray(R.array.titles);
beschreibung = res.getStringArray(R.array.beschreibung);
list = (ListView) findViewById(R.id.listView1);
VivzAdapter adapter = new VivzAdapter(this, titles, beschreibung);
list.setAdapter(adapter);
}
protected void onListItemClick(ListView l, View v, int position, long id) {
// TODO Automatisch generierter Methodenstub
onListItemClick(l, v, position, id);
String cheese = titles[position];
try {
Class ourClass = Class.forName("com.example.benice." + cheese);
Intent ourIntent = new Intent(Main.this, ourClass);
startActivity(ourIntent);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
#Override
public void onClick(View v) {
// TODO Automatisch generierter Methodenstub
}
}
class VivzAdapter extends ArrayAdapter<String> {
Context context;
String[] titlesArray;
String[] beschreibungArray;
VivzAdapter(Context c, String[] titles, String[] beschreibung) {
super(c, R.layout.single_row, R.id.titleTextView, titles);
this.context = c;
this.titlesArray = titles;
this.beschreibungArray = beschreibung;
}
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflator = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View row = inflator.inflate(R.layout.single_row, parent, false);
TextView titles = (TextView) row.findViewById(R.id.titleTextView);
TextView beschreibung = (TextView) row.findViewById(R.id.beschTextView);
titles.setText(titlesArray[position]);
beschreibung.setText(beschreibungArray[position]);
return row;
}
}
this is how the .xml looks like
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="90dp"
android:background="#drawable/backgg"
android:orientation="vertical" >
<TextView
android:id="#+id/titleTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="20dp"
android:paddingRight="20dp"
android:paddingTop="5dp"
android:text="Here is the Title"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="#fefefe" />
<TextView
android:id="#+id/beschTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="10dp"
android:paddingLeft="20dp"
android:paddingRight="20dp"
android:text="Here is the Descrition"
android:textColor="#fefefe" />
</LinearLayout>
It's possible to construct your ListView by extending ListActivity rather than Activity - onListItemClick will only work as it is used in you code if you extend ListActivity. You can also unimplement OnClickListener regardless of what you do. For instance:
public class MainActivity extends ListActivity {
String[] titles = { "One", "two", "three", "four", "five"};
String[] beschreibung = { "1", "2", "3", "4", "5"};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// VivzAdapter? Good to see another SlideNerd fan :)
VivzAdapter adapter = new VivzAdapter(this, titles, beschreibung);
setListAdapter(adapter);
}
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
String cheese = titles[position];
try {
Class ourClass = Class.forName("com.example.benice." + cheese);
Intent ourIntent = new Intent(this, ourClass);
startActivity(ourIntent);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
This will work for as long as you have other Classes called "One", "two", "three" etc. You also need to alter the construction of your getView() method in the custom ArrayAdapter.
public View getView(int position, View convertView, ViewGroup parent) {
View row;
if (convertView == null) {
LayoutInflater inflator = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflator.inflate(R.layout.row, parent, false);
} else {
row = convertView;
}
TextView titles = (TextView) row.findViewById(R.id.titleTextView);
TextView beschreibung = (TextView) row.findViewById(R.id.beschTextView);
titles.setText(titlesArray[position]);
beschreibung.setText(beschreibungArray[position]);
return row;
}
This post goes into more depth on onListItemClick.
First of all you need to implement an AdapterView.OnItemClickListener not View.OnClickListener as you Activity is doing.
Then you need to also set this listener on your listview, like this for example:
list.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// your code here
}
});
There might be other things wrong with your code, for example, Class.forName() is most likely going to throw exceptions if you're feeding it random strings from a list view, but without more detail about what exactly you're trying to do that's hard to say.
There's a few issues with your code, and i got a few tips for you as well.
The first issue, as to why ListClick event doesn't work. You never actually bind it to the listview.
To enable click events on your list, use this code:
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//Put your code here
}
});
Also, you have implemented onClick in your activity, because you have 'implements OnClickListener'. Why? You dont use it, so just remove it.
I'm fairly certain this could also play a role in how click events are handled by your list click event handler. As the click event for the activity might get triggered first, and then stop the click event of the list from firing.
A few tips:
1) Write all your code in english, even variable names and comments. Makes is much easier for people to read (especially since you're asking for help on an english speaking forum)
2) You can use 'LayoutInflater.from(Context)' to get a LayoutInflater, instead of that long line of code where you use 'getSystemService'.
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.