Android GridView Multiple Selection

試著忘記壹切 提交于 2019-12-18 04:55:17

问题


I have a GridView implemented and activated the

mGridView.setChoiceMode(GridView.CHOICE_MODE_MULTIPLE_MODAL);

mode. Now I have the possibility to select multiple items from my grid when I perform a long click on one item. I want to achieve this behavior on a normal, short click. Is this possible?


回答1:


First, I'd suggest to think if this user scenario is what you have been looking for. By default, in Android UX to select something you do long press and it's a pattern users used to. So, maybe you should rethink the whole flow.

Saying that, do you actually need GridView.CHOICE_MODE_MULTIPLE_MODAL?

You can handle it on the Adapter level, by just storing selected positions and update this list in onClick handler:

static final String[] numbers = new String[] {
        "A", "B", "C", "D", "E",....
        "U", "V", "W", "X", "Y", "Z"};

.....

gridView = (GridView) findViewById(R.id.gridView1);
final CustomAdapter adapter = new CustomAdapter(numbers);
gridView.setAdapter(adapter);
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    public void onItemClick(AdapterView<?> parent, View v,
                            int position, long id) {
        int selectedIndex = adapter.selectedPositions.indexOf(position);
        if (selectedIndex > -1) {
            adapter.selectedPositions.remove(selectedIndex);
            ((CustomView)v).display(false);
        } else {
            adapter.selectedPositions.add(position);
            ((CustomView)v).display(true);
        }
    }
});

Custom BaseAdapter to display Custom views:

public class CustomAdapter extends BaseAdapter {
    private String[] strings;
    List<Integer> selectedPositions = new ArrayList<>();

    CustomAdapter(String [] strings) {
        this.strings = strings;
    }

    @Override
    public int getCount() {
        return strings.length;
    }

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

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        CustomView customView = (convertView == null) ? 
                                    new CustomView(MainActivity.this) : (CustomView) convertView;
        customView.display(strings[position], selectedPositions.contains(position));
        return customView;
    }
}

Custom View (in my case - cell with TextView). Xml:

<merge xmlns:android="http://schemas.android.com/apk/res/android">
    <TextView
        android:id="@+id/textView"
        android:textColor="#FFF"
        android:gravity="center"
        android:layout_width="match_parent"
        android:layout_height="60dp" />
</merge>

Code:

class CustomView extends FrameLayout {

    TextView textView;

    public CustomView(Context context) {
        super(context);
        LayoutInflater.from(context).inflate(R.layout.custom_view, this);
        textView = (TextView)getRootView().findViewById(R.id.textView);
    }

    public void display(String text, boolean isSelected) {
        textView.setText(text);
        display(isSelected);
    }

    public void display(boolean isSelected) {
        textView.setBackgroundColor(isSelected? Color.RED : Color.LTGRAY);
    }
}



回答2:


In case you don't want to use the answer below, and still want to achieve multiple mode selection by normal click, you need to simulate long click as mentioned in comments. If you check AbsListView sources, you will see that there is a method called performLongPress fired when you're trying to long click. So we will do that by using java reflection:

final GridView gridView = (GridView) findViewById(R.id.grid_view);
gridView.setAdapter(adapter);
gridView.setChoiceMode(GridView.CHOICE_MODE_MULTIPLE_MODAL);
gridView.setMultiChoiceModeListener(...); 
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            try {
                // trying to invoke "performLongPress" method, to reproduce the behavior
                Class[] args = new Class[3];
                args[0] = View.class;
                args[1] = int.class;
                args[2] = long.class;
                Method method = AbsListView.class.getDeclaredMethod("performLongPress", args);
                method.setAccessible(true);
                method.invoke(gridView, view, position, adapter.getItemId(position));

                //needed lines, if you check "AbsListView" sources, they're doing the same 
                //in "CheckForLongPress" Runnable class
                Field touchModeField = AbsListView.class.getDeclaredField("mTouchMode");
                touchModeField.setAccessible(true);
                touchModeField.setInt(gridView, -1);

                gridView.setPressed(false);
                view.setPressed(false);
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            }
        }
    });

Voila! Now you have the same behavior for normal click, as for long click. And multiple choice mode will work by single click. Not sure that it's a good way that follows all guidelines, but it will work as you want.



来源:https://stackoverflow.com/questions/34492280/android-gridview-multiple-selection

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!