public View renderComboBox()

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;
        }
    }