in source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/input/ChoiceSetInputRenderer.java [242:395]
public View renderComboBox(
RenderedAdaptiveCard renderedCard,
Context context,
ChoiceSetInput choiceSetInput,
HostConfig hostConfig,
RenderArgs renderArgs)
{
final Vector<String> titleList = new Vector<>();
ChoiceInputVector choiceInputVector = choiceSetInput.GetChoices();
long size = choiceInputVector.size();
int selection = 0;
String value = choiceSetInput.GetValue();
for (int i = 0; i < size; i++)
{
ChoiceInput choiceInput = choiceInputVector.get(i);
titleList.addElement(choiceInput.GetTitle());
if (choiceInput.GetValue().equals(value))
{
selection = i;
}
}
// If the default value is empty, then create an empty option at the end to avoid any mess
// with indexes
boolean hasEmptyDefault = value.isEmpty();
if (hasEmptyDefault)
{
// Android has an undocumented behaviour where a spinner with an empty option selected
// will not receive accessibility focus, if we add an single space ' ' then the spinner
// can receive focus.
String placeholder = choiceSetInput.GetPlaceholder();
if (placeholder.isEmpty())
{
placeholder = " ";
}
titleList.addElement(placeholder);
selection = (int) size;
}
boolean usingCustomInputs = isUsingCustomInputs(context);
final Spinner spinner = new ValidatedSpinner(context, usingCustomInputs);
final ComboBoxInputHandler comboBoxInputHandler = new ComboBoxInputHandler(choiceSetInput);
boolean isRequired = choiceSetInput.GetIsRequired();
ValidatedInputLayout inputLayout = null;
// if using custom inputs, we don't have to create the surrounding linear layout
boolean needsOuterLayout = (isRequired && !usingCustomInputs);
if (needsOuterLayout)
{
inputLayout = new ValidatedSpinnerLayout(context,
getColor(hostConfig.GetForegroundColor(ContainerStyle.Default, ForegroundColor.Attention, false)));
inputLayout.setTag(new TagContent(choiceSetInput, comboBoxInputHandler));
comboBoxInputHandler.setView(inputLayout);
}
else
{
spinner.setTag(new TagContent(choiceSetInput, comboBoxInputHandler));
comboBoxInputHandler.setView(spinner);
}
renderedCard.registerInputHandler(comboBoxInputHandler, renderArgs.getContainerCardId());
class TextSpinnerAdapter extends ArrayAdapter<String>
{
TextSpinnerAdapter(Context context, int resource,
Vector<String> items, boolean hasEmptyDefault)
{
super(context, resource, items);
m_hasEmptyDefault = hasEmptyDefault;
m_itemCount = items.size();
}
public int getCount()
{
if (m_hasEmptyDefault)
{
return m_itemCount - 1;
}
else
{
return m_itemCount;
}
}
private int m_itemCount = 0;
private boolean m_hasEmptyDefault = false;
}
class WrappedTextSpinnerAdapter extends TextSpinnerAdapter
{
WrappedTextSpinnerAdapter(Context context, int resource,
Vector<String> items, boolean hasEmptyDefault)
{
super(context, resource, items, hasEmptyDefault);
}
@NonNull
@Override
// getView returns the view when spinner is not selected
// override method disables single line setting
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent)
{
View view = super.getView(position, convertView, parent);
TextView txtView = view.findViewById(android.R.id.text1);
txtView.setSingleLine(false);
return view;
}
}
ArrayAdapter<String> spinnerArrayAdapter;
if (choiceSetInput.GetWrap())
{
spinnerArrayAdapter = new WrappedTextSpinnerAdapter(context, android.R.layout.simple_spinner_item, titleList, hasEmptyDefault);
}
else
{
spinnerArrayAdapter = new TextSpinnerAdapter(context, android.R.layout.simple_spinner_item, titleList, hasEmptyDefault);
}
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(spinnerArrayAdapter);
spinner.setSelection(selection);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener()
{
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id)
{
CardRendererRegistration.getInstance().notifyInputChange(comboBoxInputHandler.getId(), comboBoxInputHandler.getInput());
}
@Override
public void onNothingSelected(AdapterView<?> parent)
{
CardRendererRegistration.getInstance().notifyInputChange(comboBoxInputHandler.getId(), comboBoxInputHandler.getInput());
}
});
spinner.setFocusable(true);
if (needsOuterLayout)
{
inputLayout.addView(spinner);
return inputLayout;
}
else
{
return spinner;
}
}