How to extend AlertDialog.Builder result? - android

I need to show an AlertDialog with a ListView and a context menu for the ListView items. I prefer to use AlertDialog.Builder and call setItems(), so the Builder creates a ListView inside the AlertDialog with stylized layout for me. For the stylizing it uses internal Android resources, so I cannot reimplement it in my code.
The problem is that I cannot catch a context menu item click event because of default AlertDialog.onMenuItemSelected() implementation, which does not forward such events to the parent:
public boolean onMenuItemSelected(int featureId, MenuItem item) {
return false;
}
I cannot extend AlertDialog.Builder class and force it to create an instance of my own AlertDialog with onMenuItemSelected() overridden because I need to override AlertDialog.Builder.create() for that. But it uses a private P variable, which is not accessible from a derived class:
public AlertDialog create() {
final AlertDialog dialog = new AlertDialog(P.mContext, mTheme, false);
P.apply(dialog.mAlert);
dialog.setCancelable(P.mCancelable);
if (P.mCancelable) {
dialog.setCanceledOnTouchOutside(true);
}
dialog.setOnCancelListener(P.mOnCancelListener);
if (P.mOnKeyListener != null) {
dialog.setOnKeyListener(P.mOnKeyListener);
}
return dialog;
}
Is there a way to force AlertDialog.Builder to construct a custom AlertDialog (with onMenuItemSelected method overridden)?

I still found no solution for the question, but I found some problems, which makes the solution useless. For Android 2.1, built-in ListView items (android.R.layout.select_dialog_item) are displayed as black text on dark grey background, ListView items are not separated from the dialog message (setMessage()), etc.
I finally switched back to my own AlertDialog with custom layout for ListView and its items (AlertDialog.Builer not used). Context menu events can be easily catched this way.
Luksprog, thanks a lot for your comments. But the main idea was to use as many stylized layouts, as possible. AFAIK, no standard layouts (android.R.layout.*) offer the buttons you mentioned. Also, an item could be removed occasionally with the button. With a context menu, at least two click required to remove an item.

Related

Android 4.+ NumberPicker - Forcing Number Keyboard Layout

Am posting this in hopes to help someone else; but, if there is an easier way to do the same, I hope someone can share their steps. If I use the method 'setDisplayedValues' to pass an array of values to display in the NumberPicker, the underlying method forces the use of a Text Keyboard Layout, instead of the Number Layout, which isn't what I want.
I found a way to set the InputType for my NumberPicker. This is done in my extended class:
class public class NumberPickerDialogFragment extends DialogFragment:
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// We are getting the parameters passed in to figure out the range of the Number Picker
NumPickerValues = getArguments().getStringArray("NumPickerRange");
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// Get the layout inflater
LayoutInflater inflater = getActivity().getLayoutInflater();
View dlgNumPicker = inflater.inflate(R.layout.dialog_num_picker, null);
NumberPicker np = (NumberPicker) dlgNumPicker.findViewById(R.id.npNumberPicker);
// Always remember that NumberPicker methods need an index position, rather than the value in that array position
np.setMinValue(0);
np.setMaxValue(NumPickerValues.length-1);
np.setDisplayedValues(NumPickerValues);
np.setValue(getArguments().getInt("InitialValue"));
np.setWrapSelectorWheel(false);
np.setOnValueChangedListener(this);
// Since the underlying code for the NumberPicker sets the keyboard layout for text, due to the use of 'setDisplayedValues',
// we need to set it back to a number keyboard layout
((EditText)np.getChildAt(0)).setRawInputType(InputType.TYPE_CLASS_NUMBER);
// Inflate and set the layout for the dialog
// Pass null as the parent view because its going in the dialog layout
return builder.setView(dlgNumPicker)
.setTitle(getArguments().getInt("NumPickerTitle"))
.setPositiveButton(getArguments().getInt("SaveButtonTitle"), new ButtonCLickListener())
.setNegativeButton(R.string.cancel, new ButtonCLickListener())
.create();
}
On the section of code above, the line that sets the InputType is
((EditText)np.getChildAt(0)).setRawInputType(InputType.TYPE_CLASS_NUMBER);
I didn't find anything on the web that does this. It seems like a clean way of doing it; but, am not sure if there is any performance issues by doing it this way. If there is, let us know.

How to attach GestureDetector to a ListPreference?

The challenge of attaching a GestureDetector to a ListPreference is 2-fold:
Getting a handle to a ListPreference that's only defined in a preferences.xml (i.e. not instantiated in Java code).
ListPreference is neither a View nor Activity subclass.
Is it possible at all to attach a GestureDetector to a ListPreference?
If so, how would one go about this? Where would I write the code to instantiate GestureDetector and implement the listener?
Unless I didn't quite catch the question correctly, the answer is probably simpler than you might think. The source code for ListPreferece teaches that it's little more than a wrapper around an AlertDialog that displays its various options in a ListView. Now, AlertDialog actually allows you to get a handle on the ListView it wraps, which is probably all you need.
In one of the comments you indicated that, at this stage, all you're interested in is detecting a long-press on any item in the list. So rather than answering that by attaching a GestureDetector, I'll simply use an OnItemLongClickListener.
public class ListPreferenceActivity extends PreferenceActivity implements OnPreferenceClickListener {
private ListPreference mListPreference;
#Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.list_prefs);
mListPreference = (ListPreference) findPreference("pref_list");
mListPreference.setOnPreferenceClickListener(this);
}
#Override
public boolean onPreferenceClick(Preference preference) {
AlertDialog dialog = (AlertDialog) mListPreference.getDialog();
dialog.getListView().setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override public boolean onItemLongClick(AdapterView<?> parent, View v, int position, long id) {
Toast.makeText(getApplicationContext(), "Long click on index " + position + ": "
+ parent.getItemAtPosition(position).toString(), Toast.LENGTH_SHORT).show();
return false;
}
});
return false;
}
}
The result (which the toast in the long-click displaying):
With a reference to the ListView, you could also attach an OnTouchListener, GestureDetector etc. Up to you to go from here.
As #TronicZomB suggested, this isn't directly possible.
You can work around this by creating your own ListPreference derived class, getting its view in the inherited onBindDialogView().
Remember however that the latter is tricky because onBindDialogView() is only called if onCreateDialogView() doesn't return null, and this can happen only if you create your own custom view for YourListPreference.
The recommended way to do this is to build a custom Preference.
Once you have done that, you have a reference to YourListPreference's view, which is mandatory for attaching GestureDetector because one of the steps requires setOnTouchListener() on the view.
I have set a GestrueDetector to a ScrollView using setOnTouchListener previously and searched for a similar method for ListPreference, however since the ListPreference does not contain such a method, I do not believe this will be possible.

How to display a (modal) dialog at the very start of the app?

At the start of my Android app the user is required to choose from a list of alternatives. Here is why.
Let's assume I have a long list of items, and each item belongs to exactly one category. Each user is only interested in one specific category. Thus, when the app is started and the SharedPreferences don't contain any information about the selected category, a modal dialog should be displayed - here the user has to choose his or her category of interest. After having selected a category, only the items of that category are displayed.
So far, I tried to implement this behavior in the Activity's onCreate() method, which doesn't work obviously. The dialog is not shown or at least not long enough so that I could see it.
To be honest, I didn't expect the code to work by calling it from onCreate(). However, I was unable to find a suitable event handler in the Activity from where I could trigger the dialog.
Where should this dialog be triggered from in order to ensure the selection of a category (before any other data is loaded)?
Thanks in advance.
Here's the code:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
setContentView(R.layout.activity_item_list);
...
ensureCategorySelected();
}
where the relevant method is
private void ensureCategorySelected() {
String chosenCategory = getCategoryFromSharedPreferences();
if (chosenCategory != null) {
final CharSequence[] items = getCategories();
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Choose category");
builder.setItems(items, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
// handle the selection of the category
}
});
AlertDialog alert = builder.show();
}
}
You have a logic problem there. You want to show the dialog when there are still no preferences saved, and you are showing it when there are preferences saved. Change it to chosenCategory == null and it should work.
And why didn't you expect the code to work in onCreate()? I don't see a problem opening a dialog there.
Edit: I'm not quite sure if onCreate() is the correct place to show the dialog. Try putting ensureCategorySelected() in onStart() instead of onCreate().
You could also consider implementing an activity for this, which you could start with startActivityForResult().

Android: How to set the selection in a single choice AlertDialog?

I created a single choice AlertDialog with "Apply" and "Cancel" buttons. When the user presses "Cancel", I would like to set the selected item back to what it was when the dialog was first shown (I have the value stored already).
I know how to set the selected item when the dialog is first created in setSingleChoiceItems() but is there a way to set it again later?
I would like to be compatible with API level 7, so I'd rather not use onPrepareDialog().
Well, nobody could find a solution to my problem, so I settled for a dialog which doesn't use buttons. When the user presses an item in the list, that selection is applied and the dialog is dismissed. No need to remember previous choices or support cancelling.
You can create your dialog on the spot rather than going through showDialog and onCreateDialog. This way its always using the current selection we give to setSingleChoiceItems.
//where we display the dialog
showDialog(MYDIALOG);
AlertDialog.Builder builder = new Builder(this);
String[] choices = {"A","B","C"};
builder.setSingleChoiceItems(choices,current_choice,null);
builder.setPositiveButton("Select",null);
builder.setNegativeButton("Cancel",null);
builder.show();
...
protected Dialog onCreatDialog(int id) {
if (id==MYDIALOG) {
AlertDialog.Builder builder = new Builder(this);
String[] choices = {"A","B","C"};
builder.setSingleChoiceItems(choices,current_choice,null);
builder.setPositiveButton("Select",null);
builder.setNegativeButton("Cancel",null);
return builder.show();
}
return null;
}
In Altert Dialog For creating single choice have you used single choice list view or radio group?
If You have used Single Choice Listviwe then no need to worry.
IF you have used Radio Group then you have to keep track of selected Radio Button Using Global Varialbe in your activity.
What you want to do when user click on cancel.
when user click on cancel than do you want to remove selected item from list if yes then you have to do the following.
In Your listitemseleted listener
alb.setSingleChoiceItems(items, 0, new OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
/* which argument is the position of the item in
array items you have to remove this item from items array
Make your items array global variable.since in java array are
immutable you have to use arraylist.Arraylist can be converted
to array.*/
}
});
hope this will help if any question feel free to ask.

Android opening context menu after button click

I want to open context menu when I click a button, but also I have to know which list item is focused when I click the button. Do you know how to do that? What code should be in onclick method?
I was looking for the same, and found that instead of context menu, you should use Dialogs
final CharSequence[] items = {"Red", "Green", "Blue"};
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Pick a color");
builder.setItems(items, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
Toast.makeText(getApplicationContext(), items[item], Toast.LENGTH_SHORT).show();
}
});
AlertDialog alert = builder.create();
alert.show();
http://developer.android.com/guide/topics/ui/dialogs.html#AlertDialog
If you really want to do it for whatever reason... (in my case, out of laziness)
During onCreate of your activity or somewhere before your user can touch the button, do registerForContextMenuon that button. Then in the actual button onClick handler, call openContextMenu(View).
For example, I have a button declared in xml like
<Button
android:id="#+id/btn_help"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onHelp"
android:text="#string/help_btn_text" />
in my onCreate
registerForContextMenu(findViewById(R.id.btn_help));
and in onHelp function
public void onHelp(View v) {
openContextMenu(v);
}
this works because the View v is the same as the view registered for context menu.
First thing, you should register the view by calling registerForContextMenu(View view). Second, override the onCreateContextMenu() to add the menus and lastly, override the onContextItemSelected() to put logic on each menu.
First of all, you should know why you should use ContextMenu. The functionality of ContextMenu of a View is similar to the right-click menu on a PC, which means the "available operations" on some item.
According to your description, I think what you actually need is a customized Dialog with a list, which is displayed when clicking the Button and is also able to get the focused item of your ListView. Then you can save the registration of ContextMenu for some View that really needs the menu:)

Categories

Resources