I repair big android app and I have many custom dialogs which inherit from various types of standard android dialogs (AlertDialog, ProgressDialog, ...).
I have to add option "setCanceledOnTouchOutside(false)" for all dialogs in app, because in ICS we have this option set on true by default android 4.0 Dialog gets canceled when touched outside of dialog window
I can add line "*dialog.setCanceledOnTouchOutside(false)" for every dialog in my project, but this is hard to maintanence solution.
I can't inherit from MyDialog which inherit from Dialog, because I inherit from AlertDialog, ProgressDialog,... too.
Probably the best solution would be set all dialogs option for whole project in one place or make any hack that give us by default behavior from older android version than ICS, but I don't know if it is possible and how to do this?
Can You advise me?
have all the dialogs implement a common interface, like this,
interface DialogSettings {
void setCancelOnTouchOutside(boolean cancel);
}
now implement a stand-alone version of this,
class VersionAwareDialogSettings implements DialogSettings {
private final Dialog d;
DialogSettingsImpl(Dialog d) {
this.d = d;
}
#Override
void setCancelOnTouchOutside(boolean cancel) {
if (Build.Version.SDK_INT ...) {
d.setCancelOnTouchOutside(cancel);
}
}
}
now, in all your dialog classes, implement this interface, like this,
class MyDialog extends AlertDialog implement DialogSettings {
...
#Override
public void setCancelOnTouchOutside(boolean cancel) {
new VersionAwareDialogSettings(this).setCancelOnTouchOutside(cancel);
}
}
this can seem like a lof of cruft, but it's a nice separation of concerns. if you want to add a version-aware dialog setting, change the interface, and all parts of your code that you need to modify are flagged. if you need to change the impl of a verison-aware dialog setting, just change it in one place: VersionAwareDialogSettings.
you should be more concerned with writing correct code than trying to cut down on the number of lines you write. i don't know about you, but i can type much faster than i think. my brain is the bottleneck.
Related
Google decided to make a single-threaded user interface that doesn't have modal dialogs. I'm sure most of you have found that nothing updates until your function returns because everything is event driven on a single thread (by "law").
If I have a simple alert-box, such as "Are You Sure?" (example only), with a Yes and No button, then I have to assign callbacks to the buttons rather than having a simple return value (no modal dialogs). That's fine, even though a return value would vastly simplify my problem (arguments stay local to the caller), although this would stop the calling activity from responding (modal).
Imagine now if I have a list of items and the user attempts to perform some operation. The dialog must now have some way to pass WHICH item I want to perform the operation on to the button's callback, but I can't seem to find any mechanism in the API for passing this along to the onclick handler. Using non-local variables is a work-around, but messy.
How can I pass this information along cleanly? Does anyone have some sort of hack that would somehow "fake" a modal dialog that can return a value (I'm not seeing how).
Create a custom dialog that extends the default android Dialog and add the information you need and pass on the constructor.
See more here: How can I pass values between a Dialog and an Activity?
I am not sure what exactly what do you want to achieve. Not sure if your problems is in the communication between the activity to the dialog or dialog to the activity or both.
Anyway, I have some experience on Android and I really recommend you to achieve the communication between activities, fragments, even dialog (DialogFragments) to use one of these libraries. At the beggining could be a little bit hard to understand how work, but the result is faster and cleaner code, of course offers you more flexibility.
Take a look to:
https://github.com/beworker/tinybus --> less used but it is awesome
https://github.com/greenrobot/EventBus --> more extended and used for the community
Hope to help you!
In a situation like this, I Created a new string array entry in the strings.xml in values folder like this:
<string-array name="array">
<item>1</item>
<item>2</item>
</string-array>
And then create a dialog using Dialog builder like this:
AlertDialog.Builder dialog=new AlertDialog.Builder(this);
LayoutInflater infl=this.getLayoutInflater();
Resources res=getResources();
dialog.setSingleChoiceItems(R.array.alphabets, 0,new OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
mReturnVariable=which;
}
});
dialog.create().show();
So the mReturnVariable contains the user selected item index .Hope that solves the problem
I passed the required arguments to the Alert Dialog using View Binding in Android Latest version.
private ConnectDialogBinding connectDialogBinding;
private String chargerID;
private void connectDialog() {
// Create the object of
// AlertDialog Builder class
AlertDialog.Builder builder = new AlertDialog.Builder(ConnectActivity.this);
connectDialogBinding = ConnectDialogBinding.inflate(getLayoutInflater());
builder.setView(connectDialogBinding.getRoot());
connectDialogBinding.txtID.setText(chargerID);
builder.setCancelable(false);
// Create the Alert dialog
AlertDialog alertDialog = builder.create();
// Show the Alert Dialog box
alertDialog.show();
connectDialogBinding.cancelBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
alertDialog.cancel();
}
});
}
enter image description here
I am performing a click on the "Set"-button in a DatePickerDialog with Robotium via
solo.clickOnButton("Set");
If I now change the language of the testing device to a different language, Robotium is not able to find the button, as the text is not "Set" anymore but the translated word.
Is there any possibility to access the button in the Picker in a different way?
As in Jelly Bean the DatePicker lost the "Cancel" button, I cannot use the clickOnButton(int index) method.
The only idea I have would be to use setButton on the DatePickerDialog to have access to the localized string resource of the button text or keep a reference to the button.
But maybe someone knows of a better way to gain access without the need of custom button text.
Regards
Kim
If you have access to the source code, you can use both getString() and getView():
Button button = (Button) solo.getView(R.id.x);
solo.clickOnView(button);
There is also solo.getString(R.string.x) that is good to use for localized builds.
I know that it's not the best solution but it works for me:
solo.clickOnButton(0);
Here's my suggestion (assuming you are showing the dialog via a DialogFragment): I have a SelectDateDialogFragment with a unique TAG and an onCreateDialog() method which creates a DatePickerDialog. I then show the dialog via selectDateDialogfragment.show(getFragmentManager(), SelectDateDialogFragment.TAG). In the Robotium tests, I use code like the following to click the dialog's buttons:
solo.clickOnView(editDateButton);
solo.waitForFragmentByTag(SelectDateDialogFragment.TAG);
solo.setDatePicker(0, 2000, 1, 1);
SelectDateDialogFragment dialogFragment = (SelectDateDialogFragment) activity.getFragmentManager()
.findFragmentByTag(SelectDateDialogFragment.TAG);
DatePickerDialog dialog = (DatePickerDialog) dialogFragment.getDialog();
Button okButton = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
solo.clickOnView(okButton);
solo.waitForDialogToClose();
I would like to share some details with you.
First:
solo.clickOnButton(0);
worked well for me some time. But as the new Dialogs don't have the "Set" and "Cancel" buttons, but instead "Cancel" and "OK", this solution would now select the cancel button on newer devices while just switching to
solo.clickOnButton(1);
would break the test for older devices.
So I migrated to csoltenborn's solution with two modifications:
as I want to stay compatible with older devices I use the SupportFragmentManager
as my fragment is nested in another fragment depending on the device and it's orientation, I sometimes have to access a certain fragments ChildFragmentManager.
This is my solution, maybe it can add to csoltenborn's good answer:
DialogFragment dialogFrag;
Fragment outerFragment = getActivity().getSupportFragmentManager().findFragmentByTag("outerFragmentTAG");
if (outerFragment == null) {
dialogFrag = (DialogFragment)getActivity().getSupportFragmentManager().findFragmentByTag("datePicker");
} else {
dialogFrag = (DialogFragment)outerFragment.getChildFragmentManager().findFragmentByTag("datePicker");
}
Button okButton = ((DatePickerDialog)dialogFrag.getDialog()).getButton(DialogInterface.BUTTON_POSITIVE);
solo.clickOnView(okButton);
I want to show a dialog when the user clicks on an option menu inside an Activity. I first wanted to do this using the Dialog class. The code is something similar to the one below.
final Dialog d = new Dialog(this);
d.setContentView(R.layout.customDialog);
d.setTitle("Sample title");
data = (EditText) d.findViewById(R.id.data);
button = (Button) d.findViewById(R.id.aButton);
d.show();
button.setOnClickListner(new View.OnClickListner() {
// grab data from edittext and save it to some var
d.dismiss();
});
Something like that. The dev guide suggests I not instantiate directly a Dialog class. Is there something particularly bad about this approach ?
The android dev guide adds a lot of extra info to help developers avoid tasks which take up a lot of processing time. Instantiating a Dialog class directly probably takes up a lot more processing time.
The system keeps a cache of dialogs, so you don't have to manage it yourself. Each dialog is created only once and stored somewhere so it can be reused later. That's because creating a dialog is computationally expensive, I guess. The system gives you the hooks to create the dialog the first time it's needed and to prepare it just before showing
i am using following code to show date picker in android
DatePickerDialog dial= new DatePickerDialog(this.getContext(),0,mDateSetListener,thisYear,thisMonth,thisDay);
dial.setOnDismissListener(new OnDismissListener() {
#Override
public void onDismiss(DialogInterface arg0) {
// dismiss it.
}
});
dial.show();
now i want to pick time too along with date any one guide me how to achieve this?
Step #1: Create a dialog (e.g., use AlertDialog.Builder).
Step #2: Put a DatePicker and a TimePicker in the dialog (e.g., setView() on AlertDialog.Builder).
Note that this may not work well on small screens, since DatePicker and TimePicker are each large -- there may not be enough room for both and the dialog buttons and such.
As said you can create a dialog with both in however on most screens it will look poor due to the size of them.
You could recreate your own making it smaller (it's not that hard) or reflow your app and have them on separate pop-ups
I'm trying to port one of my iPhone apps over to the Android. It was all going along swimmingly until I came to AlertDialogs. In the iPhone app, sometimes there will be more than one alert to pass to the user. When this happens, the first alert dialog will come up, and when they click it away the next one will come up.
I can't seem to get more than one dialog box to come up like that in Android. Is it possible to display back to back AlertDialogs where a second one pops up as soon as the first is finished?
You execute 2 consecutive call to 'showDialog()' after eachother and the second will show after the 1st was dismissed:
showDialog(FIRST_DIALOG_ID);
showDialog(SECOND_DIALOG_ID);
Ofcourse you also have to implement onCreateDialog().
If you feel that you will be having multiple dialogs, one after another, you could create a custom class that holds all of the information for the alert, such as the title, text, icon, etc. From there, create an arraylist to store the custom class objects. When you are done with your first dialog, remove it from the arraylist, then check to see if there are any remaining dialogs that need to be presented.
The only issue you'll run into is that it will be much more difficult if you want to have different conditions in your Confirm and Cancel options.
public class DialogObject(){
String title;
String body;
String iconName; // or just an Image asset
}
ArrayList<DialogObject> dialogList = new ArrayList<>();
When a dialog is required, add it to the list if there is a dialog already on screen
dialogList.add(new DialogObject(param1, param2, param3));
This may not be the best way, but it is an option. The ArrayList will need to be in a separate class itself so you don't lose the data when moving from screen to screen.
For example - Note the "static" keyword.
public class DialogHolder(){
public static ArrayList<DialogObject> = new ArrayList<>();
}