Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Select multiple items in GridView

I am developing a gallery-like Activity. Everything runs fine but there is a key functionality which is missing and I couldn't find a decent answer or explanation. What I need is to give the user the ability to select multiple items by long clicking on them.

Here is the desired result:

enter image description here

You can clearly see the selected pics and the options in the ActionBar.



My setup is this:

1.I have a GridView in my XML:

<GridView xmlns:android="http://schemas.android.com/apk/res/android"
          android:id="@+id/gridview"
          android:layout_width="fill_parent"
          android:layout_height="fill_parent"
          android:columnWidth="90dp"
          android:numColumns="auto_fit"
          android:verticalSpacing="5dp"
          android:horizontalSpacing="5dp"
          android:stretchMode="columnWidth"
          android:gravity="center"/>

2.It is attached to a class, which extends BaseAdapter and loads images using Picasso:

public class GalleryAdapter extends BaseAdapter {
    Context mContext;
    List<String> mDataset;

    public GalleryAdapter(Context context, List<String> dataset) {
        mContext = context;
        mDataset = dataset;
    }

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

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

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ImageView imageView;
        if(convertView == null){
            imageView = new ImageView(mContext);
            imageView.setLayoutParams(new GridView.LayoutParams(200,200));
            imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
            imageView.setPadding(8,8,8,8);
        } else {
            imageView = (ImageView) convertView;
        }

        //TODO: REMOVE INTEGER.VALUEOFF. IT'S MADE FOR MOCK
        Picasso.with(mContext).load(Integer.valueOf(mDataset.get(position))).fit().into(imageView);

        return imageView;
    }


}

3.It is attached to the Activity:

//Get images paths
List<String> data = getImagesPath(this);
    List<String> sortedData = new ArrayList<>();
    for(String file : data){
        sortedData.add(0, file);
    }

    GalleryAdapter adapter = new GalleryAdapter(this, sortedData);
    mGallery.setAdapter(adapter);


From now on the struggle begins:

  • I tried making my item in the GridView to implement Checkable:

    public class CheckableItem extends LinearLayout implements Checkable{
    private boolean mIsChecked = false;
    private static final int[] CHECKED_STATE_SET = { android.R.attr.state_checked };
    
    public CheckableItem(Context context) {
        super(context);
    }
    
    @Override
    protected int[] onCreateDrawableState(int extraSpace) {
        int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
        if (isChecked())
            mergeDrawableStates(drawableState, CHECKED_STATE_SET);
        return drawableState;
    }
    
    @Override
    public void setChecked(boolean checked) {
        mIsChecked = checked;
        refreshDrawableState();
    }
    
    @Override
    public boolean isChecked() {
        return mIsChecked;
    }
    
    @Override
    public void toggle() {
        setChecked(!isChecked());
        refreshDrawableState();
    }
    

Then I load it in my XML and added .setChoiceMode(GridView.CHOICE_MODE_MULTIPLE) to my GridView in the Activity. Nothing Happened.

  • Added MultiChoiceModeListener:

    class MultiChoiceListener implements GridView.MultiChoiceModeListener{ @Override public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) { int selectCount = mGallery.getCheckedItemCount(); switch (selectCount) { case 1: mode.setSubtitle("One item selected"); break; default: mode.setSubtitle("" + selectCount + " items selected"); break; } }

    @Override
    public boolean onCreateActionMode(ActionMode mode, Menu menu) {
        mode.setTitle("Select Items");
        mode.setSubtitle("One item selected");
        return true;
    }
    
    @Override
    public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
        return false;
    }
    
    @Override
    public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
        return false;
    }
    
    @Override
    public void onDestroyActionMode(ActionMode mode) {
    
    }
    

    }

Then added it to my gridView .setMultiChoiceModeListener(newMultiChoiceListener()); but still no results.

Can someone propose a way to achieve this item selecting behavior in GridView? I'd like to use the native Android API, no 3rd party libraries.

like image 468
BabbevDan Avatar asked Mar 10 '16 21:03

BabbevDan


1 Answers

I think Checkable and the rest that I see in your code is a bit of an overkill...When I want to implement something like that I just add another field in the class of the object that is shown in the GridView/ListView which stores the checked state of the object. example:

class Image {
     Bitmap bm;
     boolean isChecked=false;

     public Image(Bitmap bm){
        this.bm=bm;
     }

     public boolean isChecked(){
         return isChecked;
     }
     public void toggleChecked(){
         isChecked = !isChecked;
     }
}

and feed an ArrayList to the adapter. an in the getView method of the adapter I do something like this;

@Override
public View getView(int position, View convertView, ViewGroup parent) { 

     if(images.get(position).isChecked()){
        //show the overlay view that suggests the item is selected
     }
     else{
        //hide the overlay view 
     } 
}

finally in the onItemClickListener of the ListView

listView.setOnItemClickListener(new OnItemClickListener() {

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        images.get(position).toggleChecked();
        listView.getAdapter().notifyDataSetChanged();
    }
});
like image 80
Anonymous Avatar answered Nov 10 '22 01:11

Anonymous