I would like to open a custom dialog when someone clicks on a listview entry. That dialog will need to know the text that was clicked on in order to display additional information on that particular entry. Can anyone point me in the right direction on how to accomplish that?
Thanks!
On the ListActivity, override the onListItemClick method. There, you will get the position of the item that was clicked. As you said you want to know the text that is on the item that was clicked, I suppose you have a simple List. In that case, I guess you have, for instance, an array with strings to populate the list.
public void onListItemClick(ListView parent, View v, int position,
long id) {
String itemText = items[position]);
}
So, in this case I'm supposing you have an array of Strings called items. The next step would be to create a Dialog, which can be done this way:
public void onListItemClick(ListView parent, View v, int position,
long id) {
String itemText = items[position]);
new AlertDialog.Builder(this)
.setTitle("Title for " + itemText)
.setMessage("Custom message for "+itemText)
.setNeutralButton("Close", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dlg, int sumthin) {
// do whatever you want to do
}
}).show();
}
By the way... if you want to receive nice answers here, make sure you provide nice questions. By "nice question" I mean something with a little bit of your code, so that we can get a better idea of how to help you ;)
Related
I am making a ToDo List and have troubles with deleting an item from ListView.
If the User has done one thing on his list, he can click on that item and it will be either striked through, or the strike trhough will be undone:
lv.setOnItemClickListener(new AdapterView.OnItemClickListener(){
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
TextView tv = (TextView) view;
int i_strikethrough = tv.getPaintFlags();
if(i_strikethrough == 1297){
tv.setPaintFlags(tv.getPaintFlags() & (~Paint.STRIKE_THRU_TEXT_FLAG));
} else if (i_strikethrough == 1281){
tv.setPaintFlags(tv.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
}
}
});
If the user makes a long click, a message will pop up and he can choose to delete this item:
lv.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener(){
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view, final int position, long id) {
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context);
alertDialogBuilder.setTitle("Delete");
alertDialogBuilder.setMessage("Are you sure you want to delete?");
alertDialogBuilder.setCancelable(false);
alertDialogBuilder.setPositiveButton("Yes", new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface dialogInterface, int i)
{
adapterInhalt.remove(adapterInhalt.getItem(position));
}
});
alertDialogBuilder.setNegativeButton("No", new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface dialogInterface, int i)
{
dialogInterface.cancel();
}
});
AlertDialog alertDialog = alertDialogBuilder.create();
alertDialog.show();
return true;
}
});
Now, my problem is the following:
Imagine the second Item is striked through but the third is not.
If i delete the second Item, then the third Item is at second place and is striked through. But it should not be striked through.
I hope that you understand my problem and that you can help me solving this issue.
I hope this picture will help you understanding the issue:
A helping Picture
You aren't implementing a list view properly. List views recycle views. This means they reuse the same views and put different positions in your list into them. This provides very efficient UI code. It also means that if you make any changes to the view outside of getView of your adapter that those changes will be applied to the wrong item when you remove or scroll.
The write way to make a listview is that if you want to update the UI of any position, you change the model of that position. THen you tell the adapter that it needs to update by calling notifyDataSetChanged(). The getView function will then get called to redraw each visible element and should apply the strike through.
You should define a class for your items, that has a boolean field for strike status. for example:
public class MyItem{
String name;
boolean isStriked;
}
then you can check if an item is striked through on adapter's getView() method. you can increase the cohesion in your code this way. BTW I recommend using RecyclerView as it has predefined methods and animations for item deletion
I have a ListView that contains items with checkboxes that should behave sometimes like a CHOICE_MODE_MULTIPLE and sometimes like a CHOICE_MODE_SINGLE. What I mean is for certain items in the list, when selected certain other items needs to be deselected whilst other can remain selected.
So when item A is checked I can find in my data the item B that needs to be unchecked but how do I get the UI to refresh to show this as I (I believe) cannot find the actual View that represents B but just it's data?
It sounds like you're off to a good start. You're right that you should be manipulating the underlying data source for item B when A is clicked.
Two tips that may help you:
Your getView() method in the Adapter should be looking at your data source and changing convertView based on what it finds. You cannot find the actual View that represents B because in a ListView, the Views are recycled and get reused as different data needs to be displayed. Basically, when an item is scrolled off the list, the View that was used gets passed to the getView() function as convertView, ready to handle the next element's data. For this reason, you should probably never directly change a View in a ListView based on user input, but rather the underlying data.
You can call notifyDataSetChanged() from within your adapter to signal that somewhere the underlying data has been changed and getView() should be called again for the elements currently displayed in your list.
If you're still having trouble, feel free to post some code that illustrates the specific problem that you're having. It's much easier to provide concrete advice when the problem is better defined. Hope this helps!
you can use singleChoice alartDialog, i have used like:
private int i = 0; // this is global
private final CharSequence[] items = {"Breakfast", "Lunch", "Dinner"}; // this is global
Button settings = (Button)view.findViewById(R.id.settings);
settings.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(final View v) {
AlertDialog.Builder builder = new AlertDialog.Builder(v.getContext());
//Title of Popup
builder.setTitle("Settings");
builder.setSingleChoiceItems(items, i,
new DialogInterface.OnClickListener() {
// When you click the radio button
public void onClick(DialogInterface dialog, int item){
i=item;
}
});
builder.setPositiveButton("Confirm",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
if (i == 0) {
//it means 1st item is checked, so do your code
}
if (i == 1) {
//it means 2nd item is checked, so do your code
} /// for more item do if statement
}
});
//When you click Cancel, Leaves PopUp.
builder.setNegativeButton("Cancel", null);
builder.create().show();
}
});
i have initialized i=0, so that for the very first time when user click on settings button, the first item is selected. and after then when user select other item, i have saved the i value so that next time when user click settings button, i can show user his/her previously selected item is selected.
I come across and solve this question today.
public class ItemChooceActivity extends Activity implements OnItemClickListener {
private int chosenOne = -1;
class Madapter extends BaseAdapter {
.....
.....
#Override
public View getView(final int position, View convertView,
ViewGroup parent) {
// TODO Auto-generated method stub
if (chosenOne != position) {
set the view in A style
} else {
set the view in B style
}
return convertView;
}
}
#Override
public void onItemClick(AdapterView<?> arg0, View view, int position,
long arg3) {
,,,,
chosenOne = position;
adapter.notifyDataSetChanged();
,,,
}
}
UPDATE
The original question i asked was about my long id value but because you guys were right in the way u said i had the correct id i removed my error. Thanks for the help. read my answer for more detail.
1) My app uses the local android SQLiteDatabase and has three tables. I have no problems for two of the tables but turns out my third one is presenting some issues because of my column declarations are public static final string COLUMN_NAME = "name"; ,etc.
My Activities are not extending the ListActivity so that I can have custom lists and listviews for each activity.
I am getting my listview by listview = (ListView) findViewById(R.id.myList); and adding a listener to the listview by listview.setOnItemClickListener(ListListener); Then here is my method for the list listener:
OnItemClickListener ListListener = new OnItemClickListener(){
public void onItemClick(AdapterView<?> arg0, View v, int position,
final long id)
{
AlertDialog.Builder dialog = new AlertDialog.Builder(ExerciseList.this)
.setIcon(R.drawable.edit)
.setTitle("Update Selected Exercise")
.setMessage("Would you like to update the current Exercise? Click continue to proceed.")
.setPositiveButton("Continue", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface arg0, int arg1) {
final Intent i = new Intent(getBaseContext(), AddExercise.class);
i.putExtra(ExerciseDbAdapter.KEY_ROW_ID, id);
startActivityForResult(i, EDIT_EXERCISE);
}
})
.setNegativeButton("Back", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
dialog.show();
}
};
This above method is just a working on list item click listener!
Intent.putExtra("Key",value) is right way to put the data in intent so
i.putExtra("INSERT THE KEY HERE",ExerciseDbAdapter.KEY_ROW_ID, id);
Okay guys so i found the issue with my application and you were all right. I was getting the correct row id from the application.
I however was passing another data member through my intent causing the setRowIdFromIntent() method to change the id from null to 0. or from not null to 0.
Basically no matter what the value i was passing it was being set to 0 from my setRowIdFromIntent() method because of the data member i passed through. Therefore the above code is almost irrelevant to my problem.
So if you want a working on click list listener the one above will definitely help you pass the correct id to your new activity. Sorry again for this confusion I had on my side. Thanks again for all other postings!
I am new to android programming. I need some help here. I have used this site example on creating a listview. What I want to achieve is when the user clicks a particular row, the row clicked will perform its respective action. (Eg. When clicked row 1 will show a toast. When clicked row 2 will direct the user to another new view, etc.)
I have set a OnItemClickListener to the listview but am lost on how to do it. Any help will be appreciated. Thanks!
Below is my code:
.......
final ListView list = new ListView(this);
list.setOnItemClickListener(new OnItemClickListener(){
#Override
public void onItemClick(Adapter<?> arg0, View v, int i, long l){
// At implementation
}
});
.......
It looks like you're on the right track, everything should be clearer with onItemClick's parameter names :
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Toast.makeText(getApplicationContext(), "Clicked row " + position,
Toast.LENGTH_SHORT).show();
}
So you actually get the position of the item clicked, and can have a different action for each item.
To get the index of the selected item:
int selected_item = myListView.getPositionForView(view);
or to get the string:
String chosen_item = (myListView.getItemAtPosition(selected_item).toString());
If your class is extending ListActivity replace "myListView" with "this".
I'm trying to identify a view that has been clicked in an expandableListView. When I set an OnItemLongClickListener I get an argument that shows me the position of the clicked view inside the list. However, it also counts child views. I'd like it to count only groups, so when a group was clicked I can determine which one it was. Is there a way to do that?
No, the long parameter is not the packed value, this is the ID generated by your adapter (getCombinedChildId()). Attempting to interpret an ID, even if you generate it in a certain way would be a bad idea. Id is an id.
I believe the right way is to use ExpandableListView.getExpandableListPosition(flatPos) method. Your "pos" argument passed to the listener is, in fact, flat list position. getExpandableListPosition() method returns the packed position which can be then decoded into separate group and child positions using the static methods of ExpandableListView.
I have hit this problem myself today so I am describing the solution I have found working for me.
The long id parameter passed by the onItemLongLongClick method is a packed value.
You can retrieve group position with ExpandableListView.getPackedPositionGroup(id)
Child position is obtained with ExpandableListView.getPackedPositionChild(id).
If Child == -1 then the long click was on the group item.
Below is an example listener class demonstrating unpacking of id.
private class expandableListLongClickListener implements AdapterView.OnItemLongClickListener {
public boolean onItemLongClick (AdapterView<?> p, View v, int pos, long id) {
AlertDialog.Builder builder = new AlertDialog.Builder(ctx);
builder.setTitle("Long Click Info");
String msg = "pos="+pos+" id="+id;
msg += "\ngroup=" + ExpandableListView.getPackedPositionGroup(id);
msg += "\nchild=" + ExpandableListView.getPackedPositionChild(id);
builder.setMessage(msg);
builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) { }
} );
AlertDialog alert = builder.create();
alert.show();
return true;
}
}