I am displaying some rows in my ListView and want to change only one of the row, by seeing if any of the date in the list matches today's date.
My partial code is:
DateFormat df = new SimpleDateFormat("EEEEE, LLLL d", Locale.US);
String[] suspendedDates = {
"Tuesday, January 1",
"Wednesday, April 16",
"Monday, October 6",
"Wednesday, December 25"
};
lvDisplay = (ListView) findViewById(R.id.lvDisp);
for (int i = 0; i < suspendedDates.length; i ++) {
sDate = suspendedDates[i];
sReason = datesReason[i];
if (Arrays.asList(suspendedDates).contains(df.format(Calendar.getInstance(Locale.US).getTime()))) {
inIconShow = R.drawable.caliconpressed; //if today matches display a different drawable
contents.add(new SetRows(inIconShow, sDate, sReason));
}
if (!Arrays.asList(suspendedDates).contains(df.format(Calendar.getInstance(Locale.US).getTime()))) {
inIconShow = R.drawable.calicon; //if today doesn't match the array display the default drawable
contents.add(new SetRows(inIconShow, sDate, sReason));
}
}
// Now set your adapter.
adapter = new SetRowsCustomAdapter(MainActivity.this, R.layout.listdates, contents);
lvDisplay.setAdapter(adapter);
SetRowsCustomAdapter class:
import java.util.ArrayList;
import android.app.Activity;
import android.content.Context;
import android.graphics.Typeface;
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 SetRowsCustomAdapter extends ArrayAdapter<SetRows> {
Context context;
int layoutResourceId;
ArrayList<SetRows> data=new ArrayList<SetRows>();
public SetRowsCustomAdapter(Context context, int layoutResourceId, ArrayList<SetRows> data) {
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = data;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
ImageHolder holder = null;
if(row == null)
{
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);
holder = new ImageHolder();
holder.txtTitle = (TextView)row.findViewById(R.id.tvDateVal);
//holder.txtTitle.setTypeface(Typeface.createFromAsset(getContext().getAssets(), "fonts/robm.ttf"));
holder.imgIcon = (ImageView)row.findViewById(R.id.ivIcon0);
holder.txtID = (TextView)row.findViewById(R.id.tvReasonVal);
//holder.txtID.setTypeface(Typeface.createFromAsset(getContext().getAssets(), "fonts/robm.ttf"));
row.setTag(holder);
}
else
{
holder = (ImageHolder)row.getTag();
}
SetRows myImage = data.get(position);
holder.txtTitle.setText(myImage.name);
holder.txtID.setText(myImage.id);
int outImage=myImage.image;
holder.imgIcon.setImageResource(outImage);
return row;
}
static class ImageHolder
{
ImageView imgIcon;
TextView txtTitle;
TextView txtID;
}
}
So the 4th row should have a different icon and the other 3 should have default icon. What is happening is if the date matches, every row has the different icon, otherwise every row has the default icon.
How do I fix it?
if you want change the image you can do in getView method like bellow code:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
ImageHolder holder = null;
if(row == null)
{
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);
holder = new ImageHolder();
holder.txtTitle = (TextView)row.findViewById(R.id.tvDateVal);
//holder.txtTitle.setTypeface(Typeface.createFromAsset(getContext().getAssets(), "fonts/robm.ttf"));
holder.imgIcon = (ImageView)row.findViewById(R.id.ivIcon0);
holder.txtID = (TextView)row.findViewById(R.id.tvReasonVal);
//holder.txtID.setTypeface(Typeface.createFromAsset(getContext().getAssets(), "fonts/robm.ttf"));
row.setTag(holder);
}
else
{
holder = (ImageHolder)row.getTag();
}
SetRows myImage = data.get(position);
holder.txtTitle.setText(myImage.name);
holder.txtID.setText(myImage.id);
int outImage=myImage.image;
if (data.getValue)
holder.imgIcon.setImageResource(deferentIcon);
else
holder.imgIcon.setImageResource(defaultIcon);
return row;
}
and if you want change multi row icons you can send one list of your row and check in that, and for refresh you list use adapter.notifyDataSetChanged()
Edit
for your situation you can add on boolean value in your DS and if date equal set true otherwise set else that and in if statement check that
Use viewHolder in adapter then use notifyDataSetChanged() in adapter;
I already used and it will help.
Related
What happens is that I have a ArrayList<Pair<String, String>> and when I loop through that list in order to add the pair to a listview with two separate columns using a list adapter, I try to add the pair's first string to a certain textview and then the second string to certain textview, then it loops through the whole list and then adds in identical values to all lines.
Code for list adapter:
package com.example.test2;
import android.content.Context;
import android.util.Log;
import android.util.Pair;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import java.util.ArrayList;
public class ThreeColumn_ListAdapter extends ArrayAdapter<Pair<String, String>> {
private LayoutInflater mInflater;
private ArrayList<Pair<String, String>> news;
private int mViewResourceId;
public ThreeColumn_ListAdapter(Context context, int textViewResourceId, ArrayList<Pair<String, String>> news) {
super(context, textViewResourceId, news);
this.news = news;
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mViewResourceId = textViewResourceId;
}
public View getView(int position, View convertView, ViewGroup parent) {
convertView = mInflater.inflate(mViewResourceId, null);
TextView firstName = convertView.findViewById(R.id.textFirstName);
TextView lastName = convertView.findViewById(R.id.textLastName);
//TextView favFood = convertView.findViewById(R.id.textFavFood);
Log.i("n2",news.toString());
for(int j=0;j<news.size();j++){
firstName.setText(news.get(j).first);
lastName.setText(news.get(j).second);
}
return convertView;
}
}
What is stored in ArrayList<Pair<String, String>> news:
[Pair{usd -0.8068}, Pair{eur 0.5327}, Pair{gbp 1.2172}, Pair{nzd -2.7538}, Pair{cad 0.7586}, Pair{aud -1.7719}, Pair{chf 0.9591}, Pair{jpy 1.8649}]
Output viewed in listview layout:
Pair{jpy 1.8649} with pair's first value in textview firstName iterated 8 times and the pair's second value in textview lastName iterated 8 times and the 8 being the length of the ArrayList<Pair<String, String>> news
Figured it out, all I had to do was remove the for loop and do just news.get(position).first instead of doing a loop for news, since listview does a loop naturally.
So previously:
public View getView(int position, View convertView, ViewGroup parent) {
convertView = mInflater.inflate(mViewResourceId, null);
TextView firstName = convertView.findViewById(R.id.textFirstName);
TextView lastName = convertView.findViewById(R.id.textLastName);
//TextView favFood = convertView.findViewById(R.id.textFavFood);
Log.i("n2",news.toString());
for(int j=0;j<news.size();j++){
firstName.setText(news.get(j).first);
lastName.setText(news.get(j).second);
}
return convertView;
}
Correct Way:
public View getView(int position, View convertView, ViewGroup parent) {
convertView = mInflater.inflate(mViewResourceId, null);
TextView firstName = convertView.findViewById(R.id.textFirstName);
TextView lastName = convertView.findViewById(R.id.textLastName);
//TextView favFood = convertView.findViewById(R.id.textFavFood);
firstName.setText(news.get(position).first);
lastName.setText(news.get(position).second);
return convertView;
}
i"m using custom list have two buttons, one for and second one for whatsaap. my problem is when i"m click first button then make a phone call its not working for me... please help me
custom list :
import java.util.List;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.NetworkImageView;
public class CustomListAdapter extends BaseAdapter {
private Activity activity;
private LayoutInflater inflater;
private List<Movie> movieItems;
ImageLoader imageLoader = AppController.getInstance().getImageLoader();
public CustomListAdapter(Activity activity, List<Movie> movieItems) {
this.activity = activity;
this.movieItems = movieItems;
}
#Override
public int getCount() {
return movieItems.size();
}
#Override
public Object getItem(int location) {
return movieItems.get(location);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (inflater == null)
inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null)
convertView = inflater.inflate(R.layout.list_row, null);
if (imageLoader == null)
imageLoader = AppController.getInstance().getImageLoader();
NetworkImageView thumbNail = (NetworkImageView) convertView
.findViewById(R.id.thumbnail);
TextView title = (TextView) convertView.findViewById(R.id.title);
TextView rating = (TextView) convertView.findViewById(R.id.rating);
TextView genre = (TextView) convertView.findViewById(R.id.genre);
Button year = (Button) convertView.findViewById(R.id.releaseYear);
year.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(activity, "ramu...", Toast.LENGTH_LONG).show();
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setData(Uri.parse("tel:123456789"));
startActivity(callIntent);
}
});
// getting movie data for the row
Movie m = movieItems.get(position);
// thumbnail image
thumbNail.setImageUrl(m.getThumbnailUrl(), imageLoader);
System.out.println("thumbNail===============>"+thumbNail);
// title
title.setText(m.getTitle());
// rating
rating.setText("Rating: " + String.valueOf(m.getRating()));
// release year
year.setText(String.valueOf(m.getYear()));
return convertView;
}
private void startActivity(Intent callIntent) {
// TODO Auto-generated method stub
}
}
`
You are committing few mistakes which cannot be ignored.
Listview recycles views on scroll, so it is very important that you handle this check. Not doing so will cause views inflation at wrong positions. Use ViewHolder
Solution:
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
/* This is where you initialize new rows, by:
* - Inflating the layout,
* - Instantiating the ViewHolder,
* - And defining any characteristics that are consistent for every row */
} else {
/* Fetch data already in the row layout,
* primarily you only use this to get a copy of the ViewHolder */
}
/* Set the data that changes in each row, like `title` and `size`
* This is where you give rows there unique values. */
return convertView;
}
You need to implement OnClickListener outside of checks like:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.list_row, null);
NetworkImageView thumbNail = (NetworkImageView) convertView
.findViewById(R.id.thumbnail);
TextView title = (TextView) convertView.findViewById(R.id.title);
TextView rating = (TextView) convertView.findViewById(R.id.rating);
TextView genre = (TextView) convertView.findViewById(R.id.genre);
Button year = (Button) convertView.findViewById(R.id.releaseYear);
}else {
}
year.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(activity, "ramu...", Toast.LENGTH_LONG).show();
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setData(Uri.parse("tel:123456789"));
startActivity(callIntent);
}
});
// getting movie data for the row
Movie m = movieItems.get(position);
// thumbnail image
thumbNail.setImageUrl(m.getThumbnailUrl(), imageLoader);
System.out.println("thumbNail===============>"+thumbNail);
// title
title.setText(m.getTitle());
// rating
rating.setText("Rating: " + String.valueOf(m.getRating()));
// release year
year.setText(String.valueOf(m.getYear()));
return convertView;
}
Initialize ImageLoader in adapter constructor:
I've been attempting to upgrade an old app I made in college, including adding a listview to show data from Last.FM. The idea is having a main text with subtext under it, but the adapter I put together just isn't working. I've tried a good number of options, and the most recent is giving me a "Attempt to invoke virtual method on a null object reference" error, a previous try got a "Cannot cast Activity to Application" error.
Relevant code sections:
Main Activity adapter section:
ListView lv;
final Dialog dialog = new Dialog(MainActivity.this);
dialog.setContentView(R.layout.summarylayout);
dialog.getWindow().setLayout(WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT);
lv = (ListView) dialog.findViewById(R.id.itemList); //Listview name
artistAdapter = new itemAdapter(getApplicationContext(), //Changed from ArrayAdapter<Item>
R.layout.custom_listview, //R.layout.custom_listview if itemAdapter works
result.toArray(new Item[] {}));
lv.setAdapter(artistAdapter);
lv.setOnItemClickListener(new MyOIListener());
Button closeButton = (Button) dialog
.findViewById(R.id.closeBtn);
// if button is clicked, close the custom dialog
closeButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
tracks = false;
dialog.dismiss();
}
});
The custom Adapter itself (Commented sections are previous attempts):
public class itemAdapter extends ArrayAdapter<Item>{
Context context;
int layoutResourceId;
Item data[] = null;
public itemAdapter(Context context, int layoutResourceId, Item[] data) {
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = data;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
// ItemHolder holder = null;
Item rowIn = new Item();
TextView main;
TextView sub;
if(row == null)
{
//LayoutInflater inflater = ((Application)context).getLayoutInflater();
//row = inflater.inflate(layoutResourceId, parent, false);
//row = LayoutInflater.from(getActivity()).inflate(R.layout.custom_listview, parent, false);
LayoutInflater inflater = LayoutInflater.from(this.getContext());
row = inflater.inflate(layoutResourceId, parent, false);
//holder = new ItemHolder();
//rowIn = new Item();
}
else
{
rowIn = (Item) row.getTag();
}
main = (TextView)row.findViewById(R.id.mainText);
sub = (TextView)row.findViewById(R.id.subText);
row.setTag(rowIn);
Item temp = data[position];
main.setText(temp.getTitle());
sub.setText(temp.getExtra());
return row;
}
/* static class ItemHolder
{
TextView mainText;
TextView subText;
}*/
}
The "Item" class is simply a holder for text/URLs parsed from the Last.FM api request.
I realize this is a question asked often, but 3 days of attempts and searching hasn't helped me out much. Any help would be appreciated
You're passnig the applicationContext to your adapter. Pass your Activity by:
artistAdapter = new itemAdapter(MainActivity.this, //Changed from ArrayAdapter<Item>
R.layout.custom_listview, //R.layout.custom_listview if itemAdapter works
result.toArray(new Item[] {}));
Your getView method was wrong, actually you will face a null variable there when getting the data from the tag.
This one should work for you, it is using ViewHolder Pattern
public class itemAdapter extends ArrayAdapter<Item> {
Context context;
int layoutResourceId;
Item data[] = null;
public itemAdapter(Context context, int layoutResourceId, Item[] data) {
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = data;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ItemHolder holder = null;
if (convertView == null) {
//LayoutInflater inflater = ((Application)context).getLayoutInflater();
//row = inflater.inflate(layoutResourceId, parent, false);
//row = LayoutInflater.from(getActivity()).inflate(R.layout.custom_listview, parent, false);
LayoutInflater inflater = ((Activity) this.context).getLayoutInflater();
convertView = inflater.inflate(layoutResourceId, parent, false);
holder = new ItemHolder();
holder.mainText = row.findViewById(R.id.mainText);
holder.subText = row.findViewById(R.id.subText);
convertView.setTag(holder);
} else {
holder = (ItemHolder) convertView.getTag();
}
Item temp = data[position];
if(temp != null) {
holder.mainText.setText(temp.getTitle());
holder.subText.setText(temp.getExtra());
}
return convertView;
}
static class ItemHolder {
TextView mainText;
TextView subText;
}
}
And as #vinitius said, pass your Activity context to the adapter.
I've a problem with listview in android, I've created a list view that takes data from SQLite database with a custom ArrayAdapter
I want to display an image view when user choose an item, but when I click on an item, the image (check mark) shows in 3 other items
I don't know where is the problem exactly, here is my code for adapter :
import info.androidhive.tabsswipe.R;
import java.util.List;
import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.itdinamik.tabswipe.CompareVehicle;
import com.itdinamik.vcompare.MySQLiteHelper;
import com.itdinamik.vcompare.Vehicle;
public class ComperAdapter extends ArrayAdapter<Vehicle>{
List<Vehicle> data;
Context context;
int layoutResID;
Vehicle itemdata;
MySQLiteHelper dbhelper;
public ComperAdapter(Context context, int layoutResourceId, List<Vehicle> data) {
super(context, layoutResourceId, data);
this.data=data;
this.context=context;
this.layoutResID=layoutResourceId;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final NewsHolder holder;
View row = convertView;
dbhelper = new MySQLiteHelper(context);
if(row == null)
{
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
row = inflater.inflate(layoutResID, parent, false);
holder = new NewsHolder();
holder.itemNameTitle = (TextView)row.findViewById(R.id.VehicleTxt);
holder.itemNameScore = (TextView)row.findViewById(R.id.Score);
holder.CheckedMark=(ImageView)row.findViewById(R.id.Checked);
holder.Vehicle=(ImageView)row.findViewById(R.id.Vehicle);
holder.RL = (RelativeLayout)row.findViewById(R.id.Rv);
row.setTag(holder);
}
else
{
holder = (NewsHolder)row.getTag();
}
//Toast.makeText(getContext(), String.valueOf(position +" - " + CompareVehicle.ClickedItem), Toast.LENGTH_SHORT).show();
if(CompareVehicle.ItemClieckd) {
if(position == CompareVehicle.ClickedItem) {
Log.w("Position", String.valueOf(position));
holder.CheckedMark.setVisibility(View.VISIBLE);
holder.RL.setBackgroundColor(Color.rgb(201, 50, 39));
}
}
itemdata = data.get(position);
holder.itemNameTitle.setText(itemdata.getTitle() + " - " + itemdata.getKraj() + " - "+ String.valueOf(position) + " - " + CompareVehicle.ClickedItem);
double totaldefault = itemdata.getOhranjenost()*0.25+itemdata.getPrevozeni()*0.16+
itemdata.getServis()*0.14+ itemdata.getCena()*0.13+
itemdata.getPoraba()*0.11+ itemdata.getStarost()*0.08+
itemdata.getDodatna()*0.07+ itemdata.getCenaZav()*0.06;
holder.itemNameScore.setText(String.format("%.1f",totaldefault));
return row;
}
static class NewsHolder{
TextView itemNameTitle;
TextView itemNameScore;
ImageView CheckedMark, Vehicle;
RelativeLayout RL;
}
}
and this one is for my fragment that i use to show my list view
import info.androidhive.tabsswipe.R;
import java.util.ArrayList;
import java.util.List;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.Toast;
import com.itdinamik.tabswipe.adapter.ComperAdapter;
import com.itdinamik.vcompare.MySQLiteHelper;
import com.itdinamik.vcompare.Vehicle;
public class CompareVehicle extends Fragment{
ViewPager mViewPager;
ArrayList<Vehicle> DataList;
static MySQLiteHelper dbhelper;
ComperAdapter adapter;
List<Vehicle> itemData;
ListView lv;
Button CompareButton;
int ClickedNum = 0;
public static int ClickedItem;
public static boolean ItemClieckd = false;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_compare_vehicle, container, false);
lv = (ListView)rootView.findViewById(R.id.CompareList);
CompareButton = (Button)rootView.findViewById(R.id.CompareButton);
dbhelper = new MySQLiteHelper(getActivity());
// get all vehicles
itemData = dbhelper.getAllVehicles();
adapter=new ComperAdapter(getActivity(),R.layout.list_single,itemData);
lv.setAdapter(adapter);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int position,
long arg3) {
// TODO Auto-generated method stub
ClickedItem = position;
ItemClieckd = true;
ClickedNum += 1;
adapter.notifyDataSetChanged();
/*RelativeLayout Rl = (RelativeLayout)arg1.findViewById(R.id.Rv);
ImageView CheckImg = (ImageView)arg1.findViewById(R.id.Checked);
Rl.setBackgroundColor(Color.rgb(201, 50, 39));
CheckImg.setVisibility(View.VISIBLE);*/
//Toast.makeText(getActivity(), String.valueOf(mSelectedItem), Toast.LENGTH_LONG).show();
}
});
CompareButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (ClickedNum < 2) {
Toast.makeText(getActivity(), "Please mark at least 2 items to compare them", Toast.LENGTH_LONG).show();
}
}
});
return rootView;
}
}
thank you
To avoid issues with view recycling in ListViews etc, I include a boolean for checked state in the item data List supplied to the constructor of the ArrayAdapter. I also provide my own interface for handling things like click events on child Views contained in my custom list item layout.
In my example below we handle a checkbox which can be clicked and also a label which can be long clicked:
public class MyListAdapter extends ArrayAdapter<MyItem> {
// interface for handling item child view events
public interface MyListAdapterListener {
void onItemCheckClicked(int index);
void onItemLabelLongClicked(int index);
}
private MyListAdapterListener mMyListAdapterListener;
int layoutResID;
// Constructor
public MyListAdapter(Context context, int resource, List<MyItem> myItems) {
super(context, resource, myItems);
layoutResID = resource;
}
public void setMyListAdapterListener(MyListAdapterListener listener) {
this.mMyListAdapterListener = listener;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// setup the row
View row;
if (convertView == null) {
LayoutInflater inflater = LayoutInflater.from(getContext());
row = inflater.inflate(layoutResID, null);
} else {
row = convertView;
}
// setup the ViewHolder for this item
ViewHolder holder = (ViewHolder) row.getTag();
if (holder == null) {
holder = new ViewHolder(row);
row.setTag(holder);
}
// setup this item's label view
holder.label.setText(getItem(position).label);
// tag this item's label view with position so it can be retrieved in the onLongClick
holder.label.setTag(position);
// set the OnLongClickListener for the this item's label view
holder.label.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
if (mActivityListListener != null) {
// retrieve position from the view's tag, and trigger the listeners onItemLabelLongClicked method
mActivityListListener.onItemLabelLongClicked((Integer)v.getTag());
}
return false;
}
});
// setup this item's checkbox view
holder.checkbox.setChecked(getItem(position).myItemCheckBoolean);
// tag this item's checkbox view with position so it can be retrieved in the onClick
holder.checkbox.setTag(position);
// set the OnClickListener for the this item's checkbox view
holder.checkbox.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mMyListAdapterListener != null) {
// retrieve position from the view's tag, and trigger the listeners onItemCheckClicked method
mMyListAdapterListener.onItemCheckClicked((Integer) v.getTag());
}
}
});
return row;
}
class ViewHolder {
CheckBox checkbox = null;
TextView label = null;
ViewHolder(View row) {
this.checkbox = (CheckBox) row.findViewById(R.id.check_box);
this.label = (TextView) row.findViewById(R.id.item_label);
}
}
}
The MyItem class:
public class MyItem {
public String label;
public boolean myItemCheckBoolean;
}
Using the ArrayAdapter:
public class MyFragment extends Fragment {
....
private List<MyItem> myItems = new ArrayList<MyItem>();
....
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment__my_list, container, false);
lv = (ListView)rootView.findViewById(R.id.my_list);
// For example purposes, fill myItems with dummy data setting all checkboxes initially to false
for (int i = 0; i < 10; i++) {
MyItem myItem = new MyItem();
myItem.label = "Item " + i;
myItem.myItemCheckBoolean = false;
myItems.add(myItem);
}
MyListAdapter adapter = new MyListAdapter(getActivity(), R.layout.my_list_item, myItems);
adapter.setMyListAdapterListener( new MyListAdapter.MyListAdapterListener() {
#Override
public void onItemCheckClicked(int index) {
Log.d("MyFragment", "Item " + index + " Check Clicked");
// toggle the item's boolean
myItems.get(index).myItemCheckBoolean = !myItems.get(index).myItemCheckBoolean;
}
#Override
public void onItemLabelLongClicked(int index) {
Log.d("MyFragment", "Item " + index + " Label LongClicked");
}
}
lv.setAdapter(adapter);
....
return rootView;
}
Additional:
In response to your comment, you can use the adapter to customize the display of your list items as you wish. The version below shows how you might modify the adapter to use an ImageView instead of a CheckBox, and also changes the background color:
public class MyListAdapter extends ArrayAdapter<MyItem> {
// interface for handling item child view events
public interface MyListAdapterListener {
void onItemCheckClicked(int index);
void onItemLabelLongClicked(int index);
}
private MyListAdapterListener mMyListAdapterListener;
int layoutResID;
// Constructor
public MyListAdapter(Context context, int resource, List<MyItem> myItems) {
super(context, resource, myItems);
layoutResID = resource;
}
public void setMyListAdapterListener(MyListAdapterListener listener) {
this.mMyListAdapterListener = listener;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// setup the row
View row;
if (convertView == null) {
LayoutInflater inflater = LayoutInflater.from(getContext());
row = inflater.inflate(layoutResID, null);
} else {
row = convertView;
}
// setup the ViewHolder for this item
ViewHolder holder = (ViewHolder) row.getTag();
if (holder == null) {
holder = new ViewHolder(row);
row.setTag(holder);
}
// setup this item's label view
holder.label.setText(getItem(position).label);
// tag this item's label view with position so it can be retrieved in the onLongClick
holder.label.setTag(position);
// set the OnLongClickListener for the this item's label view
holder.label.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
if (mActivityListListener != null) {
// retrieve position from the view's tag, and trigger the listeners onItemLabelLongClicked method
mActivityListListener.onItemLabelLongClicked((Integer)v.getTag());
}
return false;
}
});
// setup this item's image view based on the current state of the boolean
if (getItem(position).myItemCheckBoolean) {
holder.image.setImageResource(R.drawable.image_a);
} else {
holder.image.setImageResource(R.drawable.image_b);
}
// tag this item's image view with position so it can be retrieved in the onClick
holder.image.setTag(position);
// set the OnClickListener for the this item's image view
holder.image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mMyListAdapterListener != null) {
// retrieve position from the view's tag, and trigger the listeners onItemCheckClicked method
mMyListAdapterListener.onItemCheckClicked((Integer) v.getTag());
}
}
});
// setup this item's background based on the current state of the boolean
if (getItem(position).myItemCheckBoolean) {
holder.layout.setBackgroundColor(Color.red);
} else {
holder.layout.setBackgroundColor(Color.white);
}
return row;
}
class ViewHolder {
ImageView image = null;
TextView label = null;
RelativeLayout layout = null;
// constructor
ViewHolder(View row) {
this.image = (ImageView) row.findViewById(R.id.item_image);
this.label = (TextView) row.findViewById(R.id.item_label);
this.layout = (RelativeLayout) row.findViewById(R.id.item_layout)
}
}
}
As my post states, I can't seem to get my ArrayAdapter to update the whole list despite the call "adapter.notifyDataSetChanged();" Only the last element in the list is updated.
Can someone maby see what I'm doing wrong below??
Here is my custom adapter
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.TextView;
public class WeatherAdapter extends ArrayAdapter<Weather>{
Context context;
int layoutResourceId;
Weather data[] = null;
private WeatherHolder holder;
private Weather weather;
public WeatherAdapter(Context context, int layoutResourceId, Weather[] data) {
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = data;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
holder = null;
if(row == null)
{
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);
holder = new WeatherHolder();
holder.imgIcon = (TextView)row.findViewById(R.id.imgen);
holder.txtTitle = (TextView)row.findViewById(R.id.txtTitle);
row.setTag(holder);
}
else
{
holder = (WeatherHolder)row.getTag();
}
weather = data[position];
holder.txtTitle.setText(weather.getName());
//holder.imgIcon.setText(Double.toString(weather.getBuyingRate()));
return row;
}
public void update(String buttonPressed){
if(buttonPressed == "Köp Kurs"){
holder.imgIcon.setText(Double.toString(weather.getBuyingRate()));//This updates only the last element in list but I want to update every element in the list
}
else if(buttonPressed == "Antal"){ holder.imgIcon.setText(Double.toString(weather.getNrOfSharesInPortfolio()));//This updates only the last element in list but I want to update every element in the list
}
}
static class WeatherHolder
{
TextView imgIcon;
TextView txtTitle;
}
}
And here is my main class, when I call "Update()" method only the last element in the list is updated but not the others. How can I update the whole list instead of just the last element in the list?
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ListView;
public class MainActivity extends Activity {
private ListView listView1;
private Button goButton;
private String[] listheader = {"Köp Kurs","Antal"};
private WeatherAdapter adapter;
private int totalElemInlist = listheader.length;
private int currentelemInList=0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Weather weather_data[] = new Weather[]
{
new Weather("ABB", 56.0, 300),
new Weather("Volvo", 89.0,500),
new Weather("Astra Zeneca", 98.55, 50)
};
adapter = new WeatherAdapter(this,
R.layout.listview_item_row, weather_data);
listView1 = (ListView)findViewById(R.id.listView1);
View header = (View)getLayoutInflater().inflate(R.layout.listview_header_row, null);
listView1.addHeaderView(header);
goButton = (Button) findViewById(R.id.testButton);
goButton.setText(listheader[currentelemInList]);
listView1.setAdapter(adapter);
goButton.setOnClickListener(new OnClickListener() {
public void onClick(View view) {
String buttonPressed = (String) ((Button) view).getText();
goThroughList(buttonPressed);
System.out.println("Button Clicked" + buttonPressed);
}
});
}
private void goThroughList(String buttonPressed){
currentelemInList++;
if(currentelemInList>=totalElemInlist){
currentelemInList=0;
}
goButton.setText(listheader[currentelemInList]);
if(buttonPressed == "Köp Kurs"){
System.out.println("Köp kurs");
adapter.update(buttonPressed);
adapter.notifyDataSetChanged();//This only updates the last element in list
}
else if(buttonPressed == "Antal"){
System.out.println("Antal");
adapter.update(buttonPressed);
adapter.notifyDataSetChanged();//This only updates the last element in list
}
System.out.println(currentelemInList);
}
}
How can I update the whole list instead of just the last element in the list?
You must make your changes happen in getView(). getView() redraws every row as they appear whenever the user scrolls the ListView or notifyDataSetChanged() is called. So the changes must happen in there otherwise they will be erased.
First create a new field variable in your adapter:
private String currentImage;
Second change update() to control the contents on imgIcon:
public void update(String buttonPressed){
currentImage = buttonPressed;
notifyDataSetChanged();
}
Last change getView() to display the current images for each row:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
...
weather = data[position];
holder.txtTitle.setText(weather.getName());
if(currentImage.equals("Köp Kurs")){
holder.imgIcon.setText(Double.toString(weather.getBuyingRate()));
}
else if(currentImage.equals("Antal")){
holder.imgIcon.setText(Double.toString(weather.getNrOfSharesInPortfolio()));
}
return row;
}
(You can also simplify goThroughList(), since the if-else contains the exact same code.)
You should compare string like this.
buttonPressed.equals("Köp Kurs")
I might be wrong , but I think problem is because you are holding only last element in your holder. The member variable "holder" in adapter should be array or list, and you should hold all element, and in update method you should iterate through holder array and change the text
public void update(String buttonPressed){
for(int index =0 ; index < holder.size();index++){
if(buttonPressed == "Köp Kurs"){
holder[index].imgIcon.setText(Double.toString(weather.getBuyingRate()));//This updates only the last element in list but I want to update every element in the list
}
else if(buttonPressed == "Antal"){ holder[index].imgIcon.setText(Double.toString(weather.getNrOfSharesInPortfolio()));//This updates only the last element in list but I want to update every element in the list
}
This should solve your problem