Android ListItem with radio button - android

My page has a listView and a OK button. Each listItem has an id and RadioButtonGroup.
I am using SimpleCursorAdapter to load the list.
What I would like to do is when I click on OK, I want to get individual id and radio button selection from that radioButtonGroup.
How do I do it ?

You can add a clicklistener to your list:
list.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
RadioButton button = (RadioButton) view.findViewById(R.id.RadioButton);
button.getId();
}
});

You have to extend the SimpleCursorAdapter class and inside the newView / bindView methods you need to check for the state of the radioButtonGroup. In order to do that you need to set a listener for your radio button group using the OnCheckedChangedListener. I have some source code example that I used on a personal app. Bare in mind that I'm listening to checkboxes but is should be perfectly straight forward to adapt to a radio button group.
#Override
public void bindView(View view, Context context, Cursor cursor) {
NoteHolder holder = (NoteHolder) view.getTag();
holder.titleView.setText(cursor.getString(titleColIndex));
holder.modifiedView.setText(mUtils.formatDate(mUtils.formatDateFromString (cursor.getString(modifiedColIndex), context, "dd-MM-yyyy"), "dd-MM-yyyy"));
holder.priorityView.setImageResource(mUtils.getPriorityResourceId(cursor.getInt(priorityColIndex)));
Typeface tf = Typeface.createFromAsset(context.getAssets(), "fonts/ARLRDBD.TTF");
holder.titleView.setTypeface(tf);
holder.modifiedView.setTypeface(tf);
final int pos = cursor.getPosition();
final long id = cursor.getLong(idColIndex);
holder.checkbox.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
checkChecked(v, pos, id);
}
});
view.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
rowCheckChecked(v, pos, id);
}
});
holder.checkbox.setChecked(itemChecked.get(pos));
}
private static class NoteHolder {
TextView titleView;
TextView modifiedView;
ImageView priorityView;
CheckBox checkbox;
}
private void checkChecked(View v, int pos, long id){
CheckBox cb = (CheckBox) v.findViewById(R.id.delete_checkbox);
if (cb.isChecked())
{
itemChecked.set(pos, true);
mSelectedIDs.add(id);
}
else if(!cb.isChecked())
{
itemChecked.set(pos, false);
if(mSelectedIDs.contains(id))
mSelectedIDs.remove(id);
}
}
I would advise you to use a viewHolder pattern too. Specially if your app is going to have many list items. You can read more about it here and see an example here, you can also see it implemented in the code I've put above.
Hope that helps.

Related

how to get access to all items of a dynamically inflated layout in android

I dynamically inflate a view which contains spinner and edit text.how to understand which spinner listener is currently working.
count = 1;
buttonadd.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
count++;
Spinner spin_securityType = (Spinner) MyItem[count].findViewById(R.id.spin_securityType);
EditText ed_amount = (EditText) MyItem[count].findViewById(R.id.ed_amount);
SpinnerLogoAdapter spinnerAdapter33 = new SpinnerLogoAdapter(Activity.this.getApplicationContext(),
securityTpeIcons, securityTpeitems);
spin_securityType.setAdapter(spinnerAdapter33);
MainItemLayout.addView(MyItem[count]);
spin_securityType.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView << ? > parent, View view, int position, long id) {
//how to know which spinner is selected ????????
}
#Override
public void onNothingSelected(AdapterView << ? > parent) {}
});
}
});
what i need is add a validation on one which validates all 5 items at a same time.I have tried setTag but it does not work.please help
I found the solution myself. I programatically added id for each spinner and access it inside the listener to know which spinner is selected.For that i added id to the spinner
spin_securityType.setId(id); ex:id=1
and access it inside spin_securityType.setOnItemSelectedListener()
spin_securityType.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView parent, View view, int position, long id) {
int Id=parent.getId();//shows id as 1
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});

Hide/unhide layout in list item

I have a layout for list item, which consists of two LinearLayouts. What I want to achieve is: when item is clicked, second LinearLayout should become visible/gone, depending on the current visibility.
I am experimenting with this code:
getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
view.getViewById(R.id.id_of_the_second_linear_layout).setVisibility(View.GONE);
}
});
However when item is clicked, several other linear layouts (in different items) become visible/hidden. Why?
Update:
Adapter:
public class ExpensesCursorAdapter extends SimpleCursorAdapter implements SimpleCursorAdapter.ViewBinder {
public ExpensesCursorAdapter(Context context, Cursor cursor) {
super(context, R.layout.single_expense, cursor,
new String[]{
ExpenseContract._AMOUNT,
CategoryContract._NAME,
ExpenseContract._DATE
},
new int[]{
R.id.expense_amount,
R.id.expense_category,
R.id.expense_date
},
CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
setViewBinder(this);
}
public View getView(int position, View convertView, ViewGroup viewGroup) {
View v = super.getView(position, convertView, viewGroup);
final View expandablePanel = v.findViewById(R.id.expandable_panel);
expandablePanel.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
expandablePanel.setVisibility(view.getVisibility() == View.GONE ? View.VISIBLE : View.GONE);
}
});
return v;
}
#Override
public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
if (columnIndex == cursor.getColumnIndex(ExpenseContract._AMOUNT)) {
return handleAmountView((TextView) view, cursor);
}
else ...
return false;
}
private boolean handleAmountView(TextView view, Cursor cursor) {
TextView textView = (TextView) view;
Double amount = ExpenseDbHelper.getAmount(cursor);
String formattedAmount = new DecimalFormat("##.00").format(amount);
textView.setText(formattedAmount);
return true;
}
}
Each item has LinearLayout already added in XML, I want to toggle visibility flag, if possible.
You are writing your logic on wrong places. You want to listen clicks of views inside listitem. Write your logic in Adapter's getView method. In your getView logic can be like this
ll1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
ll2.setVisibility(View.GONE);
}
});
ll2.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
ll1.setVisibility(View.GONE);
}
});
Something like this.
When you scroll through the list items, some layouts will hide and un-hide, in that case, if you are targeting just one view to be visible at a time (that is just considering one cell at a time), then you could maintain the position of the item clicked, or the id, since you are using a cursorAdapter. Else if you are considering more than one cell then maintain a list where in you store each id of the cell that has been tapped on.
Pass the list or the single position value to the adpater, and in the getview compare the id or position and then perform the visiblity code.
Hope this hint helps.

Delete ListView row in Custom Adapter

I want to delete a row from my list view on click of "delete" button. My listview item has following things placed horizontally: TextView-1,TextView-2,TextView-3,ImageButton-delete button. Now when I click delete button, the row should be deleted from the view. Below is the adapter code;
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
View view = (View) v.getParent();
TextView tv = (TextView) view.findViewById(R.id.item_name);
String item = tv.getText().toString();
String tableno = mListItems.get(0).getTableNumber();
orderDetailsDB = new OrderDetailsDBAdapter(
getApplicationContext());
orderDetailsDB.deleteItem(item,tableno);
I tried by setting Individual textviews to blank but its not working.
holder.itemName.setText("");
holder.amount.setText("");
holder.quantity.setText("");
I read couple of posts and they suggest to remove item from my list(mListItems) and then do adapter.notifyDataSetChanged();. Problem is I am not using array adapter for populating list view but using Custom adapter, so unable to get the position for item to be deleted. Please advise. thanks.
First write below line in your adapter's getView method.
button.setTag(position)
in onClick method
#Override
public void onClick(View v) {
int position = (Integer)v.getTag();
yourarraylistObject.remove(position);
// your remaining code
notifyDataSetChanged();
}
Just use remove() to remove list item from the adapter
for your reference
adapter = new MyListAdapter(this);
lv = (ListView) findViewById(android.R.id.list);
lv.setAdapter(adapter);
lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> a, View v, int position, long id) {
AlertDialog.Builder adb=new AlertDialog.Builder(MyActivity.this);
adb.setTitle("Delete?");
adb.setMessage("Are you sure you want to delete " + position);
final int positionToRemove = position;
adb.setNegativeButton("Cancel", null);
adb.setPositiveButton("Ok", new AlertDialog.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
MyDataObject.remove(positionToRemove);
adapter.notifyDataSetChanged();
}});
adb.show();
}
});
What you can do in order to get the position that you want to delete is to pass that into your listener:
// inside custom adapter
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
.....
deleteButton.setOnClickListener(new MyClickListener(position);
}
private class MyClickListener implements OnClickListener
{
int position = -1;
public MyClickListener(final int position)
{
this.position = position;
}
#Override
public void onClick(View v) {
// do your delete code here
notifyDataSetChanged();
}

How to get ListViewItem's ViewHolder from AlertDialog's click handler when AlertDialog was created in ListViewItem's button click?

My ListViewItems have delete buttons in them. From those button's click events I want to show a confirmation dialog before deleting the item via it's ID from the database. The ID is stored in the item's ViewHolder.
How can I access the item's ViewHolder from the AlertDialog's click handler? Here is the relevant code. Compiler chokes on "V" inside onClick(DialogInterface dialog, int whichButton).
I could store the ID in the button's tag but that feels awkward.
I'm targetting minimum API level 8 but let me know if higher API levels have a solution for this. It's my first Android program so there may very well be an obvious solution.
private static class MyAdapter extends CursorAdapter {
//.....
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
View view = View.inflate(context, R.layout.my_detail, null);
MyViewHolder holder = new MyViewHolder();
holder.deleteButton = (Button) view.findViewById(R.id.deleteButton);
holder.deleteButton.setOnClickListener(deleteButtonClickListener);
holder.editButton = (Button) view.findViewById(R.id.editButton);
holder.editButton.setOnClickListener(editButtonClickListener);
holder.nameTextView = (TextView) view
.findViewById(R.id.nameTextView);
holder.itemId = cursor.getLong(cursor
.getColumnIndex(MyData.ID_COLUMN));
view.setTag(holder);
return view;
} // newView()
//.....
private OnClickListener deleteButtonClickListener = new OnClickListener() {
public void onClick(View v) {
new AlertDialog.Builder(_context)
.setTitle("Delete?")
.setMessage("Delete item?")
.setIcon(android.R.drawable.ic_dialog_alert)
.setPositiveButton(android.R.string.yes,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int whichButton) {
MyViewHolder holder = (MyViewHolder) ((View) v
.getParent()).getTag();
long itemId = holder.itemId;
_MyData.deleteItem(itemId);
}
}).setNegativeButton(android.R.string.no, null)
.show();
} // onClick()
}; // deleteButtonClickListener
//.....
}
Your code actually looks pretty good, the only change needed is that v needs to be declared final, like so:
private OnClickListener deleteButtonClickListener = new OnClickListener()
{
public void onClick(final View v) { }
}
The reason for this is due to how Java implements closures. v should be final so that our implementation of DialogInterface.OnClickListener in the setPositiveButton() has access to the variable.
first implement the onclickevtn
private static class MyAdapter extends CursorAdapte mplements android.view.View.OnClickListener
then set the event for particular
holder.editButton.setOnClickListener(this);
then override the class function
#Override
public void onClick(View v) {
if(R.id.editButton==v.getId()){
....do something
}else
}
this will work after struggling i got this way
Tag the itemid in delete button so that you can retrieve it in dialogbox
E.g
holder.deleteButton.setTag(cursor.getLong(cursor
.getColumnIndex(MyData.ID_COLUMN)));
And retrieve it in dialogbox
long itemId = v.getTag();

Android: ListView elements with multiple clickable buttons

I've a ListView where every element in the list contains a TextView and two different Buttons. Something like this:
ListView
--------------------
[Text]
[Button 1][Button 2]
--------------------
[Text]
[Button 1][Button 2]
--------------------
... (and so on) ...
With this code I can create an OnItemClickListener for the whole item:
listView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> list, View view, int position, long id) {
Log.i(TAG, "onListItemClick: " + position);
}
}
});
However, I don't want the whole item to be clickable, but only the two buttons of each list element.
So my question is, how do I implement a onClickListener for these two buttons with the following parameters:
int button (which button of the element has been clicked)
int position (which is the element in the list on which the button click happened)
Update: I found a solution as described in my answer below. Now I can click/tap the button via the touch screen. However, I can't manually select it with the trackball. It always selects the whole list item and from there goes directly to the next list item ignoring the buttons, even though I set .setFocusable(true) and setClickable(true) for the buttons in getView().
I also added this code to my custom list adapter:
#Override
public boolean areAllItemsEnabled() {
return false;
}
#Override
public boolean isEnabled(int position) {
return false;
}
This causes that no list item is selectable at all any more. But it didn't help in making the nested buttons selectable.
Anyone an idea?
The solution to this is actually easier than I thought. You can simply add in your custom adapter's getView() method a setOnClickListener() for the buttons you're using.
Any data associated with the button has to be added with myButton.setTag() in the getView() and can be accessed in the onClickListener via view.getTag()
I posted a detailed solution on my blog as a tutorial.
This is sort of an appendage #znq's answer...
There are many cases where you want to know the row position for a clicked item AND you want to know which view in the row was tapped. This is going to be a lot more important in tablet UIs.
You can do this with the following custom adapter:
private static class CustomCursorAdapter extends CursorAdapter {
protected ListView mListView;
protected static class RowViewHolder {
public TextView mTitle;
public TextView mText;
}
public CustomCursorAdapter(Activity activity) {
super();
mListView = activity.getListView();
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
// do what you need to do
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
View view = View.inflate(context, R.layout.row_layout, null);
RowViewHolder holder = new RowViewHolder();
holder.mTitle = (TextView) view.findViewById(R.id.Title);
holder.mText = (TextView) view.findViewById(R.id.Text);
holder.mTitle.setOnClickListener(mOnTitleClickListener);
holder.mText.setOnClickListener(mOnTextClickListener);
view.setTag(holder);
return view;
}
private OnClickListener mOnTitleClickListener = new OnClickListener() {
#Override
public void onClick(View v) {
final int position = mListView.getPositionForView((View) v.getParent());
Log.v(TAG, "Title clicked, row %d", position);
}
};
private OnClickListener mOnTextClickListener = new OnClickListener() {
#Override
public void onClick(View v) {
final int position = mListView.getPositionForView((View) v.getParent());
Log.v(TAG, "Text clicked, row %d", position);
}
};
}
For future readers:
To select manually the buttons with the trackball use:
myListView.setItemsCanFocus(true);
And to disable the focus on the whole list items:
myListView.setFocusable(false);
myListView.setFocusableInTouchMode(false);
myListView.setClickable(false);
It works fine for me, I can click on buttons with touchscreen and also alows focus an click using keypad
I don't have much experience than above users but I faced this same issue and I Solved this with below Solution
<Button
android:id="#+id/btnRemove"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_toRightOf="#+id/btnEdit"
android:layout_weight="1"
android:background="#drawable/btn"
android:text="#string/remove"
android:onClick="btnRemoveClick"
/>
btnRemoveClick Click event
public void btnRemoveClick(View v)
{
final int position = listviewItem.getPositionForView((View) v.getParent());
listItem.remove(position);
ItemAdapter.notifyDataSetChanged();
}
Probably you've found how to do it, but you can call
ListView.setItemsCanFocus(true)
and now your buttons will catch focus
I am not sure about be the best way, but works fine and all code stays in your ArrayAdapter.
package br.com.fontolan.pessoas.arrayadapter;
import java.util.List;
import android.content.Context;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ImageView;
import br.com.fontolan.pessoas.R;
import br.com.fontolan.pessoas.model.Telefone;
public class TelefoneArrayAdapter extends ArrayAdapter<Telefone> {
private TelefoneArrayAdapter telefoneArrayAdapter = null;
private Context context;
private EditText tipoEditText = null;
private EditText telefoneEditText = null;
private ImageView deleteImageView = null;
public TelefoneArrayAdapter(Context context, List<Telefone> values) {
super(context, R.layout.telefone_form, values);
this.telefoneArrayAdapter = this;
this.context = context;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.telefone_form, parent, false);
tipoEditText = (EditText) view.findViewById(R.id.telefone_form_tipo);
telefoneEditText = (EditText) view.findViewById(R.id.telefone_form_telefone);
deleteImageView = (ImageView) view.findViewById(R.id.telefone_form_delete_image);
final int i = position;
final Telefone telefone = this.getItem(position);
tipoEditText.setText(telefone.getTipo());
telefoneEditText.setText(telefone.getTelefone());
TextWatcher tipoTextWatcher = new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void afterTextChanged(Editable s) {
telefoneArrayAdapter.getItem(i).setTipo(s.toString());
telefoneArrayAdapter.getItem(i).setIsDirty(true);
}
};
TextWatcher telefoneTextWatcher = new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void afterTextChanged(Editable s) {
telefoneArrayAdapter.getItem(i).setTelefone(s.toString());
telefoneArrayAdapter.getItem(i).setIsDirty(true);
}
};
tipoEditText.addTextChangedListener(tipoTextWatcher);
telefoneEditText.addTextChangedListener(telefoneTextWatcher);
deleteImageView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
telefoneArrayAdapter.remove(telefone);
}
});
return view;
}
}
I Know it's late but this may help, this is an example how I write custom adapter class for different click actions
public class CustomAdapter extends BaseAdapter {
TextView title;
Button button1,button2;
public long getItemId(int position) {
return position;
}
public int getCount() {
return mAlBasicItemsnav.size(); // size of your list array
}
public Object getItem(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = getLayoutInflater().inflate(R.layout.listnavsub_layout, null, false); // use sublayout which you want to inflate in your each list item
}
title = (TextView) convertView.findViewById(R.id.textViewnav); // see you have to find id by using convertView.findViewById
title.setText(mAlBasicItemsnav.get(position));
button1=(Button) convertView.findViewById(R.id.button1);
button1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//your click action
// if you have different click action at different positions then
if(position==0)
{
//click action of 1st list item on button click
}
if(position==1)
{
//click action of 2st list item on button click
}
});
// similarly for button 2
button2=(Button) convertView.findViewById(R.id.button2);
button2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//your click action
});
return convertView;
}
}
Isn't the platform solution for this implementation to use a context menu that shows on a long press?
Is the question author aware of context menus? Stacking up buttons in a listview has performance implications, will clutter your UI and violate the recommended UI design for the platform.
On the flipside; context menus - by nature of not having a passive representation - are not obvious to the end user. Consider documenting the behaviour?
This guide should give you a good start.
http://www.mikeplate.com/2010/01/21/show-a-context-menu-for-long-clicks-in-an-android-listview/

Categories

Resources