web-dev-qa-db-fra.com

android spinner

J'ai Spinner comme ceci:

<Spinner
                Android:layout_width="match_parent"
                Android:layout_height="wrap_content"
                Android:id="@+id/spinner1"
                Android:background="@drawable/spinner_bg"
                Android:popupBackground="@drawable/spinner_bg"/>

c'est spinner_bg.xml:

<item>
    <layer-list>
        <item>
            <shape>
                <gradient
                    Android:startColor="#ffffff"
                    Android:centerColor="#111111"
                    Android:endColor="#000000"
                    Android:angle="-90" />

                <stroke
                    Android:width="2dp"
                    Android:color="#ffffff" />

                <corners
                    Android:radius="2dp" />

                <padding
                    Android:left="10dp"
                    Android:right="10dp"/>
            </shape>
        </item>
        <item >
            <bitmap
                Android:gravity="right"
                Android:src="@Android:drawable/arrow_down_float" />
        </item>
    </layer-list>
</item>

c'est mon code pour spinner personnalisé:

ArrayAdapter<ClassId> adapter = new ArrayAdapter<ClassId>(getActivity(),
                        R.layout.list_id, idList);
                adapter.setDropDownViewResource(R.layout.list_id_select);

c'est la disposition de list_id.xml:

<TextView xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:textAllCaps="true"
Android:singleLine="true"
Android:ellipsize="end"
Android:textColor="#ff0004"
Android:textSize="14sp"
Android:paddingTop="10dp"
Android:paddingBottom="10dp"/>

c'est la disposition de list_id_select.xml:

<CheckedTextView xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:textAllCaps="true"
Android:singleLine="true"
Android:ellipsize="end"
Android:textColor="#0004ff"
Android:textSize="14sp"
Android:checked="true"
Android:checkMark="@drawable/custom_checkbox"
Android:paddingTop="10dp"
Android:paddingBottom="10dp"/>

et c'est custom_checkbox.xml:

<selector xmlns:Android="http://schemas.Android.com/apk/res/Android">
<item Android:state_checked="true"
    Android:drawable="@Android:drawable/checkbox_on_background" /> 

<item Android:state_pressed="true"
    Android:drawable="@Android:drawable/checkbox_on_background" /> 

<item Android:drawable="@Android:drawable/checkbox_off_background" /> 

c'est mon résultat lorsque le menu déroulant de spinner montre: _________________________________________________
__________________________ case à cocher_______________
____texte_________________________________________

cela signifie que le texte et la case à cocher ne sont pas en ligne (case à cocher supérieure au texte).
comment le réparer?

10
1234abcd

Pour cela, vous devez créer Custom Adapter et définissez TextView et CheckBox à l'intérieur de cette manière ci-dessous.

Définissez Spinner en xml

<Spinner
        Android:id="@+id/spinner"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_centerHorizontal="true"
        Android:layout_marginTop="10dp" />

Créer spinner_item.xml fichier dans le dossier layout.

<?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/text"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:layout_marginLeft="20dp"
        Android:text="text"
        Android:textAlignment="gravity" />

    <CheckBox
        Android:id="@+id/checkbox"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_alignParentEnd="true"
        Android:layout_alignParentRight="true" />
</RelativeLayout>

Maintenant, créez StateVO.Java classe pouvant contenir les valeurs TextView et CheckBox.

public class StateVO {
    private String title;
    private boolean selected;

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public boolean isSelected() {
        return selected;
    }

    public void setSelected(boolean selected) {
        this.selected = selected;
    }
}

Maintenant, dans votre Activity initiez le Spinner et définissez CustomAdapter ci-dessous.

 final String[] select_qualification = {
                "Select Qualification", "10th / Below", "12th", "Diploma", "UG",
                "PG", "Phd"};
        Spinner spinner = (Spinner) findViewById(R.id.spinner);

        ArrayList<StateVO> listVOs = new ArrayList<>();

        for (int i = 0; i < select_qualification.length; i++) {
            StateVO stateVO = new StateVO();
            stateVO.setTitle(select_qualification[i]);
            stateVO.setSelected(false);
            listVOs.add(stateVO);
        }
        MyAdapter myAdapter = new MyAdapter(Main2Activity.this, 0,
                listVOs);
        spinner.setAdapter(myAdapter);

Et enfin, créez la classe CustomAdapter comme ci-dessous.

MyAdapter.Java

public class MyAdapter extends ArrayAdapter<StateVO> {
    private Context mContext;
    private ArrayList<StateVO> listState;
    private MyAdapter myAdapter;
    private boolean isFromView = false;

    public MyAdapter(Context context, int resource, List<StateVO> objects) {
        super(context, resource, objects);
        this.mContext = context;
        this.listState = (ArrayList<StateVO>) objects;
        this.myAdapter = this;
    }

    @Override
    public View getDropDownView(int position, View convertView,
                                ViewGroup parent) {
        return getCustomView(position, convertView, parent);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        return getCustomView(position, convertView, parent);
    }

    public View getCustomView(final int position, View convertView,
                              ViewGroup parent) {

        final ViewHolder holder;
        if (convertView == null) {
            LayoutInflater layoutInflator = LayoutInflater.from(mContext);
            convertView = layoutInflator.inflate(R.layout.spinner_item, null);
            holder = new ViewHolder();
            holder.mTextView = (TextView) convertView
                    .findViewById(R.id.text);
            holder.mCheckBox = (CheckBox) convertView
                    .findViewById(R.id.checkbox);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        holder.mTextView.setText(listState.get(position).getTitle());

        // To check weather checked event fire from getview() or user input
        isFromView = true;
        holder.mCheckBox.setChecked(listState.get(position).isSelected());
        isFromView = false;

        if ((position == 0)) {
            holder.mCheckBox.setVisibility(View.INVISIBLE);
        } else {
            holder.mCheckBox.setVisibility(View.VISIBLE);
        }
        holder.mCheckBox.setTag(position);
        holder.mCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {

            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                int getPosition = (Integer) buttonView.getTag();

                if (!isFromView) {
                    listState.get(position).setSelected(isChecked);
                }
            }
        });
        return convertView;
    }

    private class ViewHolder {
        private TextView mTextView;
        private CheckBox mCheckBox;
    }
}

Sortie:

enter image description here

34
Ironman

Ce message est une excellente ressource. Pour toute personne intéressée, j'ai créé un adaptateur générique basé sur l'autre réponse qui a bien fonctionné pour plusieurs types de données. Vous permet également de cliquer sur le texte pour désactiver la case à cocher.

public class CheckableSpinnerAdapter<T> extends BaseAdapter {

    static class SpinnerItem<T> {
        private String txt;
        private T item;

        SpinnerItem(T t, String s) {
            item = t;
            txt = s;
        }
    }

    private Context context;
    private Set<T> selected_items;
    private List<SpinnerItem<T>> all_items;
    private String headerText;

    CheckableSpinnerAdapter(Context context,
                            String headerText,
                            List<SpinnerItem<T>> all_items,
                            Set<T> selected_items) {
        this.context = context;
        this.headerText = headerText;
        this.all_items = all_items;
        this.selected_items = selected_items;
    }

    @Override
    public int getCount() {
        return all_items.size() + 1;
    }

    @Override
    public Object getItem(int position) {
        if( position < 1 ) {
            return null;
        }
        else {
            return all_items.get(position-1);
        }
    }

    @Override
    public long getItemId(int position) {
        return 0;
    }

    @Override
    @SuppressWarnings({"unchecked"})
    @NonNull
    public View getView(int position, View convertView, @NonNull ViewGroup parent) {

        final ViewHolder holder;
        if (convertView == null ) {
            LayoutInflater layoutInflator = LayoutInflater.from(context);
            convertView = layoutInflator.inflate(R.layout.checkable_spinner_item, parent, false);

            holder = new ViewHolder();
            holder.mTextView = convertView.findViewById(R.id.text);
            holder.mCheckBox = convertView.findViewById(R.id.checkbox);
            convertView.setTag(holder);
        }
        else {
            holder = (ViewHolder) convertView.getTag();
        }

        if( position < 1 ) {
            holder.mCheckBox.setVisibility(View.GONE);
            holder.mTextView.setText(headerText);
        }
        else {
            final int listPos = position - 1;
            holder.mCheckBox.setVisibility(View.VISIBLE);
            holder.mTextView.setText(all_items.get(listPos).txt);

            final T item = all_items.get(listPos).item;
            boolean isSel = selected_items.contains(item);

            holder.mCheckBox.setOnCheckedChangeListener(null);
            holder.mCheckBox.setChecked(isSel);

            holder.mCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    if( isChecked ) {
                        selected_items.add(item);
                    }
                    else {
                        selected_items.remove(item);
                    }
                }
            });

            holder.mTextView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    holder.mCheckBox.toggle();
                }
            });
        }

        return convertView;
    }

    private class ViewHolder {
        private TextView mTextView;
        private CheckBox mCheckBox;
    }
} 

Et la mise en page checkable_spinner_item.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">

    <CheckBox
        Android:id="@+id/checkbox"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_margin="16dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@id/text"
        app:layout_constraintBottom_toBottomOf="@id/text"/>

    <TextView
        Android:id="@+id/text"
        Android:layout_width="0dp"
        Android:layout_height="wrap_content"
        Android:layout_marginStart="16dp"
        Android:layout_marginLeft="16dp"
        Android:layout_marginTop="8dp"
        Android:layout_marginBottom="8dp"
        Android:textSize="16sp"
        Android:textColor="#000000"
        app:layout_constraintStart_toEndOf="@id/checkbox"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        Android:textAlignment="gravity" />

</Android.support.constraint.ConstraintLayout>

Vous l'utiliseriez en créant une liste d'éléments à afficher, un ensemble, qui contiendra les éléments sélectionnés et le texte de la ligne d'en-tête. Par exemple:

private final List<CheckableSpinnerAdapter.SpinnerItem<MyObject>> spinner_items = new ArrayList<>();
private final Set<MyObject> selected_items = new HashSet<>();

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // fill the 'spinner_items' array with all items to show
    List<MyObject> all_objects = getMyObjects(); // from wherever
    for(MyObject o : all_objects) {
        spinner_items.add(new CheckableSpinnerAdapter.SpinnerItem<>(o, o.getName()));
    }

    // to start with any pre-selected, add them to the `selected_items` set

    String headerText = "Click an Item";

    Spinner spinner = findViewById(R.id.my_spinner);
    CheckableSpinnerAdapter adapter = new CheckableSpinnerAdapter<>(this, headerText, spinner_items, selected_items);
    spinner.setAdapter(adapter);

    // when you want to see what the user has selected, look in the `selected_items`
    // set anywhere in your activity
}

Un exemple d'utilisation:

Example use

EDIT: MyObject peut être n'importe quelle classe ou énumération, tout ce que vous voulez associer aux éléments spinner. Si vous copiez cet exemple directement, il devrait implémenter une méthode String getName(). Voici un exemple simple:

class MyObject {
    private String mName;
    private String mAddr;

    MyObject(String name, String address) {
        mName = name;
        mAddr = address;
    }

    String getName() { return mName; }
    String getAddress() { return mAddr; }
}
0
Tyler V