The View for a ListView two buttons (for example to perform: call, send SMS). I want to set up a listeners for clicks on the buttons. It is my understanding that if I set up a OnItemSelectedListener, I won't know which of the two buttons was clicked.
When I set up listeners for a button, when I click on it, I get the listener of the corresponding button that is in the last item in the list (not the one I clicked on) (which makes sense programmatically) but this is not what I want. I can tell because it always calls the number that belongs to the last item in the list.
Any tips on how set up OnClick for multiple views in each item ?
#NonNull
#Override
public View getView(final int position, #Nullable final View convertView, #NonNull ViewGroup parent) {
LayoutInflater inf = ((Activity)context).getLayoutInflater();
View view = inf.inflate(R.layout.place , parent , false);
name = view.findViewById(R.id.name);
type = view.findViewById(R.id.type);
minAge = view.findViewById(R.id.minAge);
open = view.findViewById(R.id.open);
close = view.findViewById(R.id.close);
distance = view.findViewById(R.id.distance);
phone = view.findViewById(R.id.phone);
picture = view.findViewById(R.id.picture);
btnCall = view.findViewById(R.id.btnCall);
final Place place = placeList.get(position);
// btnCall.setOnClickListener(this);
// I tried both setups with the same result.
// the button is always the one belonging to the last item in the list.
btnCall.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String s = btnPhone.getText().toString();
}
});
// another button would have its own OnClick
name.setText(place.getName());
type.setText(place.getType());
minAge.setText(Integer.toString(place.getMinAge()));
open.setText(Integer.toString(place.getOpen()));
close.setText(Integer.toString(place.getClose()));
distance.setText(Integer.toString(place.getDistance()));
phone.setText(place.getPhone());
int id = context.getResources().getIdentifier("place"+position,"drawable" ,
((Activity)context).getPackageName());
//row_pic.setImageResource(id);
return view;
}
#Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_DIAL);
intent.setData(Uri.parse("tel:" + phone.getText()));
if (intent.resolveActivity(context.getPackageManager()) != null) {
context.startActivity(intent);
}
if (intent.resolveActivity(context.getPackageManager()) != null)
{
context.startActivity(intent);
}
}
I found the solution just after posting the question.
USE TAGS to pass data.
'''
phone.setText(place.getPhone());
btnCall.setTag(phone.getText().toString());
btnCall.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String s = (String) ((Button) view).getTag().toString();
// now I can call the correct number
}
});
'''
Related
I am trying to convert my app to android version, and I am a bit new in android. I have a list view in which the items include buttons. It is a user list and you can follow each user, when the button is clicked, only in the item including the button, the button text should turn in to "followed". Retrieving the list works fine, but with my below code the button text is not changing. How can I make this happen? Thank you very much.
private class MyListAdapter extends ArrayAdapter<String> {
public MyListAdapter() {
super(getActivity().getApplicationContext(), R.layout.fragment_users_cell, myItemList);
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View cellView = convertView;
if (cellView == null){
cellView = getActivity().getLayoutInflater().inflate(R.layout.fragment_users_cell, parent, false);
}
profileBtn = (Button) cellView.findViewById(R.id.fragment_users_cell_profileBtn);
followBtn = (Button) cellView.findViewById(R.id.fragment_users_cell_followBtn);
profileBtn.setText(myItemList.get(position));
profileBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
System.out.println(myItemList.get(position));
System.out.println(position);
}
});
followBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
System.out.println(myItemList.get(position));
profileBtn.setText("followed");
}
});
return cellView;
}
}
You have to update your dataset and refersh the list after you make changes so that it reflects the latest changes. In your case the text changes.
followBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
profileBtn.setText("followed");
myItemList.add(position, "followed");//Change your dataset
notifyDataSetChanged(); //And refresh the adapter
}
});
you need to change the value in myItemList so that next time when view load, the value from list set as text on profile button comes which ix followed
i.e. you need to update the list on click of follow button and notify the ListView.
followBtn.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
System.out.println(myItemList.get(position));
myItemList.get(position).set("followed");
profileBtn.setText("followed");
}
});
I have a ListView dynamically inflated with custom layout that has different text views and a button. On button click, a user specifies options in a dialog window and the data returned to the selected item in the list view.
I expect the data to get inserted in text views of the corresponding item in the list view. However, when the list has fewer item that are not scrollable, no data gets inserted at all when dialog is closed and when it has enough items to be scrollable, the data gets inserted into text views of wrong item in the list. I don't know what I am doing wrong, here is my code:
public double COST_EM = 0.00, COST = 0.00, NUM_CO = 0.00;
private Spinner mPSpinner, mMediSpinner;
private ArrayAdapter<String> pmedi, numCo;
private TextView mPTv, mCoTv, mSubMain, mSubTv;
#Override
public View getView(final int position, View convertView,
ViewGroup parent) {
View view = null;
LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.item_custom_layout, parent, false);
// Display image in the ImageView widget
TempP tphoto = tempPList.get(position);
mPTv = (TextView) view.findViewById(R.id.p_tv_po);
mCoTv = (TextView) view.findViewById(R.id.co_tv_po);
mSubMain = (TextView) view.findViewById(R.id.sub_list);
mModify = (Button) view.findViewById(R.id.modify_btn_po);
mModify.setOnClickListener(new View.OnClickListener() {
// calculate the order cost
protected void calculateCost() {
mSub = ((COST_EM + COST) * NUM_CO);
mSubtv.setText("" + Double.toString(mSub));
}
#Override
public void onClick(View v) {
mDialog = new Dialog(PCustom.this);
mDialog.setContentView(R.layout.item_custom_dialog);
mDialog.setTitle("Modify specifications");
mPSpinner = (Spinner) mDialog.findViewById(R.id.ces_sp_dialog);
mSubTv = (TextView) mDialog.findViewById(R.id.sub_der_dialog);
// set spinner adapters (code truncated for brevity)
pmedi = new ArrayAdapter<String>(MyApplication
.getContext(), R.layout.spinner_style, pmedi);
mPSpinner.setAdapter(pmedi);
mPSpinner
.setOnItemSelectedListener(new OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> arg0,
View arg1, int pos, long arg3) {
if (mPSpinner.getSelectedItem() == "Glossy") {
COST = 2000.00;
} else if (mPSpinner
.getSelectedItem() == "Standard") {
COST = 1500.00;
} else if (mPSpinner
.getSelectedItem() == "Other") {
COST = 1000.00;
}
// calculate the cost
calculateCost();
}
public void onNothingSelected(
AdapterView<?> arg0) {
}
});
Button save = (Button) mDialog
.findViewById(R.id.save_btn_po_dialog);
Button cancel = (Button) mDialog
.findViewById(R.id.cancel_btn_po_dialog);
save.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// String newnumber =
// mobileNumber.getText().toString();
mPTv.setText("" + mPSpinner
.getSelectedItem());
mCoTv.setText((String) mNCoSpinner
.getSelectedItem());
mSubMain.setText(Double.toString(mSub));
mDialog.dismiss();
}
});
cancel.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mDialog.dismiss();
}
});
mDialog.show();
}
});
return view;
}
The method getView() return one item View each time ListView call it with a specific "position" parameter, so the times it is called is no less than the number of items it has. So, your member variables mPTv, mCoTv and mSubMain will be reassigned many times and finally have their values in the final calling of getView().That's why you meet that problem.
To solve your problem, you need to have the correct TextViews when the "save Button" is clicked.Here is how to find those correct TextViews:
In the OnClickListener of mModify Button, the "v" parameter in the method onClick(View v) is the same instance of mModify itself. So, you can use it to find those correct TextViews. Perhaps you can set the item root View as its tag and get the root View in onClick(View v) and then use it to find all those correct TextViews. Here is how to change your code:
mModify = (Button) view.findViewById(R.id.modify_btn_po);
// set the root view as the tag of "modify button".
mModify.setTag(view);
mModify.setOnClickListener(new View.OnClickListener() {
// calculate the order cost
protected void calculateCost() {
mSub = ((COST_EM + COST) * NUM_CO);
mSubtv.setText("" + Double.toString(mSub));
}
#Override
public void onClick(View v) {
// retrieve the root view here, it's the root view of the item on which you
// clicked the "modify button".
View view = (View)v.getTag();
// find the correct TextViews here.
mPTv = (TextView) view.findViewById(R.id.p_tv_po);
mCoTv = (TextView) view.findViewById(R.id.co_tv_po);
mSubMain = (TextView) view.findViewById(R.id.sub_list);
BTW, you didn't optimize your ListView, so it may not scroll smoothly, but this is not what caused your problem.You can refer to this:
How to optimize Android ListView?
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;
}
}
}
First of all, I'm a beginner in android programming. So dont be too harsh :P
Anyway, I have a recycling ListView, containing an Image and a Text per List Item.
Let's say there are 100 different Items. Every Item clicked leads me to my Activity "DetailActivity.class" with the "detail_layout.xml". Now I want to configurate this layout depending on which Item was clicked.
TestActivity.java:
ArrayList<String> list = new ArrayList<String>();
for(int i = 0; i <= 99; i++) {
list.add(detail_array[i]);
//detail_array[] contains Strings which are used to add Items to the list.
}
private ListView myList = (ListView)findViewById(R.id.list);
myList.setAdapter(new MyCustomAdapter(TestActivity.this,list));
MyCustomAdapter.java:
public class MyCustomAdapter extends BaseAdapter {
private ArrayList<String> mListItemsTV;
private LayoutInflater mLayoutInflater;
public View getView(int position, View view, ViewGroup viewGroup) {
ViewHolder holder;
if (view == null) {
holder = new ViewHolder();
view = mLayoutInflater.inflate(R.layout.list_item, null);
holder.itemName = (TextView) view.findViewById(R.id.list_item_text_view);
view.setTag(holder);
} else {
holder = (ViewHolder)view.getTag();
}
String stringItem = mListItemsTV.get(position);
if (stringItem != null) {
if (holder.itemName != null) {
holder.itemName.setText(stringItem);
ImageView imageView = (ImageView) view.findViewById(R.id.list_item_image_view);
if(holder.itemName.getText() == "SomeName") {
imageView.setImageResource(R.drawable.somedrawable);
}
return view;
}
To be honest, I've got those from some kind of tutorial and I guess I know whats happening there^^
Now, how can I manage to get which Item was clicked? I tried it several times with "setOnClickListener" but it never seems to work. How do I use this? Should I use this? Where do I have to use it?
The basic idea is listview is generally dynamic so you will have a collection of an arbatrary number of items that you want to register with a listener. Oclicklistener will not work unless you register each item separate (not a good idea). Use onitemclicklistener to register the collection this link should help. http://www.ezzylearning.com/tutorial.aspx?tid=1351248&q=handling-android-listview-onitemclick-event
You'll want to use setOnItemClickListener. This is an example on how it's used. You'll need to adapt it to your code. But you can see how you would reference an individual item in the list.
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, final View view,
int position, long id) {
final String item = (String) parent.getItemAtPosition(position);
view.animate().setDuration(2000).alpha(0)
.withEndAction(new Runnable() {
#Override
public void run() {
list.remove(item);
adapter.notifyDataSetChanged();
view.setAlpha(1);
}
});
}
});
}
I'll fix the formatting when I get home. On mobile ATM. If anyone wants to edit the code feel free.
If you don't want to use an adapter then try this:
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
switch(position){
/*
* The case is the list position
*/
case 0:
break;
case 1:
break;
}
}
I have a collection of items in an ArrayList. I add them to a customer adapter as follows:
this.m_adapter = new MyAdapter(this, R.layout.myitem,
itemCart.m_items);
I have a delete button for each of these items in my list, but I am not sure how to connect the delete button's onClick() with the original item in the ArrayList. Can someone please explain how to do this or point me to a tutorial where I can read up on this? Non-sarcastic/non-condescending responses are greatly appreciated.
You can call the remove() method on your ArrayList
itemCart.m_items.remove(<index of element to remove>);
this.m_adapter.notifyDataSetChanged();
And then you need to call notifyDataSetChanged(); on your adapter to update the ListView
You can get the index of the element by simply noticed that a list view is a collection of child views (the rows of the list).
You can do something like this in your code:
(inside the getView() method, for example)
row.setOnLongClickListener(new OnLongClickListener()
{
#Override
public boolean onLongClick(View view) {
remove(listView.indexOfChild(view));
return true;
}
}
That is, the solution is simply use indexOfChild(View) method to get index of child view that user (long) pressed.
Here's my solution so far:
In the getView() method I do something like this:
deleteButton.setTag(position);
It looks like getTag() returns an Object. So I converted the position int into an Integer object first. It appears to be working.
In the OnClickListener() I do the following:
items.remove(index.intValue());
So far, so good.
Following works for me:
/* Read values from resource into an array */
String[] strColorValues = getResources().getStringArray(R.array.colors);
ArrayList<String> list = new ArrayList<String>();
for (int i = 0; i < strColorValues.length; i++) {
list.add(strColorValues[i]);
}
ArrayAdapter adapterColors = new ArrayAdapter(getActivity(), android.R.layout.simple_spinner_item, list);
adapterColors.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinnerColors.setAdapter(adapterPermissionLevels);
spinnerColors.setOnItemSelectedListener(this);
/* Remove first element from the adapter and notify dataset changed. */
String item = spinnerColors.getItemAtPosition(0).toString();
adapterColors.remove(item);
adapterColors.notifyDataSetChanged();
Here's my Code.
transfer.setItemPosition(position, items.get(position).getAddMode());
the transfer here is the instance of the main class. everytime i click the deletebutton, it then pass the position of the that item on the list in this line.
public View getView(final int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
final Context context = getContext();
LayoutInflater vi = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.listviewitem_layout, null);
}
ItemEntry item = items.get(position);
if (item != null) {
TextView textViewName = (TextView) v.findViewById(R.id.textViewItemName);
ImageView imageViewDelete = (ImageView) v.findViewById(R.id.imageViewDeleteIcon);
imageViewDelete.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
transfer.showDialog(4);
transfer.setItemPosition(position, items.get(position).getAddMode());
}
});
if (textViewName != null) {
textViewName.setText(item.getItemName());
}
if(imageViewDelete != null) {
imageViewDelete.setImageResource(R.drawable.delete);
}
}
return v;
}
}
Remove by position:
mainAdapter.remove(mainAdapter.getItem(position));
Such as the last one:
mainAdapter.remove(mainAdapter.getItem(mainAdapter.getCount() - 1));
Try these codes of lines it was very helpful for me
holder.image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
list.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, list.size());
}
});
If you use context menu, then you can get
AdapterContextMenuInfo and this structure gives index and id of clicked element.
It seems that you can get the index (or position) of a clicked item in the ListView as follows:
listview.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
listview.remove(listview.getItem(position).toString());
}
}
So you need to listen for clicks on Views and then take the index from that.