Multiple choice alert dialog with custom row layout - android

I need to create an AlertDialog with multiple choice items but I'm having some trouble trying to set a custom layout file to the internal ListView.
For single choice items I use a constructor that takes a ListAdapter as parameter and this way I can set the proper layout resource for each row:
builder.setSingleChoiceItems(new ArrayAdapter<String>(getActivity(),
R.layout.list_item_single_choice_answer, items), checkedItem,
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
checkedItem = which;
toggleEditTextAnswer(checkedItem == (items.length - 1));
dialog.dismiss();
}
});
The problem is that there's no constructor for setMultiChoiceItems that accepts a ListAdapter as parameter when creating a multiple choice list.
I need to set a custom layout for each row because I use drawable selectors for setting the row background and text color.
Any ideas?
PS. here is the AlertDialog source code for more information.
https://android.googlesource.com/platform/frameworks/base.git/+/android-4.2.2_r1/core/java/android/app/AlertDialog.java

Well, I know I should create a custom Dialog but right now I don't have the time to do it ... so this is how I hacked this problem:
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// Set the adapter
builder.setAdapter(
new ArrayAdapter<String>(getActivity(),
R.layout.list_item_multiple_choice_answer, items), null)
// Set the action buttons
.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int id) {
dialog.dismiss();
}
});
AlertDialog alertDialog = builder.create();
ListView listView = alertDialog.getListView();
listView.setAdapter(new ArrayAdapter<String>(getActivity(),
R.layout.list_item_multiple_choice_answer, items));
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
CheckedTextView checkedTextView = (CheckedTextView) view;
checkedItems[position] = !checkedTextView.isChecked();
}
});
listView.setDivider(null);
listView.setDividerHeight(-1);
alertDialog.setOnShowListener(new DialogInterface.OnShowListener() {
#Override
public void onShow(DialogInterface dialog) {
setCheckedItems(((AlertDialog) dialog).getListView());
}
});
alertDialog.show();
First I set the adapter with the items and the instead of calling setMultiChoiceItems I get the ListView object from the Dialog and then configure it myself.

I would recommend that you create your own dialog class like this:
Customizing dialog by extending Dialog or AlertDialog
How to create a Custom Dialog box in android?
This way you will have full control over your dialog and you can customize it any way you want.
Also if you still have issues with your list view after that you can customize your list view items completely: (You can only affect the background and text in a small way through xml and selectors without doing your custom implementation)
http://www.androidhive.info/2012/02/android-custom-listview-with-image-and-text/
Try it out, it may seem hard but when you do it once it will be piece of cake and will do wonders for you in your future development projects.

Related

Android Studio, Remove ListView Item without affecting another Item

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

Custom row Layout for a Multiple Choice Dialog

I would like to implement a Custom Multiple Choice Dialog, so following the directions from this answer, this is what I did:
I created the xml for my row, which is a CheckedTextView
<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceListItemSmall"
android:gravity="center_vertical"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:textColor="#000000"
android:fontFamily="sans-serif-condensed"
style="?android:textAppearanceSmall"
android:background="?android:attr/activatedBackgroundIndicator"
android:minHeight="?android:attr/listPreferredItemHeightSmall"
android:checkMark="?android:attr/listChoiceIndicatorMultiple"
android:clickable="true"/>
Now, my Dialog
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setAdapter(
new ArrayAdapter<String>(getActivity(),
R.layout.dialog_list_item, tables), null)
// Set the action buttons
.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int id) {
dialog.dismiss();
}
});
AlertDialog alertDialog = builder.create();
alerDialog.show();
As you can see, I have not implemented an setOnItemClickListener yet, but I do not know how though. However, the Dialog looks fine. How can I call a ClickListener for each of the CheckedTextView?
Than you very much
The way that #Rahul Gupta suggested works after implementing a ListView and OnItemClickListener, but if the ListView contains too many items, the Views that are not shown are going to be "checked" as well. I suppose the Views are not yet generated until the user actually scrolls down and see the rest of the items.
The way that I made it work was creating a Layout with a single ListView and setting the value of choice mode to CHOICE_MODE_MULTIPLE. In that case, I don't have to deal with each item, but I can retrieve an array of the items selected by using listview.getCheckedItemPositions()
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater li = LayoutInflater.from(getActivity());
View view= li.inflate(R.layout.listview_dialog, null);
builder.setView(view);
builder.setTitle(title);
listView = (ListView) view.findViewById(R.id.listview);
ArrayAdapter<String> ad = new ArrayAdapter<String>(getActivity(), R.layout.dialog_list_item , R.id.text2, tables);
listView.setAdapter(ad);
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
listView.setDivider(null);
builder.create();
Yes, you can implement thee onClickListener for your CheckedTextView.
You just have to find its reference. Now as it is in your dialog, you will have to do this :-
CheckedTextView dialogCheckedTextView = (CheckedTextView ) alertDialog.findViewById(R.id.yourcheckedtextboxid);
dialogCheckedTextView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//TODO
}
});

Android Listview dialog doesn't disapear after choosing an item

I've tried to create a list view dialog to display a list of choose. My code is shown below:
LayoutInflater factory=LayoutInflater.from(this);
final View stuckLevelDialogView=factory.inflate(R.layout.report_stuck_dialog, null);
final ListView stuckLevelListViewForDialog=(ListView)stuckLevelDialogView.findViewById(R.id.report_stuck_dialog_listview);
final String[] stuckLevelList=new String[]{"1 - You can move freely","2 - You have to be aware of your movement","3 - You can move slowly","4 - There is a traffic jam","5 - There is a serious traffic jam"};
ArrayAdapter<String> adapterForDialog=new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, android.R.id.text1, stuckLevelList);
stuckLevelListViewForDialog.setAdapter(adapterForDialog);
final AlertDialog.Builder stuckLevelDialog=new AlertDialog.Builder(this);
stuckLevelDialog.setTitle("What stuck level is this point?");
stuckLevelDialog.setView(stuckLevelDialogView);
stuckLevelDialog.show();
However, when I choose an option, the onItemClick is executed, but the listview dialog doesn't disappear, I have to press back button manually. I've tried to debug the code for a whole day, but it has not been solved yet. Please help me. Thank in advanced!
I think you need to dismiss() the dialog in your onItemClick listener as below:
stuckLevelListViewForDialog.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> p_arg0, View p_arg1,
int p_arg2, long p_arg3) {
stuckLevelDialog.dismiss();
}
});
Use stuckLevelDialog.dismiss; at the end of onItemClick.
You can set setSingleChoiceItems in your alert dialog box with your items list, which will show a list with a radio buttons. If you want to add buttons you can else once user select any items you can dismiss the dialog.
new AlertDialog.Builder(this)
.setSingleChoiceItems(array, -1, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// here you can do your functionality and can dismiss dialog as well
dialog.dismiss();
}
})
.show();

How do I make a Button to create a new spinner on click

I want to create a form that allows the user to choose as many languages he\she knows (at least one)
I don't want to create an infinite number of Spinner, I want to create a button ("+" button)
that when the user click on it it will create a new spinner that will allow the user to choose another language.
How can I do it?
tnx
button.setOnClickListener(new onClickListener()
{
onClick(View v)
{
Spinner spinner = new Spinner(YourActivity.this);
layout.addView(spinner);
}
});
layout - your parent layout
just implement the Spinner as well, but setVisibility(GONE) and when you click the button change the visibility
you can fill your language data in an arry and set dialogs items with this array.
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(R.string.pick_color);
.setItems(R.array.colors_array, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// The 'which' argument contains the index position
// of the selected item
}
});
return builder.create();
}

How to display an arraylist in AlertDialog

i'm trying to get an arraylist on alert dialog but i can see the list items only if i click them. any idea whats wrong with the below code .any suggestions pls....
ArrayList<String> matches = data.getStringArrayListExtra(
RecognizerIntent.EXTRA_RESULTS);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
final ArrayAdapter<String> aa1=new ArrayAdapter<String>(getApplicationContext(), android.R.layout.simple_list_item_single_choice, matches);
builder.setSingleChoiceItems(aa1, 0, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
numbers.add(aa1.getItem(item));
aa.notifyDataSetChanged();
dialog.dismiss();
}
});
alert = builder.create();
alert.show();
I believe this is caused by a bug when using the default themes and AlertDialog.Builder.
You should be able to work around it by copying the android.R.layout.simple_list_item_single_choice layout xml out of the platform and creating a local layout file with the android:textColor properties overridden to something other than themed text color attributes.
Just use this one
android.R.layout.simple_spinner_dropdown_item
simple dialog here try this. Just you have to pass string or charsequence array to it shows simple dialog..

Categories

Resources