package org.commcare.views.widgets; import android.content.Context; import android.util.TypedValue; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.inputmethod.InputMethodManager; import android.widget.AdapterView; import android.widget.AdapterView.OnItemSelectedListener; import android.widget.ArrayAdapter; import android.widget.Spinner; import android.widget.TextView; import org.commcare.dalvik.R; import org.javarosa.core.model.SelectChoice; import org.javarosa.core.model.data.IAnswerData; import org.javarosa.core.model.data.SelectOneData; import org.javarosa.core.model.data.helper.Selection; import org.javarosa.form.api.FormEntryPrompt; import java.util.Vector; /** * SpinnerWidget handles select-one fields. Instead of a list of buttons it uses a spinner, wherein * the user clicks a button and the choices pop up in a dialogue box. The goal is to be more * compact. If images, audio, or video are specified in the select answers they are ignored. * * @author Jeff Beorse (jeff@beorse.net) */ public class SpinnerWidget extends QuestionWidget { private final Vector<SelectChoice> mItems; private final Spinner spinner; private final String[] choices; public SpinnerWidget(Context context, FormEntryPrompt prompt) { super(context, prompt); mItems = prompt.getSelectChoices(); spinner = new Spinner(context); choices = new String[mItems.size()]; for (int i = 0; i < mItems.size(); i++) { choices[i] = prompt.getSelectChoiceText(mItems.get(i)); } // The spinner requires a custom adapter. It is defined below SpinnerAdapter adapter = new SpinnerAdapter(getContext(), android.R.layout.simple_spinner_item, getChoicesWithEmptyFirstSlot(choices), TypedValue.COMPLEX_UNIT_DIP, mQuestionFontSize); spinner.setAdapter(adapter); spinner.setPrompt(prompt.getQuestionText()); spinner.setEnabled(!prompt.isReadOnly()); spinner.setFocusable(!prompt.isReadOnly()); // Fill in previous answer String s = null; if (prompt.getAnswerValue() != null) { s = ((Selection)prompt.getAnswerValue().getValue()).getValue(); } if (s != null) { for (int i = 0; i < mItems.size(); ++i) { String sMatch = mItems.get(i).getValue(); if (sMatch.equals(s)) { spinner.setSelection(i+1); } } } spinner.setOnItemSelectedListener(new OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) { widgetEntryChanged(); } @Override public void onNothingSelected(AdapterView<?> parent) { //do nothing here } }); addView(spinner); } public static String[] getChoicesWithEmptyFirstSlot(String[] originalChoices) { //Creates an empty option to be displayed the first time the widget is shown String[] newChoicesList = new String[originalChoices.length+1]; newChoicesList[0] = ""; System.arraycopy(originalChoices, 0, newChoicesList, 1, originalChoices.length); return newChoicesList; } @Override public IAnswerData getAnswer() { int i = spinner.getSelectedItemPosition(); if (i < 1) { return null; } else { SelectChoice sc = mItems.elementAt(i-1); return new SelectOneData(new Selection(sc)); } } @Override public void clearAnswer() { // It seems that spinners cannot return a null answer. This resets the answer // to its original value, but it is not null. spinner.setSelection(0); } @Override public void setFocus(Context context) { // Hide the soft keyboard if it's showing. InputMethodManager inputManager = (InputMethodManager)context.getSystemService(Context.INPUT_METHOD_SERVICE); inputManager.hideSoftInputFromWindow(this.getWindowToken(), 0); } // Defines how to display the select answers private class SpinnerAdapter extends ArrayAdapter<String> { final Context context; final String[] items; final int textUnit; final float textSize; public SpinnerAdapter(final Context context, final int textViewResourceId, final String[] objects, int textUnit, float textSize) { super(context, textViewResourceId, objects); this.items = objects; this.context = context; this.textUnit = textUnit; this.textSize = textSize; } @Override // Defines the text view parameters for the drop down list entries public View getDropDownView(int position, View convertView, ViewGroup parent) { if (convertView == null) { LayoutInflater inflater = LayoutInflater.from(context); convertView = inflater.inflate(R.layout.custom_spinner_item, parent, false); } TextView tv = (TextView)convertView.findViewById(android.R.id.text1); tv.setText(items[position]); tv.setTextSize(textUnit, textSize); tv.setPadding(10, 10, 10, 10); return convertView; } @Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { LayoutInflater inflater = LayoutInflater.from(context); convertView = inflater.inflate(android.R.layout.simple_spinner_item, parent, false); } TextView tv = (TextView)convertView.findViewById(android.R.id.text1); tv.setText(items[position]); tv.setTextSize(textUnit, textSize); return convertView; } } @Override public void setOnLongClickListener(OnLongClickListener l) { spinner.setOnLongClickListener(l); } @Override public void unsetListeners() { super.unsetListeners(); spinner.setOnLongClickListener(null); } @Override public void cancelLongPress() { super.cancelLongPress(); spinner.cancelLongPress(); } }