I have a multiplechoice dialog on my activity. I have a boolean array to keep track of which items are selected from the dialog. So I want each time an item is clicked to make the corresponding place on my array true. The array is being created in the onCreateDialog before the return.
public Dialog onCreateDialog(int id) {
userlistlocal=getuserlist(username);
boolean[] usernamechecked=new boolean[userlistlocal.length/3];
Arrays.fill(usernamechecked,false);
return new AlertDialog.Builder(Newevent.this)
.setIcon(R.drawable.ic_menu_invite)
.setTitle("Add People")
.setMultiChoiceItems(userselectionlistlocal,
null,new DialogInterface.OnMultiChoiceClickListener() {
public void onClick(DialogInterface dialog, int whichButton,
boolean isChecked) {
/* User clicked on a check box do some stuff */
usernamechecked[whichButton]=isChecked;<-------HERE
}
})
.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
/* User clicked Yes so do some stuff */
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
/* User clicked No so do some stuff */
}
})
.create();
}
But when I put in the onClick method my boolean array it says it has to be final(Cannot refer to a non-final variable usernamechecked inside an inner class defined in a different method). I dont know what to do
You cannot access your array if it is not declared final. But if it is declared final you have to consider that you can't modify it any more.
A method to resolve this problem is to define the OnMultiChoiceClickListener not as an anonymous inner class. For example you could define it as a inner class in the same class or even as a separate class.
you defined usernamechecked inside the onCreateDialog method, it only exists inside the scope of this method. You should define it as a member of your activity class or of the inner class. Since its size is dependent on a call to getuserlist, which i assume is a method of your activity class, i would add it as a member of your activity class although this is up to you.
Define usernamechecked as a member of your activity class as:
private boolean usernamechecked[];
I'd also move
userlistlocal=getuserlist(username);
usernamechecked=new boolean[userlistlocal.length/3];
Arrays.fill(usernamechecked,false);
to your onCreate Method (or some other initialization method) if possible as it looks like it has nothing to do with the dialog creation but this is just a style / maintainability issue.
Related
I'm working on an android app and my requirement is that, I need to display the cursor values into alertdialog and let the user choose an item from the list and the value selected should be returned to the calling Activity.In my app, based on the student info, the cursor holds the values of courses he is taking. So the user should be able to choose one of the courses and then that value should be returned to the Activity that called alertdialog. Can you please let me know how to proceed on this.I've looked at multiple examples and none seems to work exactly.
Here is my sample code
final AlertDialog.Builder builder = new AlertDialog.Builder(view.getContext());
final Cursor courses=dbConnector.getCourses(student);
builder.setTitle("Enter Course");
builder.setCursor(courses, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int itemSelected) {
if (courses.moveToPosition(itemSelected)) {
String text=courses.getString(0);
Toast.makeText(getApplicationContext(),
"You selected: "+text,
Toast.LENGTH_SHORT);
builder.show();
}
courses.moveToFirst();
}
},"course");
builder.create();
createRow(sview, student, pass,text);
Now I want to return the text variable to the Calling Activity but, here it is local to the onClick() method. How can we do that without having to extend any DialogFragment class.
I suggest you calling a method of the class inside overridden onClick method and do whatever you like with that because the method will be in the Activity like here
#Override
public void onClick(DialogInterface dialogInterface, int itemSelected) {
myMethod(itemSelected);
}
private void myMethod(int selectedItem){
//Do whatever with that selected item
}
I have a ListView with each row consisting of a TextView and a CheckBox.
The user is allowed to click on each TextView, and once he does a Dialog is presented to him where he is expected to either choose Yes or No.
When he chooses Yes, another activity is presented to him where he needs to enter data.
I am implementing all this inside a base adapter class, so inside the base adapter I created the AlertDialog and handled it's OnClickListeners.
Here is the problem: I need to use startActivityForResult in order to get back the data that the user will enter in the new activity, and like I said above, I have done so in the BaseAdapter. Now, how can I get the data from the new activity back inside the BaseAdapter? I researched various sources and found out that one cannot start an Intent directly from a BaseAdapter class, but instead needs to reference the Intent to the calling activity like below:
((Activity) mContext).startActivityForResult(intent, 1);
This would then result in having the the onActivityResult() method in the adapter Activity and not inside the BaseAdapter.
I need to leave the code inside the BaseAdapter for various reasons.
The value I need to retrieve is a simple boolean that if it results to true, will tick the CheckBox next to the selected TextView.
How could I implement this? What alternatives do you guys suggest? I tried creating a method inside the BaseAdapter so that I can call it from the "main" Activity at the OnActivityResult() but the CheckBox that I need to tick is returning null at that point; the reason being quite obvious.
I would appreciate any help on this matter.
Inside BaseAdapter class
final AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
builder.setTitle("Materials");
builder.setMessage("Did you require any materials to fix this error?");
builder.setPositiveButton("Yes", new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface dialog, int which)
{
String clickedError;
clickedError = holder.text.getText().toString();
Intent intent = new Intent(mContext, Material.class);
intent.putStringArrayListExtra("materialList", materialList);
intent.putExtra("clickedError", clickedError);
intent.putExtra("repairID", repairID);
((Activity) mContext).startActivityForResult(intent, 1);
}
});
builder.setNegativeButton("No", new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface dialog, int which)
{
if(checkbox.getTag() == v.getTag())
{
checkbox.setChecked(true);
}
}
});
builder.show();
// Method to tick the checkbox.
public void TickBox(CheckBox cb)
{
cb.setChecked(true);
}
The main activity containing OnActivityResult()
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
if(resultCode == RESULT_OK)
{
boolean moreThanOne = data.getBooleanExtra("moreThanOne", false);
if(moreThanOne)
{
CheckBox cb = adapter.checkbox;
adapter.TickBox(cb);
}
else
{
// ....
}
}
}
Create a Callback listener inside your BaseAdaper, inside that method write Intent code,
For updating it later Create a method inside the BaseAdapter which will gets called from onActivityResult.
u can update ur checkbox from ur activity.... TRY this
when user click the listview send the listItem position to ur new activity.AND return the same value in ur old activity in onActivityResult.
then in onActivityResult **
use the same layout that u r using when creating listView
RelativeLayout itemLayout = (RelativeLayout)mListViewObject.getChildAt(i);
CheckBox cb = (CheckBox)itemLayout.findViewById(R.id.checkBox);
cb.setChecked(RESULT);
I show dialog of checkboxes (list retrieved from DB) to allow user select, which rows remove. Because android dialog caching, I need to refresh count and names of checkboxes.
In my onCreateDialog:
dialog = new AlertDialog.Builder( this )
.setTitle( "Remove Items" )
.setMultiChoiceItems( items, _selections, new OnMultiChoiceClickListener(){public void onClick (DialogInterface dialog, int which, boolean isChecked){}} )
.setPositiveButton("Smazat", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.dismiss();
deleteRow(_selections);
} })
.setNegativeButton("Storno", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.dismiss();
} })
.create();
How refresh values (items,_selections) in onPrepareDialog?
I tried invalidate views, hoping that force android to load items againg(dont work neither), but I think its bad choice as well as removing dialog and recreating.
protected void onPrepareDialog(final int id, final Dialog dialog) {
switch (id) {
case REMOVE_DIALOG_ID:
ListView lv = ((AlertDialog) dialog).getListView();
lv.invalidateViews();
break;
}
Thanks for any ideas!
When you create a list of items using AlertDialog.Builder, it internally takes that and creates a ListAdapater that is dependent on the type of data you passed. Since "items" in your example doesn't look like a resource ID, I'm assuming it's either a CharSequence[] or a Cursor. If you provide more information about what "items" is, I can provide a more concrete example.
For CharSequence[] (like String[]) data, Builder creates an ArrayAdapter instance.
For Cursor data, Builder creates a CursorAdapter
You will need to obtain a reference to this ListAdapter using getListView().getAdapter() on the AlertDialog instance.
For a Cursor, you can get away with calling notifyDataSetChanged() after you have called requery() to update the data set.
Since you can't "update" an array with new data (changing the pointer to a new instance is not the same thing...the instance that the adapter is pointing to stays unchanged), this case is a little more work. You will need to call the add(), clear(), etc. methods of the adapter to remove invalid items and add the updates ones. With the adapters data set fully updated, you may now call notifyDataSetChanged().
Hope that Helps!
I spent lot of time to search for same solution and eventually fixed my problem with simple stuff after trying to use onPrepareDialog too
I use the removeDialog(int) function of the Activity. When a dialog is dismissed, the Activity basically stores the state of the dialog (for performance reasons I would imagine). Calling removeDialog(int) on the dialog forces the activity to unload all references for the dialog and dismisses it from the screen if it's being shown.
did this when my activity lost focus simply add:
public void onStop() {
removeDialog(Id_Dial);
return;
}
My technique is to create an adapter with empty data in onCreateDialog and completely replace the adapter during onPreparDialog.
Example:
#Override
protected Dialog onCreateDialog(int id) {
switch (id) {
case DialogMergeRegion:
title = ...
return new AlertDialog.Builder(BaseDataTabView.this)
.setTitle(title)
.setMultiChoiceItems(new CharSequence[0], null,
new OnMultiChoiceClickListener() {
#Override
public void onClick(DialogInterface dialog, int which, boolean isChecked) {
manageSelectionList(which, isChecked);
}
})
//...
.create();
}
}
#Override
protected void onPrepareDialog(int id, Dialog dialog) {
super.onPrepareDialog(id, dialog);
switch (id) {
case DialogMergeRegion: {
List<String> regionNames = ...// get the data
ListAdapter mergeAdapter = new ArrayAdapter<String>(this, android.R.layout.select_dialog_multichoice, regionNames);
AlertDialog ad = (AlertDialog) dialog;
ad.getListView().setAdapter(mergeAdapter);
break;
}
}
In your onPrepareDialog method, instead of using invalidateViews(), you should try getting the adapter of the ListView and try calling either notifyDataSetChanged() or notifyDataSetInvalidated(). Does that help?
I'm using and ArrayAdapter to populate a ListView. After selecting and item, it displays a confirmation Y/N dialog. If the user's choice is negative, then he should be able to select another item showing the same dialog. And so on.
Here's my code:
lView.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(final AdapterView<?> parent, final View v, final int index, final long id) {
Toast.makeText("Selected file"+ mFiles.get(index).getfileName(),
Toast.LENGTH_SHORT).show();
SelectedFile = mFiles.get(index);
showDialog(DIALOG_CONFIRMIMPORT_ID);
}
});
The weird thing is that while the "Toast" shows the clicked item every time, only the first selected item since the Activity is initiated is being passed to "SelectedFile". No matter how many times you click a diferent item, "SelectedFile" always assumes the same value, the value of the first clicked item, outside of this code.
Heres's my Dialog code:
Protected Dialog onCreateDialog(int id) {
switch(id) {
case DIALOG_CONFIRMIMPORT_ID:
{
AlertDialog.Builder builder = new AlertDialog.Builder(this);
String message = String.format(getString(R.string.importstudentfileconfirm),SelectedFile.getfileName());
builder.setMessage(message)
.setCancelable(false)
.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// Activity.this.finish();
// startActivity(new Intent(Activity.this, LOL.class));
}
})
.setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
SelectedFile = null;
dismissDialog(DIALOG_CONFIRMIMPORT_ID);
mFiles.notifyAll();
}
});
AlertDialog alert = builder.create();
return alert;
}
}
return null;
}
Thank you very much for any help!
I'm guessing this has something to do with the fact that the onCreateDialog method is only called the first time the dialog is created. So the first time you see the dialog it will have the correct filename.
After onCreateDialog is called, onPrepareDialog(...) is called. onPrepareDialog, allows you to change the dialog after it has been created, but before it gets displayed.
Remember that underneath everything, Android isn't creating a new Dialog for you every time you want to show the DIALOG_CONFIRMIMPORT_ID dialog. It is too computationally expensive to instantiate a new dialog every time. Instead, it creates it once, which causes onCreatDialog to be called, followed by the onPrepareDialog. Every other time the dialog is shown, it only calls onPrepareDialog.
Check out the following article on the Android Developer site. It explains things pretty clearly.
http://developer.android.com/guide/topics/ui/dialogs.html#ShowingADialog
So try using onCreateDialog just for initialization of stuff that won't change between showings of the dialog, then use the onPrepareDialog method to dynamically update the contents of the dialog (i.e. getting the new filename)
Cheers!
This is a followup to this post:
findViewById in a subclassed SurfaceView throwing RuntimeException
Based on Romain Guy's feedback (which I'll accept shortly as it is a solution), I'd like to obtain the calling Activity from within the View, so that I can use it to obtain the desired TextView resource.
I don't see any methods in View that return Activity. What is the proper way to do this? Or is there a better alternative for working with TextViews from within another View context.
Basically, I am calling setContentView(R.layout.xxx) in onCreate() (as usual), so I don't really have a way to pass in references to additional TextViews unless I awkwardly retrieve the View after setContentView and then make calls on it.
An Activity is a Context, but there is no guarantee that the Context used by a View is always an Activity. Getting the views from onCreate() to do some setup is perfectly valid and is how Android applications are usually written. You could do something like this for instance:
setContentView(...);
MySurfaceView v = findViewById(R.id.theusrface);
TextView t = findViewById(R.id.thecontent);
v.setContent(v);
The logic should not go in your Views.
If you already know the Activity class your View is in, i.e. MyActivity, you can use the static member MyActivity.this from inside your View and its listeners, as in the following example:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Are you sure you want to exit?")
.setCancelable(false)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
MyActivity.this.finish();
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
AlertDialog alert = builder.create();
which I've found in this Android tutorial:
http://developer.android.com/guide/topics/ui/dialogs.html
It worked wonders for me.
PJ_Finnegan