Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I've been experimenting with making more complex views in Spinners' dialogs.</p> <p>To do what you've explained, I made a subclass of <code>Spinner</code>. I examined the <strong><a href="http://www.netmite.com/android/mydroid/frameworks/base/core/java/android/widget/Spinner.java" rel="nofollow">source</a></strong> of the Android Spinner and overrided the <code>performClick</code> to do essentially what you want: populate your own dialog with a custom view.</p> <pre><code>package me.ribose.example; // you'll have to change this import android.app.AlertDialog; import android.content.Context; import android.database.DataSetObserver; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.Button; import android.widget.ListAdapter; import android.widget.ListView; import android.widget.Spinner; import android.widget.SpinnerAdapter; public class CustomSpinner extends Spinner implements OnItemClickListener { private AlertDialog mDialog = null; private OnClickListener mButtonClickListener = null; public UnitSelectionSpinner(Context context, AttributeSet attrs) { super(context, attrs); } public void setButtonClickListener(OnClickListener listener) { mButtonClickListener = listener; } @Override public boolean performClick() { Context context = getContext(); // get the set adapter final DropDownAdapter adapter = new DropDownAdapter(getAdapter()); // inflate our layout final LayoutInflater inflater = LayoutInflater.from(getContext()); final View v = inflater.inflate(R.layout.customSpinner, null); // set up list view final ListView lv = (ListView) v.findViewById(R.id.list); lv.setAdapter(adapter); lv.setSelection(getSelectedItemPosition()); lv.setOnItemClickListener(this); // set up button final Button btn = (Button) v.findViewById(R.id.addButton); btn.setOnClickListener(mButtonClickListener); // build our dialog AlertDialog.Builder builder = new AlertDialog.Builder(context); // show prompt, just as our Spinner parent does if (getPrompt() != null) { builder.setTitle(getPrompt()); } // create and show dialog mDialog = builder.setView(v).create(); mDialog.show(); return true; } @Override public void onItemClick(AdapterView&lt;?&gt; view, View itemView, int position, long id) { setSelection(position); if (mDialog != null) { mDialog.dismiss(); mDialog = null; } } /** * &lt;p&gt;Wrapper class for an Adapter. Transforms the embedded Adapter instance * into a ListAdapter.&lt;/p&gt; */ private static class DropDownAdapter implements ListAdapter, SpinnerAdapter { private SpinnerAdapter mAdapter; /** * &lt;p&gt;Creates a new ListAddapter wrapper for the specified adapter.&lt;/p&gt; * * @param adapter the Adapter to transform into a ListAdapter */ public DropDownAdapter(SpinnerAdapter adapter) { this.mAdapter = adapter; } public int getCount() { return mAdapter == null ? 0 : mAdapter.getCount(); } public Object getItem(int position) { return mAdapter == null ? null : mAdapter.getItem(position); } public long getItemId(int position) { return mAdapter == null ? -1 : mAdapter.getItemId(position); } public View getView(int position, View convertView, ViewGroup parent) { return getDropDownView(position, convertView, parent); } public View getDropDownView(int position, View convertView, ViewGroup parent) { return mAdapter == null ? null : mAdapter.getDropDownView(position, convertView, parent); } public boolean hasStableIds() { return mAdapter != null &amp;&amp; mAdapter.hasStableIds(); } @Override public void registerDataSetObserver(DataSetObserver observer) { if (mAdapter != null) { mAdapter.registerDataSetObserver(observer); } } @Override public void unregisterDataSetObserver(DataSetObserver observer) { if (mAdapter != null) { mAdapter.unregisterDataSetObserver(observer); } } /** * &lt;p&gt;Always returns false.&lt;/p&gt; * * @return false */ public boolean areAllItemsEnabled() { return true; } /** * &lt;p&gt;Always returns false.&lt;/p&gt; * * @return false */ public boolean isEnabled(int position) { return true; } public int getItemViewType(int position) { return 0; } public int getViewTypeCount() { return 1; } public boolean isEmpty() { return getCount() == 0; } } } </code></pre> <p>You'll need my customSpinner.xml:</p> <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt; &lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"&gt; &lt;ListView android:id="@+id/list" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1" android:layout_marginTop="5px" android:cacheColorHint="@null" android:background="@android:color/background_light" android:divider="@android:drawable/divider_horizontal_bright" android:scrollbars="vertical"&gt; &lt;/ListView&gt; &lt;Button android:id="@+id/addButton" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Add to Database"&gt; &lt;/Button&gt; &lt;/LinearLayout&gt; </code></pre> <p>Of course, make that <code>android:text</code> a string resource.</p> <p>More words on this: Just make a <code>CustomSpinner</code> in your activity's layout as you need it and call <code>setButtonClickListener</code> (probably near where you set the adapter) to add a callback for your button, that perhaps prompts the user to add or whatever you need. And of course <code>notifyDataSetChanged()</code> on your adapter after adding to the database. Everything that works on a Spinner should work exactly the same with this custom spinner.</p> <p>Side note (UPDATED): You will have to make sure your adapter's list items have black text (ex: <code>android:textColor="@android:color/primary_text_light_nodisable"</code>)! I changed the XML above so it doesn't require white background on items (which then makes item highlights not work).</p> <hr> <p>Code notes: Since the people who made Android decided to not make an easy way to customize spinner dialogs (hard-coded use of <code>AlertDialog.Builder</code> using <code>setSingleChoiceItems()</code> as well as a private class to "convert" <code>SpinnerAdapter</code>s to <code>ListAdapter</code>s), I had to copy their entire inner class to get the desired effect. Also note they are bad documenters (see <code>DropDownAdapter</code>.<code>isEnabled</code>/<code>areAllItemsEnabled</code> for the laugh of the day!).</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload