web-dev-qa-db-fra.com

Gridview Android garder l'élément sélectionné

J'ai un GridView avec plusieurs éléments, mais les éléments doivent être conservés lorsque le onClickListener est appelé. Comment puis-je y parvenir?

J'ai déjà essayé v.setSelected(true) mais cela ne semble pas fonctionner.

gridview.setOnItemClickListener(new OnItemClickListener() {
        public void onItemClick(AdapterView<?> parent, View v,
                int position, long id) {
            // Toast.makeText(Project.this, "Red" + position,
            // Toast.LENGTH_SHORT).show(); //position = al catelea element
            v.setPressed(true);
            if (bp == 2) {
                if (position == 0) {
                Square.setSex(R.drawable.girl_body2v);
                Square2.setHair(R.drawable.girl_hair_01v);
                SquareAccesories.setAcc(R.drawable.girl_accessories_01v);
                SquareEyes.setEyes(R.drawable.eyes_1v);
                SquareLips.setLips(R.drawable.lip_1v);
                Square3.setDress(R.drawable.girl_tops_01v);
                SquareShoes.setShoes(R.drawable.girl_shoes_01v);
                SquarePants.setPants(R.drawable.girl_bottom_01v);
                setS(2);

Ceci est une petite partie du code pour le onClickListener parce que j'ai beaucoup de cas.

16
Dorin Rusu

Le concept que vous souhaitez atteindre est possible, mais pas comme vous le faites actuellement. 

La solution la meilleure et la plus simple consiste à suivre les états des éléments sur lesquels vous avez cliqué et à leur attribuer la mise en page correcte dans l'adaptateur. J'ai mis en place un petit exemple:

Activité

public class StackOverFlowActivity extends Activity {
    GridView gridView;
    MyCustomAdapter myAdapter;
    ArrayList<GridObject> myObjects;

    static final String[] numbers = new String[] { "A", "B", "C", "D", "E",
            "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R",
            "S", "T", "U", "V", "W", "X", "Y", "Z" };

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        myObjects = new ArrayList<GridObject>();
        for (String s : numbers) {
            myObjects.add(new GridObject(s, 0));
        }

        gridView = (GridView) findViewById(R.id.gridView1);

        myAdapter = new MyCustomAdapter(this);

        gridView.setAdapter(myAdapter);
        gridView.setOnItemClickListener(new OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> arg0, View v, int position, long arg3) {
                myObjects.get(position).setState(1);
                myAdapter.notifyDataSetChanged();
            }
        });
    }

    static class ViewHolder {
        TextView text;
    }

    private class MyCustomAdapter extends BaseAdapter  {

        private LayoutInflater mInflater;

        public MyCustomAdapter(Context context) {
            mInflater = LayoutInflater.from(context);
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            GridObject object = myObjects.get(position);
            ViewHolder holder;

            if (convertView == null) {
                convertView = mInflater.inflate(R.layout.list_item_icon_text, null);
                holder = new ViewHolder();
                holder.text = (TextView) convertView.findViewById(R.id.text);
                convertView.setTag(holder);
            } else {
                holder = (ViewHolder) convertView.getTag();
            }

            holder.text.setText(object.getName());

            if (object.getState() == 1) {
                holder.text.setBackgroundColor(Color.GREEN);
            } else {
                holder.text.setBackgroundColor(Color.BLUE);
            }
            return convertView;
        }

        @Override
        public int getCount() {
            return myObjects.size();
        }

        @Override
        public Object getItem(int position) {
            return position;
        }

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

GridObject

public class GridObject {

    private String name;
    private int state;

    public GridObject(String name, int state) {
        super();
        this.name = name;
        this.state = state;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getState() {
        return state;
    }

    public void setState(int state) {
        this.state = state;
    }   
}

Main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="fill_parent"
    Android:layout_height="fill_parent"
    Android:orientation="vertical" >

    <GridView
        Android:id="@+id/gridView1"
        Android:layout_width="fill_parent"
        Android:layout_height="fill_parent"
        Android:columnWidth="50dp"
        Android:gravity="center"
        Android:numColumns="auto_fit"
        Android:stretchMode="columnWidth" >
    </GridView>

</LinearLayout>

list_item_icon_text

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:orientation="vertical" >

    <TextView
        Android:id="@+id/text"
        Android:layout_width="fill_parent"
        Android:layout_height="fill_parent" />

</LinearLayout>
17
DroidBender

Je pense qu'une meilleure approche consiste à indiquer à la GridView que vous souhaitez appuyer la sélection (la vérification) des éléments:

gridView.setChoiceMode(GridView.CHOICE_MODE_MULTIPLE);

puis assurez-vous que items dans GridView implémentent Checkable interface. Cela signifie que les éléments peuvent être Checkbox, ToggleButton et ainsi de suite ou que vous pouvez ajouter le support Checkable vous-même - par exemple, activez la case à cocher RelativeLayout. (Voir l'exemple ci-dessous.)

Contrairement à l’autre réponse, la plupart du travail est pris en charge par le GridView lui-même - aucune variable onClickListener n’est nécessaire. Au lieu de stocker vous-même l'état, appelez simplement gridView.getCheckedItemIds() ou une méthode similaire.


Pour rendre RelativeLayout (ou quoi que ce soit) vérifiable, créez-en une sous-classe:

public class CheckableRelativeLayout extends RelativeLayout implements Checkable {
    private boolean checked = false;
    private static final int[] CHECKED_STATE_SET = { Android.R.attr.state_checked };

    public CheckableRelativeLayout(Context context) {
        super(context);
    }

    public CheckableRelativeLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public CheckableRelativeLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    protected int[] onCreateDrawableState(int extraSpace) {
         final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
         if (isChecked())
             mergeDrawableStates(drawableState, CHECKED_STATE_SET);
         return drawableState;
    }

    @Override
    public boolean isChecked() {
        return checked;
    }

    @Override
    public void setChecked(boolean _checked) {
        checked = _checked;
        refreshDrawableState();
    }

    @Override
    public void toggle() {
        setChecked(!checked);
    }

}

Notez que la méthode onCreateDrawableState met à jour le style visuel. Vous n'avez pas à le faire de cette façon, vous pouvez par exemple modifier directement l'arrière-plan dans la méthode setChange.

Utilisez ensuite la CheckableRelativeLayout comme vue de dessus pour les éléments du GridView:

<foo.bar.CheckableRelativeLayout
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:background="@drawable/my_awesome_background"
    ... more stuff
    >
        ...  content of the relative layout
</com.test.CheckableRelativeLayout>

Et définissez comment l'arrière-plan change lorsque l'élément est coché dans res/drawable/my_awesome_background.xml:

<selector xmlns:Android="http://schemas.Android.com/apk/res/Android" > 
     <item Android:state_checked="true" >
        <!-- This applies when the item is checked. -->
         <shape Android:shape="rectangle"  >
             <solid Android:color="#A8DFF4" />
         </shape>
     </item>

    <item>
        <!-- This applies when the item is not checked. -->
        <shape Android:shape="rectangle"  >
             <solid Android:color="#EFEFEF" />
         </shape>
     </item>
</selector>
52
Strix

Voici une version plus floue de la réponse de Strix (qui, à mon avis, est meilleure que la réponse acceptée) lorsque vous n'avez pas besoin de réutiliser ce code ailleurs. Au lieu de créer une nouvelle classe et d'implémenter Checked, vous pouvez simplement créer une classe anonyme dans votre méthode Adapter.getView, en remplaçant onCreateDrawableState comme dans la réponse de Strix, mais en remplaçant isChecked() par ((AbsListView)parent).isItemChecked(position). Voici le code complet de mon adaptateur qui trace une bordure autour des vignettes cochées dans une galerie:

public class ImageAdapter extends BaseAdapter {
    private final int[] CHECKED_STATE_SET = { Android.R.attr.state_checked };
    public int getCount() {return images.size();}
    public Object getItem(int position) {return images.get(position);}
    public long getItemId(int position) {return position;}

    public View getView(final int position, final View convertView, final ViewGroup parent) {
        final ImageView imageView = new ImageView(getApplicationContext()) {
            @Override public int[] onCreateDrawableState(int extraSpace) {
                final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
                if (((AbsListView)parent).isItemChecked(position)) {
                    mergeDrawableStates(drawableState, CHECKED_STATE_SET);
                }
                return drawableState;
            }
        };
        imageView.setBackground(getResources().getDrawable(R.drawable.my_awesome_background));
        imageView.setScaleType(ImageView.ScaleType.CENTER);
        final byte[] buffer = images.get(position);
        final Bitmap bmp = BitmapFactory.decodeByteArray(buffer, 0, buffer.length);
        imageView.setImageBitmap(bmp);
        return imageView;
    }
}
6
Dax Fohl

Je sais que la réponse est un peu vieille. Mais je pense que c'est la solution la plus simple . Dans votre classe d'adaptateur, ajoutez une variable contenant la position d'élément sélectionnée . Définissez la transparence sur toutes les images, à l'exception de celle sélectionnée dans la méthode GetView . dans la méthode principale, sécurisez la position d'élément sélectionnée . Avertissez l'adaptateur qu'il a changé.

Dans votre classe d'adaptateur, ajoutez une variable contenant la position d'élément sélectionnée.

public class GridImageAdapter extends BaseAdapter {
       public int selectedImage = 0;

Définissez la transparence sur toutes les images, à l'exception de celle sélectionnée dans la méthode Adapter GetView.

@Override
public View getView(final int position, View convertView, final ViewGroup parent) {
    int[] images = { R.drawable.walk, R.drawable.run, R.drawable.jump }

    ImageView imageView = new ImageView(mContext);
    if (position < imgMapper.length) {

        imageView.setImageResource(images[position]);

        if (position != selectedImage) {
            imageView.setImageAlpha(50);
        }
        imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
        imageView.setLayoutParams(new GridView.LayoutParams(150, 150));
    };

    return imageView;
}

Dans votre gestionnaire de clics dans la méthode principale, sécurisez l'élément ItemPosition sélectionné . Avertissez l'adaptateur qu'il a changé

   myGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
            GridImageAdapter myAdapter = (GridImageAdapter) myGridView.getAdapter();
            myAdapter.selectedImage = position;
            myAdapter.notifyDataSetChanged();
        }
    });
3
maniac

les vues dans gridview doivent être CheckBoxs, de cette façon vous pouvez les cocher et les décocher.

1
Mohammad Ersan
**You can add tag and check for tag**


 gv.setOnItemClickListener((adapterView, view, i, l) -> {

                int f = gv.getCheckedItemPosition();

                if(view.getTag()=="selected")
                {
                    view.setTag("notselected");
                    String clickedText = gv.getItemAtPosition(i).toString();
                    filterKeywords.remove(clickedText);
                    view.setBackgroundColor(Color.WHITE);
                }
                else
                {
                    view.setTag("selected");
                    String clickedText = gv.getItemAtPosition(i).toString();
                    filterKeywords.add(clickedText);
                    view.setBackgroundColor(Color.GREEN);

                }

                System.out.println("KEYWORDS"+filterKeywords);


            });
0
qwerty421