I am currently using the AlertDialog.builder to create a multichoice list for the user (checkboxes). This works great, except we want one of the buttons to deselect all of the others in the list.
builder.setMultiChoiceItems(list, checked,
new DialogInterface.OnMultiChoiceClickListener() {
public void onClick(DialogInterface dialog,
int item, boolean isChecked) {
if(item == ANY_ITEM_BUT_0)
{
((AlertDialog) dialog).getListView().setItemChecked(0, false);
}
}
});
When using "true" it will successfully check the box, but when using false it does not uncheck it (unless i have manually set it to true before hand.) Is there a separate listener I should be using to detect when a user clicks these? It seems to me that there are two checkmarks set, one by the "setItemChecked(0, true);", and one by actually selecting it.
This has been driving me nuts for a couple days now, any help would be greatly appreciated.
OH!!! I forget it to ensure deselect you must change checked to null ;), I had the same issue.
builder.setMultiChoiceItems(list, null, new DialogInterface.OnMultiChoiceClickListener() {
...
To deselect the other items it works fine::
if(item == ANY_ITEM_BUT_0){
for(int i=0; i<items.length;i++){
if (item != ANY_ITEM_BUT_0)
((AlertDialog)dialog).getListView().setItemChecked(i, false);
}
}
Dont think you can change the values in the list since the list-items (checkboxes) are controlled by the builder-object. However, you could simply make the dialog re-initiate when the first item is clicked... by dismissing the dialog that is showing, and create a new one....
If you want to set a check box to not be checked and you need to set the checkedItems array on the call to setMultiChoiceItems(), you need to set the checked array items to false as well. Make sure your checked array is final so you can access it in the listener.
builder.setMultiChoiceItems(list, checked,
new DialogInterface.OnMultiChoiceClickListener() {
public void onClick(DialogInterface dialog,
int item, boolean isChecked) {
if(isChecked && item == ANY_ITEM_BUT_0)
{
for(int i=0; i<list.length;i++){
if (i != ANY_ITEM_BUT_0) {
checked[i] = false;
((AlertDialog)dialog).getListView().setItemChecked(i, false);
}
}
}
}
});
Related
I have a DialogFragment which I am populating with a ListView and a Cursor Adaptor. I was having issue with selecting a radio button and deselecting others. So I did this thing which works. But I wanted to know if I really need a loop there or there is another better way to do it. Here is my code:
viewHolder.radioButton.setOnClickListener(
new View.OnClickListener()
{ #Override
public void onClick(View v) {
for (int i = 0; i < selectionArrayAr.size(); i++){
selectionArrayAr.put(i, false);
}
selectionArrayAr.put(position, true);
notifyDataSetChanged();
}
}
);
I am setting all values to false in the Sparse Array and then finally setting the clicked radio button to true.
i have created check boxes using loop and i want to validate it. Like i just want to check only 3 from the check boxes , when i press on the 4th one it should show an alert and uncheck it.
And i am able to get the alert when i press the 4the one but it is not unchecking.
anybody faced such issue and how did you solve it ?
int i;
for (i = 0; i < 20; i++) {
CheckBox ch = new CheckBox(this);
ch.setTag(Integer.valueOf(i));
ch.setText("CheckBox " + i);
ch.setChecked(false);
ch.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
numChecked++;
} else {
numChecked--;
}
if (numChecked == 4) {
buttonView.setChecked(false);
numChecked--;
// fourth one selected, show your dialog
}
}
});
}
You will also need a global variable call numChecked:
int numChecked = 0;
You will also need to add a .addView(ch) in the loop's end to add the CheckBoxes to your layout.
I would like to check a number of Spinner controls in the Onclick event of a few buttons (if the user moves away from the Activity), and if one or more were not filled out, display a warning message with 2 options to the user:
#Override
public void onClick(View v) {
int i1 = spinner1.getSelectedItemPosition();
(..)
if ((i1 == 0) | (i2 == 0) | (i3 == 0) | (i4 == 0) | (i5 == 0)) {
AlertDialog.Builder alertbox = new AlertDialog.Builder(this);
alertbox.setMessage("Answers missing, what do you want to do?");
final CharSequence[] items = {
"Oops.. let me fix that…",
"I want to leave the app now" };
alertbox.setTitle("Pick an item");
alertbox.setItems(items, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
if (item == 1) {
finish();
// should lead back to the spinner controls on the page
}else if (item == 2){
finish();
android.os.Process.killProcess(android.os.Process
.myPid());
}
}
}).create();
alertbox.show();
However, I just see an empty box with the title, but the message set with setMessage() is not displayed, and I don't get any list items for selection - the box is empty! Any idea what I can do to fix that?
I have been having the same issue, and I found that if I remove the .setMessage line, then the list appears with the title. Not sure why this is though. If you use the .setpositive button, .negative, etc, then you can have a message. I also noticed that google examples all don't use .setMessage with an item list. They only use .setTitle, which doesn't give you that much space.
So, while this doesn't help you if you want a long message, it will get your list visible if that is your main goal.
I've created an array of 5 clickable textviews using a loop, have set their parameters (size, colour, background image, to be clickable etc) and have set an onClickListener and the array is called "myArrayofTVs". Their ids have been set using the loop int (i). I have another predefined array that hold text string, and other textviews are present on the layout. Later on in the onClick method, and as all the buttons/clickable textviews do something very similar, I'd like to be able to do something like:
#Override
public void onClick(View v) {
if(v == myArrayofTVs[i]) { //using 'i' here doesn't seem to work
tv1.setText(myArray2[i]);
tv2.setText(myArray2[i+1];}
etc
etc}
I've tried various differnt ways such as using switch case statements (don't really want to use these as there will be a lot of repeated code and I'll have to add a new case statement each time I want to add new textview/buttons in the future). Is there anyway of using one statement that will handle all the buttons/clickable textviews based on the variable id given or will I have to use a separate case/tag/id statement for each one?
Many thanks in advance!
Add the views to your ViewGroup and use getChildAt(int index) and getChildCount() to create a loop. You can loop all children/views in the viewgroup and you could check with
if(child instanceof TextView)
if they are of the correct type. Then you could cast the views back to a TextView/Button/View and do the thing you want to do.
But it sounds like you want a list of something. So i would suggest using a ListView with a adapter behind it.
I really think you should use the id provided by Android instead of trying to compare objects. The reason your code wouldn't work, if it had a sufficient for loop around it, is somewhat mysterious, but I would try to parallel the switch statements you see in examples as much as possible by comparing ID's and not objects.
for( int i = 0; i < myArrayofTvs.length; i++ )
if(v.getId() == myArrayofTVs[i].getId()) {
tv1.setText(myArray2[i]);
tv2.setText(myArray2[i+1];
}
}
Also obviously you'll want to avoid an array out of bounds error in that second inner statement.
What I did was programmatically inflate my custom layout and used an onClickListener on that button from the custom layout inflated. Then to interact with a specific item I got the parent view of the view being clicked eg. your button and then used that view to change attributes of the view. This is a snippet of my code. The onClick of the alertDialog is where I go about changing values of the newly inflated view.
// if an edit button of numbers row is clicked that number will be edited
if (view.getId() == R.id.NumberRowEditButton)
{
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setTitle("Contact edit");
alert.setMessage("Edit Number");
// Set an EditText view to get user input
final EditText input = new EditText(this);
input.setSingleLine();
alert.setView(input);
alert.setPositiveButton("Ok", new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int whichButton)
{
// get input
Editable value = input.getText();
if(value.length() > 4){
View tempView = (View) view.getParent();
TextView tempTV = (TextView) tempView.findViewById(R.id.numberRowTextView);
String number = tempTV.getText().toString();
tempTV.setText(value.toString());
}
else
{
// ...warn user to make number longer
final Toast msgs = Toast.makeText(ContactEdit.this, "Number must be over 4 digits.", Toast.LENGTH_SHORT);
msgs.setGravity(Gravity.CENTER, msgs.getXOffset() / 2, msgs.getYOffset() / 2);
msgs.show();
}
}
});
alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int whichButton)
{
// cancel the dialog
dialog.cancel();
}
});
alert.show();
}
Hopefully this might help you.
I've spent over a week trying to figure out a way to do a Limited Multi Selection Preference list. Nothing I've tried works. I'm ready to give up on Android if something seemingly simple is so hard. I've been programming a long time and don't remember being beaten up this badly by something like this. I have to assume I am not understanding something basic. I hope someone can point me in the right direction.
Here is the simplest code I can think off that should work. It does not clear the checkbox even when setting it to false, I've tried true as well. Why doesn't that work? If that will not work, what will?
Any help would be most appreciated.
#Override
protected void onPrepareDialogBuilder(Builder builder)
{
CharSequence[] entries = getEntries();
CharSequence[] entryValues = getEntryValues();
if (entries == null || entryValues == null || entries.length != entryValues.length ) {
throw new IllegalStateException(
"ListPreference requires an entries array and an entryValues array which are both the same length");
}
// Added by WJT since we are loading the entries values after instantiation
// we need the clicked indexes to be setup now, they would not have been
// set up in the constructor
if ((mClickedDialogEntryIndices == null) || (mClickedDialogEntryIndices.length == 0))
mClickedDialogEntryIndices = new boolean[getEntries().length];
restoreCheckedEntries();
builder.setMultiChoiceItems(entries, mClickedDialogEntryIndices,
new DialogInterface.OnMultiChoiceClickListener()
{
public void onClick(DialogInterface dialog, int which, boolean val)
{
mDlg = (AlertDialog)getDialog();
mListView = (ListView)mDlg.getListView();
if (val)
{
if (mSelectedCount < mLimit)
{
mClickedDialogEntryIndices[which] = val;
mSelectedCount++;
}
else
{
mListView.setItemChecked(which, false);
Toast.makeText(getContext(),
R.string.newsLimitExceededMessage,
Toast.LENGTH_LONG).show();
} // (mSelectedCount < mLimit)
}
else
{
mClickedDialogEntryIndices[which] = val;
mSelectedCount--;
} // (val)
} // void onClick(DialogInterface dialog, int which, boolean val)
}); // DialogInterface.OnMultiChoiceClickListener()
} // void onPrepareDialogBuilder(Builder builder)
Thanks,
\ ^ / i l l
Here's how I would approach the problem:
Step #1: Get this working in a standalone throwaway test activity. Forget preferences. Forget dialogs. Just focus on the functionality of having a CHOICE_MODE_MULTIPLE ListView where, after a certain number of items are checked, the unchecked items become disabled.
Step #2: Get the functionality from Step #1 working in the form of a custom widget. By this, I mean you would implement a subclass of ListView (I guess...might be some container if there's more to it than a ListView) that bakes in all of what you need from Step #1.
Step #3: Create a custom DialogPreference subclass that uses the custom widget from Step #2.
For example, here is a sample project where I have a custom ColorMixer widget, rolled into a ColorPreference.