Row onClick affecting other rows - java

I am creating a check list for marking "students" present or absent.
I have a listView creating successfully with their details and to the right; an ImageView "X". When you tap the row the "X" changes to a tick! And it successfully changes other things that I need for this program to work.
My problem "was", when I would scroll one of the "ticked" rows out of view it would revert back to an "X". I have solved this using a View Holder.
My current problem is that, for example, in a List of 6 students. If I "tick" student 1, student 5 will also be changed to a tick (despite being out of view). And if I tick student 2, student 6 will be ticked. This works vice versa also. I know the onClick code is not executing for the "randomly changed rows" because despite being ticked these rows are not tagged as "ticked". It is very strange to me, here is my code:
ListView listView = (ListView) findViewById(R.id.student_listview);
listView.setBackgroundColor(Color.TRANSPARENT);
listView.setCacheColorHint(Color.TRANSPARENT);
listView.setAdapter(new MySimpleArrayAdapter(this, studentIDarr));
listView.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
ImageView img = (ImageView) view.findViewById(R.id.icon);
if(img.getTag().toString().equals("checked")) {
checkListArr.set(position, "Absent");
img.setImageResource(R.drawable.remove);
img.setTag("unchecked");
} else {
checkListArr.set(position, "Present");
img.setImageResource(R.drawable.checked);
img.setTag("checked");
}
}
});
And the Adapter with ViewHolder...
static class ViewHolder {
TextView fname;
TextView sname;
TextView ID;
TextView email;
ImageView status;
}
public class MySimpleArrayAdapter extends ArrayAdapter<String> {
private final Context context;
private final ArrayList<String> values;
public MySimpleArrayAdapter(Context context, ArrayList<String> values) {
super(context, R.layout.list_class_item, values);
this.context = context;
this.values = values;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View vi = convertView;
ViewHolder holder;
if (convertView == null) {
vi = inflater.inflate(R.layout.list_student_item, null);
holder = new ViewHolder();
holder.fname = (TextView) vi.findViewById(R.id.tvFname);
holder.sname = (TextView) vi.findViewById(R.id.tvSname);
holder.ID = (TextView) vi.findViewById(R.id.tvStudentID);
holder.email = (TextView) vi.findViewById(R.id.tvEmail);
holder.status= (ImageView) vi.findViewById(R.id.icon);
if(checkListArr.get(position).toString().equals("Absent")) {
holder.status.setTag("unchecked");
} else if (checkListArr.get(position).toString().equals("Present")) {
holder.status.setTag("checked");
}
vi.setTag(holder);
} else {
holder = (ViewHolder) vi.getTag();
}
if(checkListArr.get(position).toString().equals("Absent")) {
holder.status.setTag("unchecked");
} else if (checkListArr.get(position).toString().equals("Present")) {
holder.status.setTag("checked");
}
holder.ID.setText(values.get(position));
holder.fname.setText(fNameArray.get(position));
holder.sname.setText(sNameArray.get(position));
holder.email.setText(emailArray.get(position));
return vi;
}
}
Somebody please point out the obvious flaw in my code! Thankyou for reading!

You are misunderstanding how a ListView recycles previous views. You need to store these changes inside an underlying data model.
public class Model {
private String fname;
private String sname;
private String email;
private boolean selected;
public Model(String fname, String sname, String email) {
this.fname = fname;
selected = false;
//etc
}
public String getName() {
return fname;
}
public void setName(String fname) {
this.fname = fname;
}
public boolean isSelected() {
return selected;
}
public void setSelected(boolean selected) {
this.selected = selected;
}
//etc
}
Adapter:
private final List<Model> list;
private final Activity context;
public InteractiveArrayAdapter(Activity context, List<Model> list) {
super(context, R.layout.yourlayout, list);
this.context = context;
this.list = list;
}
static class ViewHolder {
protected TextView text;
protected CheckBox checkbox;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = null;
if (convertView == null) {
LayoutInflater inflator = context.getLayoutInflater();
view = inflator.inflate(R.layout.rowbuttonlayout, null);
final ViewHolder viewHolder = new ViewHolder();
viewHolder.text = (TextView) view.findViewById(R.id.label);
viewHolder.checkbox = (CheckBox) view.findViewById(R.id.check);
viewHolder.checkbox
.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
Model element = (Model) viewHolder.checkbox
.getTag();
element.setSelected(buttonView.isChecked());
}
});
view.setTag(viewHolder);
viewHolder.checkbox.setTag(list.get(position));
} else {
view = convertView;
((ViewHolder) view.getTag()).checkbox.setTag(list.get(position));
}
ViewHolder holder = (ViewHolder) view.getTag();
holder.text.setText(list.get(position).getName());
holder.checkbox.setChecked(list.get(position).isSelected());
return view;
}

No need for ViewHolder.
convertView is already inflated view. Inflate when it's value is null. Then find your views and set the proper values according to position in either new or convertView.
Implement SparseBooleanArray in the adapter with methods for toggling <int Position, boolean Absence> values. It's optimized HashMap like class for holding and inserting such values. AdapterView<?> will give you adapter to interact with it.
ListView also will give you access to a similar array with all selected views for processing and saving.

Related

How to get the sum of a column in a listview android?

I am trying to get the total of numbers in an sql table,
i first connected between android and sql but i can't
sum the numbers in the table column and show them
in a textview,like i want to get the total
of numbers in a column then
display them in a text view
,can someone help me with this task?
here is the code i used for
the listview
public class MyAppAdapter extends BaseAdapter //has a class viewholder which holds
{
public class ViewHolder
{
TextView textDate;
TextView textTotal;
TextView textLastTotal;
TextView textCount;
TextView textTaxs;
}
public List<ClassListItems2> parkingList;
public Context context;
ArrayList<ClassListItems2> arraylist;
private MyAppAdapter(List<ClassListItems2> apps, Context context)
{
this.parkingList = apps;
this.context = context;
arraylist = new ArrayList<ClassListItems2>();
arraylist.addAll(parkingList);
}
#Override
public int getCount() {
return parkingList.size();
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) // inflating the layout and initializing widgets
{
View rowView = convertView;
ViewHolder viewHolder= null;
if (rowView == null)
{
LayoutInflater inflater = getLayoutInflater();
rowView = inflater.inflate(R.layout.listcontent2, parent, false);
viewHolder = new ViewHolder();
viewHolder.textDate = (TextView) rowView.findViewById(R.id.date);
viewHolder.textLastTotal = (TextView) rowView.findViewById(R.id.lasttotal);
viewHolder.textTaxs = (TextView) rowView.findViewById(R.id.date3);
viewHolder.textCount = (TextView) rowView.findViewById(R.id.InvoicescCount);
viewHolder.textTotal = (TextView) rowView.findViewById(R.id.total);
rowView.setTag(viewHolder);
}
else
{
viewHolder = (ViewHolder) convertView.getTag();
}
// here setting up names and images
viewHolder.textDate.setText(parkingList.get(position).getDate()+"");
viewHolder.textTotal.setText(parkingList.get(position).getTotal());
viewHolder.textLastTotal.setText(parkingList.get(position).getLasttotal());
viewHolder.textTaxs.setText(parkingList.get(position).getTaxs());
viewHolder.textCount.setText(parkingList.get(position).getInvoicecount());
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//What happens when you click on a place!
}
});
return rowView;
}
This Adapter is feed with a Collection (List) in his constructor.
To know total numbers, in Activity/Fragment that handle that Collection use:
parkingList.size()
To get sum:
float total;
for (ClassListItems2 actualItem : parkingList) {
total += actualItem.getTotal()
}
All of this logic must be executed in Activity/Fragment, never in Adapter because the Adapter only got presentation/visual logic.

Android Checkbox in Listview selecting automatically

in my android application I am displaying the contact list of phone in a list view and a check box in each row for selecting contacts. But when I am selecting a particular row about tenth row is also getting selected automatically. I am giving my code below, if any one knows please help..
public class ContactsAdapter extends BaseAdapter
{
private Context context;
private ArrayList<Contact> contacts;
public ContactsAdapter(Context context, ArrayList<Contact> contacts)
{
this.context = context;
this.contacts = contacts;
}
public View getView(final int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View gridView;
final ViewHolder mHolder;
if (convertView == null)
{
// gridView = new View(context);
// get layout from mobile.xml
//gridView = inflater.inflate(R.layout.contact, null);
convertView = inflater.inflate(R.layout.contact, null);
mHolder = new ViewHolder();
mHolder.textName =(TextView) convertView.findViewById(R.id.name);
mHolder.textMobile =(TextView) convertView.findViewById(R.id.mobile);
mHolder.textSelector =(CheckBox) convertView.findViewById(R.id.selected);
convertView.setTag(mHolder);
));
}
else
{
mHolder = (ViewHolder) convertView.getTag();
mHolder.textSelector.setOnCheckedChangeListener(null);
}
mHolder.textMobile.setText(contacts.get(position).getMobile());
mHolder.textName.setText(contacts.get(position).getName());
mHolder.textSelector.setFocusable(false);
return convertView;
}
private class ViewHolder {
private TextView textMobile,textName;
private CheckBox textSelector;
}
#Override
public int getCount() {
return contacts.size();
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
}
Well Thats because ViewHolder will recycle the Views everytime you Scroll
i suggest you to Use onCLick on ListItem instead checkbox
To overcome this Declare a SparseBooleanArray
SparseBooleanArray sba=new SparseBooleanArray();//this should be global
Then set the items checked state as soon as you render it
mHolder.textSelector =(CheckBox) convertView.findViewById(R.id.selected);
mHolder.textSelector.setChecked(sba.get(position));
Then write a onClickListener to you convertView and check it manually
convertView.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) {
mHolder.textSelector.setChecked(isChecked);
sba.put(position,isChecked); //storing the state
}
}
);
**Well Now the sba has list items checked and you can use that for further Actions**
# Jocheved... edit your code like this...
public class ContactsAdapter extends BaseAdapter
{
private Context context;
private ArrayList<Contact> contacts;
SparseBooleanArray sba=new SparseBooleanArray();
public ContactsAdapter(Context context, ArrayList<Contact> contacts)
{
this.context = context;
this.contacts = contacts;
}
public View getView(final int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final ViewHolder mHolder;
if (convertView == null)
{
convertView = inflater.inflate(R.layout.contact, null);
mHolder = new ViewHolder();
mHolder.textName =(TextView) convertView.findViewById(R.id.name);
mHolder.textMobile =(TextView) convertView.findViewById(R.id.mobile);
mHolder.textSelector =(CheckBox) convertView.findViewById(R.id.selected);
convertView.setTag(mHolder);
}
else
{
mHolder = (ViewHolder) convertView.getTag();
}
mHolder.textMobile.setText(contacts.get(position).getMobile());
mHolder.textName.setText(contacts.get(position).getName());
mHolder.textName.setSelected(true);
mHolder.textSelector.setChecked(sba.get(position));
mHolder.textSelector.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v) {
if(mHolder.textSelector.isChecked())
{
sba.put(position, true);
}
else
{
sba.put(position, false);
}
}
});
return convertView;
}
private class ViewHolder
{
private TextView textMobile,textName;
private CheckBox textSelector;
}
#Override
public int getCount() {
return contacts.size();
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
}

Making a ListView holder for MainActivity

I have my listview working to display it on the MainActivity and the layout is set to have 3 TextView properties of a new Person object.
My previous code was working but the scrolling was slow, so i looked into using the Holder pattern for optimization. However, when trying to implement this i am getting NullPointerException on lines TextView personID=(TextView) view.findViewById(R.id.person_field1)
listView is set to a ListView on the MainActivity and i need the person objects to display on this view within the MainActivity.
MainActivity class:
public void onButtonClick()
{
//put the persons objects on the listView within MainActivity
listView.setAdapter(new personAdapter(MainActivity.this, R.layout.list_layout,
personList));
}
class personAdapter extends ArrayAdapter<Person>
{
private LayoutInflater layoutInflator;
public personAdapter(Context context, int resource, List<Person> p) {
super(context, resource, p);
layoutInflator = LayoutInflater.from(context);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
Holder holder = null;
Person p = getItem(position);
if (view == null) {
layoutInflator.inflate(R.layout.list_layout, null);
//getting null pointer exceptions here
TextView personID = (TextView) view.findViewById(R.id.person_field1);
TextView personFName = (TextView) view.findViewById(R.id.person_field2);
TextView personLName = (TextView) view.findViewById(R.id.person_field3);
holder = new Holder(personID, personFName, personLName);
view.setTag(holder);
}
else {
holder = (Holder) view.getTag();
}
holder.stop.setText(person.getID());
holder.location.setText(person.getFName());
holder.time.setText(person.getLName());
return view;
}
}
static class Holder
{
public TextView id;
public TextView FName;
public TextView LName;
public Holder(TextView id, TextView FName, TextView LName) {
this.id = id;
this.FName = FName;
this.LName = LName;
}
}
because there really is null
pay attention to check view == null, and then view never initialized
try this
view = layoutInflator.inflate(R.layout.list_layout, null);
Just add reference to your view:
view = layoutInflator.inflate(R.layout.list_layout, null);
view is null, you're even checking for it:
if (view == null) { ...
}
What you're missing is assigning the inflated layout to view
view = layoutInflator.inflate(R.layout.list_layout, null);

Integrating current ListView with a Custom Adapter with ListView to allow multiple views

The current project I have includes a ListView with a Custom Adapter. However, I am now interested in adding multiple types of views to my ListView but after several attempts I have been unable to add the two sources of code together to successfully integrate them.
Article on ListView with multiple views: ListView Article for multiple views
The custom adapter in my current code retrieves the data from another class called getData which is referenced by "data".
Code from article (ListView with multiple views):
public class MultipleItemsList extends ListActivity {
private MyCustomAdapter mAdapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mAdapter = new MyCustomAdapter();
for (int i = 1; i < 50; i++) {
mAdapter.addItem("item " + i);
if (i % 4 == 0) {
mAdapter.addSeparatorItem("separator " + i);
}
}
setListAdapter(mAdapter);
}
private class MyCustomAdapter extends BaseAdapter {
private static final int TYPE_ITEM = 0;
private static final int TYPE_SEPARATOR = 1;
private static final int TYPE_MAX_COUNT = TYPE_SEPARATOR + 1;
private ArrayList mData = new ArrayList();
private LayoutInflater mInflater;
private TreeSet mSeparatorsSet = new TreeSet();
public MyCustomAdapter() {
mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public void addItem(final String item) {
mData.add(item);
notifyDataSetChanged();
}
public void addSeparatorItem(final String item) {
mData.add(item);
// save separator position
mSeparatorsSet.add(mData.size() - 1);
notifyDataSetChanged();
}
#Override
public int getItemViewType(int position) {
return mSeparatorsSet.contains(position) ? TYPE_SEPARATOR : TYPE_ITEM;
}
#Override
public int getViewTypeCount() {
return TYPE_MAX_COUNT;
}
#Override
public int getCount() {
return mData.size();
}
#Override
public String getItem(int position) {
return mData.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
int type = getItemViewType(position);
System.out.println("getView " + position + " " + convertView + " type = " + type);
if (convertView == null) {
holder = new ViewHolder();
switch (type) {
case TYPE_ITEM:
convertView = mInflater.inflate(R.layout.item1, null);
holder.textView = (TextView)convertView.findViewById(R.id.text);
break;
case TYPE_SEPARATOR:
convertView = mInflater.inflate(R.layout.item2, null);
holder.textView = (TextView)convertView.findViewById(R.id.textSeparator);
break;
}
convertView.setTag(holder);
} else {
holder = (ViewHolder)convertView.getTag();
}
holder.textView.setText(mData.get(position));
return convertView;
}
}
public static class ViewHolder {
public TextView textView;
}
}
Current code (ListView with custom adapter):
FragmentA.java
package com.example.newsapp;
public class FragmentA extends Fragment{
getData data = getData.getMyData();
public Integer ArticleID;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View V = inflater.inflate(R.layout.fragment_a, container, false);
ListView listView = (ListView)V.findViewById(R.id.list)
CustomList adapter = new
CustomList(getActivity(), data.Headline.toArray(new String[data.Headline.size()]), data.Description.toArray(new String[data.Description.size()]), data.BitmapList.toArray(new Bitmap[data.BitmapList.size()]), data.ArticleID.toArray(new Integer[data.ArticleID.size()]));
listView.setAdapter(adapter);
listView.setOnItemClickListener(this); //Removed on click item event code.
return V;
}
CustomList.java
package com.example.newsapp;
public class CustomList extends ArrayAdapter<String>{
private final Activity context;
private final String[] titleId;
private final String[] descriptionId;
private final Bitmap[] pictureid;
public CustomList(Activity context,
String[] Headline, String[] Description, Bitmap[] BitmapList, Integer[] ArticleID) {
super(context, R.layout.single_row, Headline);
this.context = context;
this.titleId = Headline;
this.descriptionId = Description;
this.pictureid = BitmapList;
}
#Override
public View getView(int position, View view, ViewGroup parent) {
LayoutInflater inflater = context.getLayoutInflater();
View rowView= inflater.inflate(R.layout.single_row, null, true);
TextView txtTitle = (TextView) rowView.findViewById(R.id.tvTitle);
TextView txtDescription = (TextView) rowView.findViewById(R.id.tvDescription);
ImageView imageView = (ImageView) rowView.findViewById(R.id.ivIcon);
txtTitle.setText(titleId[position]);
txtDescription.setText(descriptionId[position]);
imageView.setImageBitmap(pictureid[position]);
return rowView;
}
}
Edit:
public class CustomList extends ArrayAdapter<String>{
private final Activity context;
private final String[] titleId;
private final String[] descriptionId;
private final Bitmap[] pictureid;
public CustomList(Activity context,
String[] Headline, String[] Description, Bitmap[] BitmapList, Integer[] ArticleID) {
super(context, R.layout.single_row, Headline);
this.context = context;
this.titleId = Headline;
this.descriptionId = Description;
this.pictureid = BitmapList;
}
#Override
public View getView(int position, View view, ViewGroup parent) {
int viewType = getItemViewType(position);
View rowView = null;
switch(viewType) {
case 0:
LayoutInflater inflater = context.getLayoutInflater();
rowView= inflater.inflate(R.layout.single_row, null, true);
TextView txtTitle = (TextView) rowView.findViewById(R.id.tvTitle);
TextView txtDescription = (TextView) rowView.findViewById(R.id.tvDescription);
ImageView imageView = (ImageView) rowView.findViewById(R.id.ivIcon);
txtTitle.setText(titleId[position]);
txtDescription.setText(descriptionId[position]);
imageView.setImageBitmap(pictureid[position]);
case 1:
LayoutInflater inflater2 = context.getLayoutInflater();
rowView= inflater2.inflate(R.layout.single_row_loadmore, null, true);
}
return rowView;
}
#Override
public int getViewTypeCount() {
return 2; // TODO make this a static final
}
#Override
public int getItemViewType(int position) {
return position % 2; // 0 or 1
}
}
First, a bit of an aside: you should create a class that encapsulates a headline, description, etc. and use an array/collection of those objects to back your adapter. It will be far easier than managing many disparate arrays of things, especially if one day you decide you need another attribute of an Article (its category, for example).
class Article {
int id;
String headline;
String description;
Bitmap picture;
}
With regard to your ListView, the magic happens in the methods getItemViewType() and getViewTypeCount(). In getViewTypeCount() you return the maximum number of row types -- the article you posted uses two row types and so returns 2. In getItemViewType() you return a value between zero and (viewTypeCount - 1) -- in the article, his implementation can return 0 or 1 because his viewTypeCount is 2.
How you decide which row type applies to each item is entirely up to you. If, for example, you wanted to simply alternate view types on every row, you can do this:
#Override
public int getViewTypeCount() {
return 2; // TODO make this a static final
}
#Override
public int getItemViewType(int position) {
return position % 2; // 0 or 1
}
In other applications you would probably inspect the item at the given position to help you determine what should be returned in getItemViewtype().
The reason this functionality exists is that getView() provides a parameter (called convertView) that is a row which has been recycled. In order to give you an appropriate convertView, ListView needs to first know what row type it was. When you want to implement getView() for an adapter with multiple row types, it generally looks something like this:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
int viewType = getItemViewType(position);
switch(viewType) {
case 0:
return setUpOneViewType(position, convertView, parent);
case 1:
return setUpAnotherViewType(position, convertView, parent);
}
}
Note the cases for the switch statement correspond to the possible values that can be returned from getItemViewType(). These could be static final members.
I highly suggest watching The World of ListView. That video covers this topic as well as how to properly use convertView in your adapter implementation.

Multi-line ListView w/ ImageView on left side

I am required to create a project similar to that of the ff. pic. (My apologies for the use a siily pic, I have to make do with what is readily-available).
I wouldn't say what I did was the best approach in making a 'dynamic' ListView but I'd be glad just to make what I currently have work. Anyway my implementation is as follows:
public class MultiLineListViewActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ArrayList<SearchResults> searchResults = getSearchResults();
ListView listView = (ListView) findViewById(R.id.listView);
listView.setAdapter(new MyCustomBaseAdapter(this, searchResults));
}
private ArrayList<SearchResults> getSearchResults() {
ArrayList<SearchResults> results = new ArrayList<SearchResults>();
SearchResults sr1 = new SearchResults();
sr1.setName("Name 1");
sr1.setPhone("12345");
SearchResults.setIcon(R.drawable.pic_one);
results.add(sr1);
sr1 = new SearchResults();
sr1.setName("Name 2");
sr1.setPhone("123456");
SearchResults.setIcon(R.drawable.pic_two);
results.add(sr1);
...
return results;
}
}
public class SearchResults {
private String name;
private String phone;
public static ArrayList<Integer> iconsList = new ArrayList<Integer>();
public void setName(String name) {
this.name = name;
}
public void setPhone(String phone) {
this.phone = phone;
}
public static void setIcon(int i) {
iconsList.add(i);
}
public String getName() {
return this.name;
}
public String getPhone() {
return this.phone;
}
}
public class MyCustomBaseAdapter extends BaseAdapter {
private ArrayList<SearchResults> searchArrayList;
private LayoutInflater layoutInflater;
private Context context;
public MyCustomBaseAdapter(Context context, ArrayList<SearchResults> results) {
this.searchArrayList = results;
//this.context = context;
layoutInflater = LayoutInflater.from(context);
}
#Override
public int getCount() {
return searchArrayList.size();
}
#Override
public Object getItem(int position) {
return searchArrayList.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
ImageView imageView;
if(convertView == null) {
convertView = layoutInflater.inflate(R.layout.custom_row_view, null);
holder = new ViewHolder();
holder.txtName = (TextView) convertView.findViewById(R.id.name);
holder.txtPhone = (TextView) convertView.findViewById(R.id.phone);
imageView = new ImageView(context);
convertView.setTag(holder);
}
else {
//imageView = (ImageView) convertView;
holder = (ViewHolder) convertView.getTag();
}
imageView = new ImageView(context);
imageView.setImageResource(SearchResults.iconsList.get(position));
holder.txtName.setText(searchArrayList.get(position).getName());
holder.txtPhone.setText(searchArrayList.get(position).getPhone());
return convertView;
}
class ViewHolder {
TextView txtName;
TextView txtPhone;
}
The above code was successful in displaying the Name and Phone lines in the ListView, it's the addition of the image that's giving me the 'Force Close'.
Take note of the commented line imageView = (ImageView) convertView;
I have reduced it down to that particular line in that removing the comments causes the app to crash.
Note: Whenever you get a force close that you're asking about in a StackOverflow question, please post the full stack trace.
You're always creating a new ImageView when in fact you probably shouldn't need to create one at all. It should be defined in your custom item layout (which you should probably post as well in this case) just like the TextViews. You can use findViewById the same way and get it.
kabuko is right on both counts. (UPDATE: also his comment below should not be ignored.) I'm guessing that your layout/custom_row_view is a LinearLayout, which would mean that the commented line attempts to coerce a LinearLayout to an ImageView, which yes would raise an exception. Also, your ViewHolder class is superfluous, just define those TextViews as variables in your getView() like so...
// Assuming that layout/custom_row_view is a LinearLayout...
getView(yadda) {
LinearLayout row;
ImageView imageView;
TextView txtName, txtPhone;
if (convertView == null) {
row = // inflate a new one
} else {
row = // get the old one
}
// fetch the views
imageView = row.findViewById(...);
txtName = row.findViewById(...);
txtPhone = row.findViewById(...);
// fill the views
imageView.setImageResource(...);
txtName.setContent(...);
txtPhone.setContent(...);
return row;
}
Ciao.

Categories

Resources