I have a listview with number and an image buton with each number. I want to make call on button click to the number in the row. my getview method is
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View rowView = convertView;
ContactStockView sv = null;
if (rowView == null) {
// Get a new instance of the row layout view
LayoutInflater inflater = activity.getLayoutInflater();
rowView = inflater.inflate(
R.layout.activity_row, null);
// Hold the view objects in an object,
// so they don't need to be re-fetched
sv = new ContactStockView();
sv.name = (TextView) rowView.findViewById(R.id.textacti_row1);
sv.number = (TextView) rowView.findViewById(R.id.textacti_row2);
sv.btncall=(ImageButton)rowView.findViewById(R.id.imgbtn_call);
//sv.btncall.setOnClickListener((OnClickListener) activity);
rowView.setTag(sv);
//ImageButton btn=(ImageButton)convertView.findViewById(R.id.btn_call);
/* */
} else {
sv = (ContactStockView) rowView.getTag();
}
// Transfer the stock data from the data object
// to the view objects
ContactStock currentStock = (ContactStock) stocks.get(position);
sv.name.setText(currentStock.getName());
number=currentStock.getNumber();
sv.number.setText(number);
//ImageButton btn=(ImageButton)rowView.findViewById(R.id.imgbtn_call);
sv.btncall.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
//Toast.makeText( activity, number, Toast.LENGTH_SHORT).show();
String phoneCallUri = "tel:"+number;
Intent phoneCallIntent = new Intent(Intent.ACTION_CALL);
phoneCallIntent.setData(Uri.parse(phoneCallUri));
activity.startActivity(phoneCallIntent);
}
});
/* btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
//Toast.makeText( activity, "abc", Toast.LENGTH_SHORT).show();
/*}
});*/
// TODO Auto-generated method stub
return rowView;
}
protected static class ContactStockView {
protected TextView name;
protected TextView number;
protected ImageButton btncall;
}
My log cat on call is
you should declare the string number in get view method not outside it. change
number=currentStock.getNumber();
to
final String number=currentStock.getNumber();
and delete the string(ie,number) from outside getview method
You can't findout the problem that way. You have to debug your getView method.
Do that by
1) double click on the first line of the method on the left of the outer frame to see a small point thay represents a breakpoint.
2) Right click on the project and click Debug as Android application.
3) Using the button F6 (in Eclipse) start moving steps untill you find the specific line you code produce error.
4) Now when you know the line it's easier to find out what happened.
attach the number to the view with setTag, then retrieve it in the click listener. you also don't need a new listener every time, define that once outside the function...
sv.btncall.setTag(number);
then in the onclick listener...
new View.OnClickListener() {
#Override
public void onClick(View v) {
String number = (String) v.getTag();
String phoneCallUri = "tel:"+number;
Intent phoneCallIntent = new Intent(Intent.ACTION_CALL);
phoneCallIntent.setData(Uri.parse(phoneCallUri));
activity.startActivity(phoneCallIntent);
}
}
Related
In my android applicattion i have a list view with custom adapter.The adapter has a textview and two buttons(plus & minus button) like in the image below :
when i click on the plus or minus button the textview value changes...but as soon as i scroll the listview the values are changed of all the textviews.
The code i used is as follows :
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
if(convertView==null)
{
viewHolder=new ViewHolder();//
convertView = inflater.inflate(R.layout.inventory_list_item, null);
viewHolder.txt_product_name = (TextView)convertView.findViewById(R.id.txt_product_name);
viewHolder.txt_product_units = (TextView)convertView.findViewById(R.id.txt_product_units);
viewHolder.txt_price = (TextView) convertView.findViewById(R.id.txt_price);
viewHolder.txt_qty = (TextView) convertView.findViewById(R.id.txt_qty);
viewHolder.btn_minus = (Button)convertView.findViewById(R.id.btn_minus);
viewHolder.btn_plus= (Button)convertView.findViewById(R.id.btn_plus);
convertView.setTag(viewHolder);
}
else
{
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.btn_minus.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
LinearLayout ll = (LinearLayout) v.getParent();
TextView tv = (TextView) ll.getChildAt(1);
int qty = Integer.parseInt(tv.getText().toString());
if(qty == 0)
{
}
else
{
qty = qty - 1;
tv.setText(String.valueOf(qty));
}
}
});
viewHolder.btn_plus.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
LinearLayout ll = (LinearLayout) v.getParent();
TextView tv = (TextView) ll.getChildAt(1);
int qty = Integer.parseInt(tv.getText().toString());
qty = qty + 1;
tv.setText(String.valueOf(qty));
}
});
HashMap<String, String> map = new HashMap<String, String>();
map = data.get(position);
viewHolder.txt_product_name.setText(map.get("ProductName"));
viewHolder.txt_price.setText(map.get("ProductPrice"));
viewHolder.txt_product_units.setText(map.get("ProductUnits"));
return convertView;
}
How do i address this issue?
Please help ! thanks in advance !
Try defining TextView tv inside viewHolder instead of inside click listener
ViewHolder{
TextView tv;
}
Do something like you have done for txt_product_name TextView
You need to use a model class for that . Create getter setter for each element in your list view Whether is String int or status of open and close .And Pass it to constructor of your adapter class .If you already have a model class then add these parameters to it . And change the property of text change on button click And call notifyDataSetChanged() after it . then you just need if-else in your getView() to change the text .Try it and let me know if you still face some problem.
I have created demo according your scenario ,what i did inside onClick i have updated my data and called notifyDataSetChanged();
whatever you did is very long and heavy process;make it simple .just update your data and called notifyDataSetChanged();if you need sample i can provide you my sample
don't update manually the field of textview .always update the data and get updated data and set to textview
Firstly you can't update the plus(+) and minus(-) values in your listview directly as your tried. Because your not handling any position in your code. So it seams if you change one item count (plus or minus) it will effect on the other items as well (or) else it will lose the data after scrolling..
So to achieve your task, you need to follow these steps.
Firstly you need to create a data structure, which holds the positions of your items and count of your items in the list view. Suppose third item in your list view having 5 count (plus values) we can hold both the position and count as well in this data structure.
So, i am taking a HashMap , where key is String.valueOf(position) and Value is count int. like below
HashMap< String,Integers > countDetails= new HashMap< String,Integers >;
You know the keys since it will be from position "0" to listitem.length. Using the key you can get the count values(probably to hold your item cont details for each and every list item).
Why Hashmap: because everytime you change count the new value will be overriden. (Only one unique key is maintained in hashmap).
Usage:: if the user click's the first item minus (-) or plus (+) button you need to hold that count and need to store in the hashmap with the position and count. for example (position = 0, count = 3) --> - clicked on 1st row--> plus (+) items for 3 times like that.
after clicking plus(+) and (-) values in your list item call the notifyDataChanged() in your list so, that it will update the data in listview.
So, this is the idea how you can achieve your implementation, here i am giving a sample code for it .
class AdapterClass extends ArrayAdapter<String> {
HashMap<String,Integers> countDetails = new HashMap<String,Integers>;
// you can use/ declare all your remaining data product here
public AdapterClass(Context c, String[] items, int imgs[]) {
// TODO Auto-generated constructor stub
super(c, R.layout.rowlayout, R.id.quantity, items);
this.context = c;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
if(convertView==null)
{
viewHolder=new ViewHolder();//
convertView = inflater.inflate(R.layout.inventory_list_item, null);
viewHolder.txt_product_name = (TextView)convertView.findViewById(R.id.txt_product_name);
viewHolder.txt_product_units = (TextView)convertView.findViewById(R.id.txt_product_units);
viewHolder.txt_price = (TextView) convertView.findViewById(R.id.txt_price);
viewHolder.txt_qty = (TextView) convertView.findViewById(R.id.txt_qty);
viewHolder.btn_minus = (Button)convertView.findViewById(R.id.btn_minus);
viewHolder.btn_plus= (Button)convertView.findViewById(R.id.btn_plus);
convertView.setTag(viewHolder);
}
else
{
viewHolder = (ViewHolder) convertView.getTag();
}
HashMap<String, String> map = new HashMap<String, String>();
map = data.get(position);
viewHolder.txt_product_name.setText(map.get("ProductName"));
viewHolder.txt_price.setText(map.get("ProductPrice"));
viewHolder.txt_product_units.setText(map.get("ProductUnits"));
viewHolder.btn_minus.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
int pos=position;
HashMap<String,Integers> tmpDetails = new HashMap<String,Integers>;
tmpDetails=countDetails.get(pos);
int count=tmpDetails.get(pos); // probably your getting the previous count for the item
if(count == 0)
{
}
else
{
count = count - 1;
holder.txt_qty.setText(count.toString());
}
countDetails.put(holder.uniqueKey,count); //Key -> String.valueOf(position) and Value -> int count
}
});
viewHolder.btn_plus.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
int pos=position;
HashMap<String,Integers> tmpDetails = new HashMap<String,Integers>;
tmpDetails=countDetails.get(pos);
int count=tmpDetails.get(pos); // probably your getting the previous count for the item
if(count == 0)
{
}
else
{
count = count + 1;
holder.txt_qty.setText(count.toString());
}
countDetails.put(holder.uniqueKey,count); //Key -> String.valueOf(position) and Value -> int count
}
});
return row;
}
}
p.s. I have typed in editor, there might be some compile time error. Also you can store objects of each row against the key so that when you get the count, you can get any other reference too..
I am an android newbie.. I am using a cursor adapter and a listview which has a toggle button and a textview... when I click the toggle button I need to get the click event and the position of the item in the list..
I saw many threads but I dont find a perfect solution that works for me...
finally i decided to set the position in bindview and try to retrieve it on click events.. but when I access the holder.position in click event I am getting null pointer exception.
Please help me with this guys. thanks a lot
public class CalendarListAdapter extends CursorAdapter implements OnClickListener{
protected static class RowViewHolder {
public TextView mTitle;
public ToggleButton mButton;
public int position;
}
protected ListView calListView;
#SuppressWarnings("deprecation")
public CalendarListAdapter(Context context, Cursor c) {
super(context, c);
// TODO Auto-generated constructor stub
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
// TODO Auto-generated method stub
TextView title = (TextView) view.findViewById(R.id.calendarName);
System.out.println("cursor details"
+ cursor.getString(cursor.getColumnIndex(cursor
.getColumnName(1))));
title.setText(cursor.getString(cursor.getColumnIndex(cursor
.getColumnName(1))));
Log.d("click position " , "position is " +cursor.getPosition() );
ToggleButton button = (ToggleButton) view.findViewById(R.id.silentToggle);
button.setOnClickListener(this);
Log.d("click position " , "position is " +cursor.getPosition() );
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
// TODO Auto-generated method stub
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(context.LAYOUT_INFLATER_SERVICE);
View calendarListView = inflater.inflate(R.layout.calendar_list_item, null);
RowViewHolder rowView = new RowViewHolder();
rowView.mTitle = (TextView)calendarListView.findViewById(R.id.calendarName);
rowView.mButton = (ToggleButton) calendarListView.findViewById(R.id.silentToggle);
rowView.position = cursor.getPosition();
rowView.mTitle.setOnClickListener(titleOnClickListener);
rowView.mButton.setOnClickListener(buttonOnClickListener);
return calendarListView;
}
#Override
public void onClick(View view) {
// TODO Auto-generated method stub
Log.d("item clicked", "clicked" );
RowViewHolder holder = (RowViewHolder)view.getTag();
int position = holder.position;
Log.d("common clicked", "clicked -" +position );
}
private OnClickListener titleOnClickListener = new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
RowViewHolder holder = (RowViewHolder)v.getTag();
int position = holder.position;
Log.d("title clicked", "clicked -" +position );
}
};
private OnClickListener buttonOnClickListener = new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
RowViewHolder holder = (RowViewHolder)v.getTag();
int position = holder.position;
Log.d("button clicked", "clicked -" +position );
}
};
}
To be able to use v.getTag() you need two things. In newView you need to do
calendarListView.setTag(rowView);
and in bindView you need to insert the correct data into the holder also:
rowView.position = cursor.getPosition(); // (same as in newView)
For all of this to work together, you also need to make sure that the view you are doing getTag() on is the view that you did setTag on.
In your case that would mean doing this in newView:
rowView.mTitle.setTag(rowView);
rowView.mButton.setTag(rowView);
It would probably be simpler to not use RowViewHolder at all. Instead do this:
In bindView:
int pos = cursor.getPosition();
title.setTag(pos);
button.setTag(pos);
And then in your OnClickListeners do
Integer pos = (Integer) v.getTag();
Good luck!
the answer above with the setTag and getTag worked well for me,
but somehow I realized that the tags not always bring the correct numbers.
after checking ,I found out that my newView function works too many times and thats why all my tags are "0" . if you have that problem,check
here for solution.
Practicing on the ListView, I thought of adding buttons as well to it, rather than showing only content. But in my implementation, the button does not do anything at all.
Plus I was confused whether I could get the position of the button clicked. For now I am just sending the toSend declared inside the OnItemClick in an intent.
listView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
// TODO Auto-generated method stub
final int toSend = position;
TextView refId = (TextView)view.findViewById(R.id.list_id);
TextView refName = (TextView)view.findViewById(R.id.list_name);
TextView refAdd = (TextView)view.findViewById(R.id.list_address);
Button edit = (Button)view.findViewById(R.id.edit);
edit.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
// TODO Auto-generated method stub
Intent i = new Intent(ListActivity.this, EditLayout.class);
i.putExtra("position", toSend);
startActivity(i);
}
});
String sd_id = refId.getText().toString();
String sd_name = refName.getText().toString();
String sd_add = refAdd.getText().toString();
buildAlert(sd_id, sd_name, sd_add);
}
});
You're pretty close. The "inside" setOnClickListener needs to happen when you create the list row view (the view containing id, name, address, edit).
You can do that during getView(). But where to send the clicks? Instead of creating a new onClickListener, use "this" (your activity). Put an onClick() handler in the activity.
Then, when you get a click, the onClick method will execute. Next problem: how do you know which row clicked? The easiest way that comes to mind is to give the button a different id for e ach row - use the row index (you might need to start at 1 rather than 0 - be warned).
Finally, given the row id, it's easy to start your "nested" activity.
Hope this helps.
(added later)
I do it like this; you'll need to define a layout for your row view:
class MyActivity extends Activity implements View.OnClickListener
{
public void onCreate (Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView (R.layout.my_page);
ListView list = (ListView)findViewById (android.R.id.list);
MyArrayAdapter adapter = new MyArrayAdapter (this, <your array of data>);
list.setAdapter (adapter);
}
#Override
public void onClick(View v)
{
int buttonId = v.getId();
if (buttonId is within range)
... do what you need to do with the click ...
}
private class MyArrayAdapter extends ArrayAdapter<MyData>
{
private Activity act;
//-----------------------------------------------------------------------------
public MyArrayAdapter (Activity act, MyData array)
{
super (act, R.layout.list_row, array);
this.act = act;
}
//-----------------------------------------------------------------------------
#Override
public View getView (int position, View convertView, ViewGroup parent)
{
ViewGroup rowView = (ViewGroup)convertView;
if (rowView == null)
{
LayoutInflater inflater = act.getLayoutInflater();
rowView = (ViewGroup) inflater.inflate (R.layout.list_row,
parent, false);
}
Button button = (Button)rowView.findViewById (R.id.is_member);
button.setId (position+1); // add one to avoid 0 as an id.
button.setOnClickListener (act);
// set field values here -- not shown
return rowView;
}
}
}
// Adding menuItems to ListView
mylist=(ListView)findViewById(R.id.lstshowcatalogue);
ListAdapter adapter=new LazyAdapter(this, menuItems,getApplicationContext());
mylist.setAdapter(adapter);
mylist.setOnItemClickListener(new OnItemClickListener(){
#Override
public void onItemClick(AdapterView<?> Parent, View view, int position,
long id) {
// TODO Auto-generated method stub
if(position>=0)
{
TextView c = (TextView) view.findViewById(R.id.txtlargeimage);
largeimage = c.getText().toString();
ImageView thumb_image=(ImageView)view.findViewById(R.id.ivcatalouge); // thumb image
thumb_image.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(largeimage.length()>0)
{
Intent i=new Intent();
i.setClass(getApplicationContext(), FrmShowSingleImage.class);
i.putExtra("largeimage", largeimage);
startActivity(i);
//Toast.makeText(getApplicationContext(), largeimage, Toast.LENGTH_SHORT).show();
largeimage="";
}
}});
//Toast.makeText(getApplicationContext(), largeimage, Toast.LENGTH_SHORT).show();
}
}});
I want to open a new activity on thumb image onclick. It works fine when First Select item. If I click thumb image without selecting item it getting old value
Here is my updated listview adapter
public View getView(int position, View convertView, ViewGroup parent) {
View vi=convertView;
if(convertView==null)
vi = inflater.inflate(R.layout.list_item, null);
TextView name = (TextView)vi.findViewById(R.id.name); // name
TextView desc = (TextView)vi.findViewById(R.id.desciption); // collection
TextView cost = (TextView)vi.findViewById(R.id.cost); // cost
TextView category = (TextView)vi.findViewById(R.id.txtcategory); // cost
TextView spec = (TextView)vi.findViewById(R.id.txtspec); // cost
TextView largeimg = (TextView)vi.findViewById(R.id.txtlargeimage); // cost
ImageView thumb_image=(ImageView)vi.findViewById(R.id.ivcatalouge); // thumb image
thumb_image.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
TextView c = (TextView) v.findViewById(R.id.txtlargeimage);
Intent i=new Intent();
i.setClass(mCtx, FrmShowSingleImage.class);
i.putExtra("largeimage", c.getText());
mCtx.startActivity(i);
}});
HashMap<String, String> song = new HashMap<String, String>();
song = data.get(position);
// Setting all values in listview
name.setText(song.get(FrmShowCatlogue.KEY_MODEL));
desc.setText(song.get(FrmShowCatlogue.KEY_COLLECTION));
cost.setText(song.get( FrmShowCatlogue.KEY_MRP));
category.setText(song.get( FrmShowCatlogue.KEY_CATEGORY));
spec.setText(song.get( FrmShowCatlogue.KEY_SPEC));
largeimg.setText(song.get( FrmShowCatlogue.KEY_LARGE));
largeimg.setVisibility(View.GONE);
try
{
String filename=song.get(FrmShowCatlogue.KEY_IMAGES.toString());
filename="thumbs/" + filename;
// get input stream
InputStream ims = mCtx.getAssets().open(filename);
// load image as Drawable
Drawable d = Drawable.createFromStream(ims, null);
// set image to ImageView
thumb_image.setImageDrawable(d);
}
catch(IOException ex)
{
//thumb_image.setVisibility(View.GONE);
}
return vi;
}
Now I am getting null pointer exception on thumb click.
I have removed thumb_image onclick from SetOnItemClickListener of listview
If your list item click doent get recognized,it is because your custom list item has many clickable items(imagebutton,button...) in it. make android:focusable=false for those items and your listview click will be allright.
then as JaredLua said you should add the onClickLisener() in the adapter since its for the thumb_image only and not for the listitem as a whole
I think maybe you should put thumb_image.setOnClickListener(...) into your Adapter's getView method, so correct largeimage will be set to thumb_image's click event when corresponding item is shown.
I have use this from Here.. :)
From this three link you can get clear idea,,Hope this help.
See Here
If you want to use Image Button in your list view
Refere this last :)
In my android app I have two List Views and two buttons.On clicking first button, first List View will be visible and on second button second List View will be visible.In one List View I will have list of items and in second List View there will be ADD button. Now clicking on ADD button my first List View will be visible and user can select items to add in second List View. I have done it successfully. But my problem is, by clicking on second button List View is appearing but there are no data which are added from First List View. Below is my code.
What am I missing?
final ListView lv = getListView();
LayoutInflater inflater = getLayoutInflater();
final View header = getLayoutInflater().inflate(R.layout.footer, null);
lv.addFooterView(header, null, false);
btnCollege.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
String listItems[] = {};
final ArrayAdapter<String> string = new ArrayAdapter<String>(getBaseContext(),android.R.layout.simple_list_item_1);
lv.setAdapter(string);
Button btnAdd = (Button) header.findViewById(R.id.btnAdd);
btnAdd.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (j == 0)
{
lv.setVisibility(View.VISIBLE);
header.setVisibility(View.VISIBLE);
j = 1;
}
else if (j == 1)
{
lv.setVisibility(View.INVISIBLE);
header.setVisibility(View.INVISIBLE);
j = 0;
}
else {}
lv1.setVisibility(View.VISIBLE);
lv1.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
// TODO Auto-generated method stub
String selected = lv1.getItemAtPosition(arg2).toString();
string.add(selected);
string.notifyDataSetChanged();
setListAdapter(string);
}
});
}
});
}
});
The view is not getting updated. use handlers for updating listview. That would help you solve the issue