web-dev-qa-db-de.com

Android-Rasteransicht - Element bleibt ausgewählt

Ich habe eine GridView mit mehreren Elementen, aber die Elemente müssen ausgewählt bleiben, sobald der onClickListener aufgerufen wird. Wie kann ich das erreichen?

Ich habe bereits v.setSelected(true) versucht, aber es scheint nicht zu funktionieren.

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

Dies ist ein kleiner Teil des Codes für den onClickListener, da ich viele Fälle habe.

16
Dorin Rusu

Das Konzept, das Sie erreichen möchten, ist möglich, aber nicht so, wie Sie jetzt arbeiten. 

Die beste und einfachste Lösung wäre, den Status der angeklickten Elemente zu verfolgen und ihnen das korrekte Layout im Adapter zu geben. Ich habe ein kleines Beispiel aufgestellt:

Aktivität

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

Ich denke, ein besserer Ansatz besteht darin, der GridView mitzuteilen, dass Sie die Auswahl der Elemente unterstützen möchten:

gridView.setChoiceMode(GridView.CHOICE_MODE_MULTIPLE);

stellen Sie dann sicher, dass items in GridView Checkable interface implementieren. Das bedeutet, dass die Elemente entweder Checkbox, ToggleButton usw. sein können, oder Sie können die Checkable-Unterstützung selbst hinzufügen. (Siehe das Beispiel unten.)

Im Gegensatz zu der anderen Antwort wird die meiste Arbeit von GridView selbst erledigt - es wird keine onClickListener benötigt. Statt den Zustand selbst zu speichern, rufen Sie einfach gridView.getCheckedItemIds() oder eine ähnliche Methode auf.


Um RelativeLayout (oder irgendetwas) überprüfbar zu machen, machen Sie eine Unterklasse daraus:

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

}

Beachten Sie, dass die Methode onCreateDrawableState den visuellen Stil aktualisiert. Sie müssen dies nicht auf diese Weise tun, Sie können beispielsweise den Hintergrund in der setChange-Methode direkt ändern.

Verwenden Sie dann die CheckableRelativeLayout als Draufsicht für Elemente in der 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>

Und definieren Sie, wie sich der Hintergrund ändert, wenn das Element in res/drawable/my_awesome_background.xml eingecheckt wird:

<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

Hier ist eine kurze Version der Antwort von Strix (die meiner Meinung nach besser ist als die akzeptierte Antwort), wenn Sie den Code nicht an anderer Stelle wiederverwenden müssen. Anstatt eine neue Klasse zu erstellen und Checked zu implementieren, können Sie einfach eine anonyme Klasse in Ihrer Adapter.getView-Methode erstellen, die onCreateDrawableState wie in der Antwort von Strix überschreibt, aber isChecked() dort durch ((AbsListView)parent).isItemChecked(position) ersetzen. Hier ist der vollständige Code meines Adapters, der einen Rahmen um die überprüften Miniaturbilder in einer Galerie zieht:

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

Ich weiß, die Antwort ist ein bisschen alt. Aber ich denke, es ist die einfachste von allen ... In Ihrer Adapterklasse fügen Sie eine Variable hinzu, die die ausgewählte Elementposition enthält. Legen Sie Transparenz für alle Bilder außer der ausgewählten in der GetView-Methode fest Sichern Sie in der Hauptmethode die ausgewählte ItemPosition . Benachrichtigen Sie den Adapter, dass er geändert hat.

Fügen Sie in Ihrer Adapterklasse eine Variable hinzu, die die ausgewählte Artikelposition enthält.

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

Legen Sie die Transparenz für alle Bilder außer der in der Adapter-GetView-Methode ausgewählten fest.

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

Sichern Sie in Ihrem Click-Handler in der Hauptmethode die ausgewählte ItemPosition . Benachrichtigen Sie den Adapter, dass er geändert hat

   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

die Ansichten in der Variablen gridview müssen CheckBoxs sein. Auf diese Weise können Sie sie aktivieren und deaktivieren.

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