How do I create an Android Spinner as a popup? - android

I want to bring up a spinner dialog when the user taps a menu item to allow the user to select an item.
Do I need a separate dialog for this or can I use Spinner directly? I see this link, mentions a MODE_DIALOG option but it doesn't seem to be defined anymore. AlertDialog may be OK but all the options say "clicking on an item in the list will not dismiss the dialog" which is what I want. Any suggestion?
Ideally, the code would be similar to the case where the spinner is shown on the screen:
ArrayAdapter<String> adapter = new ArrayAdapter<String>(activity,
android.R.layout.simple_spinner_item, items);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
myspinner.setAdapter(adapter);
// myspinner.showAsDialog() <-- what i want

You can use an alert dialog
AlertDialog.Builder b = new Builder(this);
b.setTitle("Example");
String[] types = {"By Zip", "By Category"};
b.setItems(types, new OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
switch(which){
case 0:
onZipRequested();
break;
case 1:
onCategoryRequested();
break;
}
}
});
b.show();
This will close the dialog when one of them is pressed like you are wanting.

In xml there is option
android:spinnerMode="dialog"
use this for Dialog mode

Try this:
Spinner popupSpinner = new Spinner(context, Spinner.MODE_DIALOG);
See this link for more details.

MODE_DIALOG and MODE_DROPDOWN are defined in API 11 (Honeycomb). MODE_DIALOG describes the usual behaviour in previous platform versions.

Adding a small attribute as android:spinnerMode="dialog" would show the spinner contents in a pop-up.

You can create your own custom Dialog. It's fairly easy. If you want to dismiss it with a selection in the spinner, then add an OnItemClickListener and add
int n = mSpinner.getSelectedItemPosition();
mReadyListener.ready(n);
SpinnerDialog.this.dismiss();
as in the OnClickListener for the OK button. There's one caveat, though, and it's that the onclick listener does not fire if you reselect the default option. You need the OK button also.
Start with the layout:
res/layout/spinner_dialog.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:id="#+id/dialog_label"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:hint="Please select an option"
/>
<Spinner
android:id="#+id/dialog_spinner"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
/>
<Button
android:id="#+id/dialogOK"
android:layout_width="120dp"
android:layout_height="wrap_content"
android:text="OK"
android:layout_below="#id/dialog_spinner"
/>
<Button
android:id="#+id/dialogCancel"
android:layout_width="120dp"
android:layout_height="wrap_content"
android:text="Cancel"
android:layout_below="#id/dialog_spinner"
android:layout_toRightOf="#id/dialogOK"
/>
</RelativeLayout>
Then, create the class:
src/your/package/SpinnerDialog.java:
public class SpinnerDialog extends Dialog {
private ArrayList<String> mList;
private Context mContext;
private Spinner mSpinner;
public interface DialogListener {
public void ready(int n);
public void cancelled();
}
private DialogListener mReadyListener;
public SpinnerDialog(Context context, ArrayList<String> list, DialogListener readyListener) {
super(context);
mReadyListener = readyListener;
mContext = context;
mList = new ArrayList<String>();
mList = list;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.spinner_dialog);
mSpinner = (Spinner) findViewById (R.id.dialog_spinner);
ArrayAdapter<String> adapter = new ArrayAdapter<String> (mContext, android.R.layout.simple_spinner_dropdown_item, mList);
mSpinner.setAdapter(adapter);
Button buttonOK = (Button) findViewById(R.id.dialogOK);
Button buttonCancel = (Button) findViewById(R.id.dialogCancel);
buttonOK.setOnClickListener(new android.view.View.OnClickListener(){
public void onClick(View v) {
int n = mSpinner.getSelectedItemPosition();
mReadyListener.ready(n);
SpinnerDialog.this.dismiss();
}
});
buttonCancel.setOnClickListener(new android.view.View.OnClickListener(){
public void onClick(View v) {
mReadyListener.cancelled();
SpinnerDialog.this.dismiss();
}
});
}
}
Finally, use it as:
mSpinnerDialog = new SpinnerDialog(this, mTimers, new SpinnerDialog.DialogListener() {
public void cancelled() {
// do your code here
}
public void ready(int n) {
// do your code here
}
});

You can use a spinner and set the spinnerMode to dialog, and set the layout_width and layout_height to 0, so that the main view does not show, only the dialog (dropdown view). Call performClick in the button click listener.
mButtonAdd.setOnClickListener(view -> {
spinnerAddToList.performClick();
});
Layout:
<Spinner
android:id="#+id/spinnerAddToList"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="10dp"
android:prompt="#string/select_from_list"
android:theme="#style/ThemeOverlay.AppCompat.Light"
android:spinnerMode="dialog"/>
The advantage of this is you can customize your spinner any way you want.
See my answer here to customize spinner:
Overriding dropdown list style for Spinner in Dialog mode

Here is an Spinner subclass which overrides performClick() to show a dialog instead of a dropdown. No XML required. Give it a try, let me know if it works for you.
public class DialogSpinner extends Spinner {
public DialogSpinner(Context context) {
super(context);
}
#Override
public boolean performClick() {
new AlertDialog.Builder(getContext()).setAdapter((ListAdapter) getAdapter(),
new DialogInterface.OnClickListener() {
#Override public void onClick(DialogInterface dialog, int which) {
setSelection(which);
dialog.dismiss();
}
}).create().show();
return true;
}
}
For more information read this article: How To Make Android Spinner Options Popup In A Dialog

This is from the Android SDK source code.
As you can see you have a special constructor to create a Spinner with the specified mode you wanna use.
Hope it will help you :)
/**
* Construct a new spinner with the given context's theme, the supplied attribute set,
* and default style. <code>mode</code> may be one of {#link #MODE_DIALOG} or
* {#link #MODE_DROPDOWN} and determines how the user will select choices from the spinner.
*
* #param context The Context the view is running in, through which it can
* access the current theme, resources, etc.
* #param attrs The attributes of the XML tag that is inflating the view.
* #param defStyle The default style to apply to this view. If 0, no style
* will be applied (beyond what is included in the theme). This may
* either be an attribute resource, whose value will be retrieved
* from the current theme, or an explicit style resource.
* #param mode Constant describing how the user will select choices from the spinner.
*
* #see #MODE_DIALOG
* #see #MODE_DROPDOWN
*/
public Spinner(Context context, AttributeSet attrs, int defStyle, int mode) {
super(context, attrs, defStyle);

If you want to show it as a full screen popup, then you don't even need an xml layout. Here's how do do it in Kotlin.
val inputArray: Array<String> = arrayOf("Item 1","Item 2")
val alt_bld = AlertDialog.Builder(context);
alt_bld.setTitle("Items:")
alt_bld.setSingleChoiceItems(inputArray, -1) { dialog, which ->
if(which == 0){
//Item 1 Selected
}
else if(which == 1){
//Item 2 Selected
}
dialog.dismiss();
}
val alert11 = alt_bld.create()
alert11.show()

Here is a Kotlin version based on the accepted answer.
I'm using this dialog from an adapter, every time a button is clicked.
yourButton.setOnClickListener {
showDialog(it /*here I pass additional arguments*/)
}
In order to prevent double clicks I immediately disable the button, and re-enable after the action is executed / cancelled.
private fun showDialog(view: View /*additional parameters*/) {
view.isEnabled = false
val builder = AlertDialog.Builder(context)
builder.setTitle(R.string.your_dialog_title)
val options = arrayOf("Option A", "Option B")
builder.setItems(options) { dialog, which ->
dialog.dismiss()
when (which) {
/* execute here your actions */
0 -> context.toast("Selected option A")
1 -> context.toast("Selected option B")
}
view.isEnabled = true
}
builder.setOnCancelListener {
view.isEnabled = true
}
builder.show()
}
You can use this instead of a context variable if you are using it from an Activity.

Related

Programatically created edit text is also getting focus while tapping another edit text in android

I have created multiple edit texts programmatically using existing edit text available in XML file but when the main edit text gets the focus then the edit texts created dynamically also getting focus. My code is as below :
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_worker_reg);
existingContact = (EditText)findViewById(R.id.workerPhone);
drawable = existingContact.getBackground();
}
public void addAnotherContactNumber(View view) {
final CharSequence[] options = { "Work", "Home","Cancel" };
AlertDialog.Builder builder = new AlertDialog.Builder(WorkerRegActivity.this);
builder.setTitle("Add Contact Number!");
builder.setItems(options, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int item) {
if (options[item].equals("Work"))
{
linearLayout = (LinearLayout)findViewById(R.id.containerLayout);
EditText newContact = new EditText(WorkerRegActivity.this);
newContact.setHint("Phone NO." + (newContactIndex - 1));
newContact.setHintTextColor(existingContact.getHintTextColors());
newContact.setInputType(existingContact.getInputType());
newContact.setLayoutParams(existingContact.getLayoutParams());
int sdk = android.os.Build.VERSION.SDK_INT;
if(sdk < android.os.Build.VERSION_CODES.JELLY_BEAN) {
newContact.setBackgroundDrawable(drawable);
} else {
newContact.setBackground(drawable);
}
linearLayout.addView(newContact, newContactIndex);
newContactIndex += 1;
contactList.add(newContact);
}
else if (options[item].equals("Home"))
{
}
else if (options[item].equals("Cancel")) {
dialog.dismiss();
}
}
});
builder.show();
}
Actually I want to create multiple edit texts using an existing edit text as defined in XML file with same background but when one edit text gains focus another one also gains the focus automatically. Please help.....
When you add new editTexts, just add a property line switching off the focus :
edittext.clearFocus();
where edittext is the id of your edittext.
If this doesn'twork, you can use this :
<!-- Dummy item to prevent AutoCompleteTextView from receiving focus -->
<LinearLayout
android:focusable="true" android:focusableInTouchMode="true"
android:layout_width="0px" android:layout_height="0px"/>
<!-- :nextFocusUp and :nextFocusLeft have been set to the id of this component
to prevent the dummy from receiving focus again -->
<AutoCompleteTextView android:id="#+id/autotext"
android:layout_width="fill_parent" android:layout_height="wrap_content"
android:nextFocusUp="#id/autotext" android:nextFocusLeft="#id/autotext"/>
This is just aworkaround to trick android to give focus to something else than the edit text. Remember, however, that you have to put the dummy element just before the editText you wish to revoke focus from.
While doing such thing we should use different object of drawable rather than same instance.
Drawable clone = drawable.getConstantState().newDrawable();

How to add default text in spinner?

I am new to android,I know access of spinner but I want to add default text in spinner and want set lay out like below image,can any one help me with this,
final String[] items = new String[] {"One", "Two", "Three"};
final ArrayAdapter<String> adapter123 = new ArrayAdapter<String>(this,
android.R.layout.simple_spinner_dropdown_item, items);
sp3.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View w) {
new AlertDialog.Builder(RegistrationForm.this)
.setTitle("the prompt")
.setAdapter(adapter123, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
}).create().show();
}
});
My suggestion for your case is use Button initially set text and set gravity (not layout_gravity) to left|center_vertical instead of opening an AlertDialog open a PopupWindow set that Button as anchor of that PopUpWindow. In that PopUpWindow place a ListView and in OnItemClick change text with selected value in that Button using setText(java.lang.CharSequence)
code snippet
XML for that Button
<Button
android:id="#+id/propertyBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="#dimen/dp_4"
android:background="#drawable/property_btn_large"
android:ellipsize="marquee"
android:gravity="left|center_vertical"
android:marqueeRepeatLimit="marquee_forever"
android:minHeight="0dp"
android:minWidth="0dp"
android:onClick="showPropertyPopUp"
android:paddingLeft="42dp"
android:paddingRight="22dp"
android:shadowColor="#android:color/white"
android:shadowDx="1"
android:shadowDy="1"
android:shadowRadius="1"
android:text="#string/select_property" />
Java code for opening PopUpWindow in that Button click
//don't forget to initialize that button in onCreate(...)
public void showPropertyPopUp(View v) {
propertyList = dbHelper.getAllProperties();
dbHelper.closeDB();
if(propertyList != null && propertyList.size() > 0) {
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View popUpView = inflater.inflate(R.layout.pop_up, null, false);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.select_dropdown);
popupWindowProperty = new PopupWindow(popUpView, propertyBtn.getWidth(),
300, true);
popupWindowProperty.setContentView(popUpView);
popupWindowProperty.setBackgroundDrawable(new BitmapDrawable(getResources(),
bitmap));
popupWindowProperty.setOutsideTouchable(true);
popupWindowProperty.setFocusable(true);
popupWindowProperty.showAsDropDown(propertyBtn, 0, 0);
ListView dropdownListView = (ListView) popUpView.
findViewById(R.id.dropdownListView);
PropertyDropdownAdapter adapter = new PropertyDropdownAdapter(
AddIncomeActivity.this,
R.layout.row_pop_up_list, propertyList);
dropdownListView.setAdapter(adapter);
dropdownListView.setOnItemClickListener(this);
}
}
code for setting text on that Button in OnItemClick
PropertyInfo addPropertyInfo = propertyList.get(position);
String propertyName = addPropertyInfo.getPropertyName();
propertyBtn.setText(propertyName);
popupWindowProperty.dismiss();
pop_up layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ListView
android:id="#+id/dropdownListView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:cacheColorHint="#null"
android:fadeScrollbars="false" >
</ListView>
</LinearLayout>
Screenshot on clicking on that Button
Screenshot after item click of ListView
Add one more element in array which you are passing in spinner and if you want to add validation you can check it by runtime using -
if (spnType.getSelectedItemPosition() == 0) {
View view = spnType.getSelectedView();
SpinnerView adapter = (SpinnerView) spnType.getAdapter();
adapter.setError(view, getString(R.string.err_leadtype));
return false;
} else {
strType = arllistType.get(spnType.getSelectedItemPosition()).get(
WebServiceResponseParameter.LIST_VALUE);
}
As Nitish explained, You need to add default value on top of your array R.array.day_birthdate. Suppose you your array is day_birthdate then add day in top where you define
<string-array name="day_birthdate">
<item name="0">day</item>
<item name="1">1</item>
...
</string-array>
Add validaton on Spinner, if option first is selected then,
if (mSpinnerBirthDate.getSelectedItemPosition() == 0) { //where mSpinnerBirthDate is Spinner for Birthdate
//show invalid selection message
}else{
//get selected value from spinner
}
Add one more element in array which you are passing in spinner and then write this code in java file.
String array[]=getResources().getStringArray(R.array.name_Of_array);
ArrayAdapter<String> ad=new ArrayAdapter<String>(this,layoutid, array);
spinner.setAdapter(ad);
You can not do that, for that you have to create custom spinner or you have to show alertdialog as a action when text view is clicked.
Edited :
Create a array
String a [] = new String [4] ;
a[0] = "ram";
a[1] = "shyam";
a[2] = "mohan";
a[3] = "krishna";
use this array as a source of listview data, now as a action listview will be displayed and set a listener for listview which will provide you a position of clicked item in the listview,
use that position for array[position], lets position = 2, then clicked item text will be mohan set this text as a item of textview .
Edited 2:
Create custom Dialog with listview inside it.
set onItemClickListener in listview.
onCreate
{
dayTextView.setText("day");
}
onItemClickListener ()
{
dayTextView.setText("Sunday");
}
Edited 3 :
Follow this tutorial for custom dilaog : http://rajeshvijayakumar.blogspot.in/2013/04/alert-dialog-dialog-with-item-list.html

Retrieving Value from EditText in DialogFragment

I'm going through Google's Android Developer page on Dialogs, specifically this section. However, instead of creating the DialogFragment's message programmatically, I made a pre-set layout named layout_newpayperiod.xml with the following elements:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<Spinner
android:id="#+id/spinner_payperiod"
android:layout_width="fill_parent"
android:layout_height="48dp"
android:padding="8dp"
android:entries="#array/pay_periods"
/>
<EditText
android:id="#+id/edittext_savepercent"
android:layout_width="fill_parent"
android:layout_height="48dp"
android:padding="8dp"
android:inputType="number"
android:hint="Percent to Save"
/>
<EditText
android:id="#+id/edittext_payment"
android:layout_width="fill_parent"
android:layout_height="48dp"
android:padding="8dp"
android:inputType="numberDecimal"
android:hint="Total Payment"
/>
</LinearLayout>
When I call the DialogFragment it shows up as normal, with the Spinner having the proper values. I filled in the entries and hit "OK", but when I try to retrieve the values from the Spinner and two EditText fields, the app forces close with a NumberFormatException: Invalid double "". I get the feeling I'm not retrieving the Views properly. Can anyone help me figure this out please? Thanks!
public class StartPayperiodDialogFragment extends DialogFragment {
/* The activity that creates an instance of this dialog fragment must
* implement this interface in order to receive event callbacks.
* Each method passees the DialogFragment in case the host needs to query it.
*/
public interface StartPayperiodDialogListener{
public void onDialogPositiveClick(DialogFragment dialog);
public void onDialogNegativeClick(DialogFragment dialog);
}
// Use this instance of the interface to deliver action events
StartPayperiodDialogListener listener;
// Override the Fragment.onAttach() method to instantiate the StartPayperiodDialogListener
#Override
public void onAttach(Activity activity){
super.onAttach(activity);
// Verify that the host activity implements the callback interface
try{
// Instantiate the NoticeDialogListener so we can send events to the host
listener = (StartPayperiodDialogListener) activity;
}catch(ClassCastException e){
// The activity doesn't implement the interface, throw exception
throw new ClassCastException(activity.toString() + " must implement StartPayperiodDialogListener");
}
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState){
// Use the Builder class for convenient dialog construction
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
View transactionLayout = View.inflate(getActivity(), R.layout.layout_newpayperiod, null);
builder.setView(transactionLayout)
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// Send the positive button event back to the calling activity
listener.onDialogPositiveClick(StartPayperiodDialogFragment.this);
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// Send the negative button event back to the calling activity
listener.onDialogNegativeClick(StartPayperiodDialogFragment.this);
}
});
return builder.create();
}
}
In MainActivity.class, the callback method:
#Override
public void onDialogPositiveClick(DialogFragment dialog) {
// User pressed OK, so we need to grab the values from the
// dialog's fields and apply them to the Views in the Main
// Activity
View transactionLayout = View.inflate(this, R.layout.layout_newpayperiod, null);
// Start with the payment amount
EditText paymentEt = (EditText) transactionLayout.findViewById(R.id.edittext_payment);
TextView paymentTv = (TextView) findViewById(R.id.text_paycheck);
paymentTv.setText(moneyFormat.format(Double.parseDouble(paymentEt.getText().toString())));
// Next, the percent to save
EditText savingsEt = (EditText) transactionLayout.findViewById(R.id.edittext_savepercent);
TextView savingsTv = (TextView) findViewById(R.id.text_savings);
savingsTv.setText(savingsEt.getText().toString() + "%");
// Then, the pay period
Spinner periodSp = (Spinner) transactionLayout.findViewById(R.id.spinner_payperiod);
TextView periodTv = (TextView) findViewById(R.id.text_payperiod);
periodTv.setText(periodSp.getSelectedItem().toString());
// Finally, let's update the daily allowance amount and clear
// the adapter
adapter.clear();
adapter.notifyDataSetChanged();
TextView allowanceTv = (TextView) findViewById(R.id.text_allowance);
Double allowanceValue;
switch(periodSp.getSelectedItemPosition()){
case(0): // Daily
allowanceValue = Double.parseDouble(paymentTv.getText().toString());
break;
case(1): // Weekly
allowanceValue = Double.parseDouble(paymentTv.getText().toString()) / 7;
break;
case(2): // 2 Weeks
allowanceValue = Double.parseDouble(paymentTv.getText().toString()) / 14;
break;
case(3): // 30 Days
allowanceValue = Double.parseDouble(paymentTv.getText().toString()) / 30;
break;
default: // Debugging purposes only
allowanceValue = 42.0;
break;
}
allowanceTv.setText(Double.toString(allowanceValue));
}
Try this:
#Override
public void onDialogPositiveClick(DialogFragment dialog) {
// User pressed OK, so we need to grab the values from the
// dialog's fields and apply them to the Views in the Main
// Activity
// Start with the payment amount
Dialog dialogView = dialog.getDialog();
EditText paymentEt = (EditText) dialogView.findViewById(R.id.edittext_payment);
... etc. (Retrieve any other views from the dialog by querying the dialogView in the same way.)
Your inflate code "inflates" a brand new version of that view. You want to access the one that was created in the dialog.
I think that this line View transactionLayout = View.inflate(this, R.layout.layout_newpayperiod, null); messes everything. Maybe it's not messing, but you're getting address of freshly created layout and assign it to transactionLayout reference. Then you're getting Views from that layout EditText paymentEt = (EditText) transactionLayout.findViewById(R.id.edittext_payment); which are certainly uninitialisted. It has value empty string value -> "";
I think you should use findViewById to get reference to your EditText's as you do with your TextView's. But as you are in your MainActivity which layout is probably not a parent view to your R.layout.layout_newpayperiod, you must find a way to do that properly.
You've got your DialogFragment as parameter in this onDialogPositiveClickcallback method. So you can obtain it's View and the layout you're looking for - that contains your EditText's
Sorry for editing this post so many times.

how can I make such dialog in android?

I would like to implement dialog such this one
User hits the button "Icon", this dialog opens, user chooses appropriate icon by pressing on it, then dialog closes and returns to me id of this icon.
How could I do it?
Thanks.
You want to create an alertDialog with a custom grid in it. In my answer I assume that OP wanted to know how to create such a dialog in general. Therefore I am using a normal style. If you want to use a dark style, create a custom styling and use it in your AlertDialog.Builder:
AlertDialog.Builder builder = new AlertDialog.Builder(context, <YourCustomStyle>);
Result:
Create the layout for a single entry. Since OP is only showing icons, I only use an ImageView. If the icon should for example have text under it, you simply could create a TextView below it and fill it with your text.
view_icon_chooser_entry.xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/image_choose_icon_entry"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:contentDescription="#null"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</android.support.constraint.ConstraintLayout>
Create an adapter that can deal with the data and create the layout. In my example I am extending from a BaseAdapter since this is quite easy to do. A little bit more modern would be to use a RecyclerView and create your own custom adapter for it.
AlertDialogImageAdapter.java:
public class AlertDialogImageAdapter extends BaseAdapter {
private LayoutInflater layoutInflater;
AlertDialogImageAdapter(Context context) {
layoutInflater = LayoutInflater.from(context);
}
#Override
public int getCount() {
return iconList.length;
}
#Override
public Object getItem(int position) {
return iconList[position];
}
#Override
public long getItemId(int position) {
return position;
}
#SuppressLint("InflateParams")
#NonNull
public View getView(int position, View convertView, #NonNull ViewGroup parent) {
AlertDialogViewHolder alertDialogViewHolder;
if (convertView == null) {
// This is an alertDialog, therefore it has no root
convertView = layoutInflater.inflate(R.layout.view_icon_chooser_entry, null);
DisplayMetrics metrics = convertView.getResources().getDisplayMetrics();
int screenWidth = metrics.widthPixels;
convertView.setLayoutParams(new GridView.LayoutParams(screenWidth / 6, screenWidth / 6));
alertDialogViewHolder = new AlertDialogViewHolder();
alertDialogViewHolder.icon = convertView.findViewById(R.id.image_choose_icon_entry);
convertView.setTag(alertDialogViewHolder);
} else {
alertDialogViewHolder = (AlertDialogViewHolder) convertView.getTag();
}
alertDialogViewHolder.icon.setAdjustViewBounds(true);
alertDialogViewHolder.icon.setScaleType(ImageView.ScaleType.CENTER_CROP);
alertDialogViewHolder.icon.setPadding(8, 8, 8, 8);
alertDialogViewHolder.icon.setImageResource(iconList[position]);
return convertView;
}
// This is your source for your icons, fill it with your own
private Integer[] iconList = {
android.R.drawable.ic_media_play, android.R.drawable.ic_media_pause,
android.R.drawable.ic_delete, android.R.drawable.ic_btn_speak_now,
android.R.drawable.ic_media_previous, android.R.drawable.ic_media_next,
android.R.drawable.ic_menu_my_calendar, android.R.drawable.ic_menu_agenda,
android.R.drawable.ic_media_play, android.R.drawable.ic_media_pause,
android.R.drawable.ic_delete, android.R.drawable.ic_btn_speak_now,
android.R.drawable.ic_media_previous, android.R.drawable.ic_media_next,
android.R.drawable.ic_menu_my_calendar, android.R.drawable.ic_menu_agenda,
android.R.drawable.ic_media_play, android.R.drawable.ic_media_pause,
android.R.drawable.ic_delete, android.R.drawable.ic_btn_speak_now,
android.R.drawable.ic_media_previous, android.R.drawable.ic_media_next,
android.R.drawable.ic_menu_my_calendar, android.R.drawable.ic_menu_agenda
};
private class AlertDialogViewHolder {
ImageView icon;
}
}
Then, place a method to create a new AlertDialog with your custom AlertDialogImageAdapterand use a grid for the layout. You can change how many columns you have with setNumColumns(4).
Put this method where you want to show the alert dialog and simply call it:
private void showAlertDialog(Context context) {
GridView gridView = new GridView(context);
gridView.setAdapter(new AlertDialogImageAdapter(context));
gridView.setNumColumns(4);
gridView.setGravity(Gravity.CENTER);
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// TODO: Implement
Toast.makeText(view.getContext(), "Clicked position is: " + position, Toast.LENGTH_LONG).show();
}
});
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setView(gridView);
builder.setTitle(R.string.title_chose_icon);
builder.show();
}
I will suggest you to "imitate" the dialog and not using the android one.
For that, you can create a second layout with the dark grey background and all your clickable icons inside. When you will call the dialog, set the dimming to the main layout and put the one with the icons on the top.
I am using this in my app. I will provide you some code in 10min.
Have a look at the fragments section in the API Demo app. There are some dialogs you can use

Android app - how do I update my ListItem?

For an Android app...I have a button on an Activity that calls a custom ListActivity. This ListActivity has two lines of text and a checkbox. When invoked, the ListActivity opens up an XML file on the device (local.xml) . This XML file contains a list of target XML files on the web. If the file exists on the device, the checkbox on the ListActivity is checked, otherwise it isn't.
When the ListItem is pressed, it checks to see if the target file exists on the device-if it does, it displays a dialog box asking if they want to overwrite. If the file doesn't exist, or if they chose to overwrite, a progress dialog is displayed as it goes to the internet and grabs a set of files (the target XML file contains a list of JPegs to gather).
After downloading the JPegs, I change the message on the progress to show whether all the JPegs downloaded or not. It sleeps for a few seconds, then disapears.
All of the above works.
My questions are:
After completion, how do I set the checkbox associated with the pressed item, based on whether all of the JPegs downloaded or not?
I'd really like a tri-state indicator instead of a checkbox, which is binary, unless I could change the color to yellow. Is there a better widget I should be using here?
Relvant code follows (let me know if you need to see more)
Initial Activity:
public class RRS_Preferences extends Activity {
onCreate(yadda, yadda) {
}
public void Button_Listener(View view) {
/* open up the ListView Activity */
Intent myIntent = new Intent();
myIntent.setClassName("com.sinisterlabs.mypackage", "com.sinisterlabs.mypackage.Download_List");
startActivity(myIntent);
}
}
Custom List Activity:
public class Download_List extends ListActivity {
List<Location>loc_list = new ArrayList<Location>();
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setListAdapter(new RRSList_ArrayAdapter(this));
selection = (TextView)findViewById(R.id.tableRow1);
/* Open the "local.xml" file, pull from it the list of files that need to go
onto the ListActivity. For each file, I add it to the List. */
loc_list.add(new Location(stringLocalFilename, stringURL, booleanIsPresent));
}
protected void onListItemClick(final ListView parent, final View v, int position, long href) {
if (fileLocalFile.exists) {
subDownloadJPegs(fileLocalFile);
} else { // Ask to download or not?
AlertDialog.Builder alertBuilder = new AlertDialog.Builder(this);
alertBuilder.setMessage("Are you sure you want to OverWrite this file and all of its image files?")
.setCancelable(false)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
subDownloadJPegs(fileLocalFile);
}
});
.setNegativeButton("No", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
Toast.makeText(getApplicationContext(), "OverWrite Operation Cancelled...", Toast.LENGTH_LONG).show();
}
});
AlertDialog alert = alertBuilder.create();
alert.show();
}
}
private void subDownloadJPegs(fileLocalFile) {
progDialog = new ProgressDialog(this);
progDialog.setCancelable(true);
progDialog.setMessage("Downloading files for " + fileLocalFile.toString() + "...");
progDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progDialog.setProgress(0);
/* open up this file and count the number of JPegs to be downloaded */
progDialog.setMax(intMax);
progDialog.setMessage("Downloading Sign Files for " + RuleSetName + "...");
progDialog.show();
/* background thread to update progress bar */
Thread background = new Thread (new Runnable() {
#Overide
public void run() {
/* Inside a loop, download each file, increment the progress bar as we do */
progressHandler.sendMessage(progressHandler.obtainMessage());
}
background.start();
}
Handler progressHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
progDialog.incrementProgressBy(1);
}
}
List Item Layout XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<CheckBox
android:id="#+id/checkBox1"
android:layout_width="50dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:clickable="false"
android:focusable="false"
android:gravity="center" />
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView android:id="#+id/text1"
android:layout_width="fill_parent"
android:layout_height="20dp"
android:textSize="18dp"></TextView>
<TextView android:id="#+id/text2"
android:layout_width="fill_parent"
android:layout_height="15dp"
android:textSize="13dp"></TextView>
</LinearLayout>
</LinearLayout>
Thanks!!!
OK, I got it. the problem was where I placed the call to dismiss the dialog box. It ended up inside a catch statement and was never executing. In fixing this, I also parameterized my calls to the handler, which made things clearer.
Wheh!
:-)

Categories

Resources