Android GridView多选

时间:2015-12-28 11:00:41

标签: android gridview android-listview android-gridview

我实现了GridView并激活了

mGridView.setChoiceMode(GridView.CHOICE_MODE_MULTIPLE_MODAL);

模式。现在,当我对一个项目执行长按时,我可以从网格中选择多个项目。我希望通过正常的短按实现此行为。这可能吗?

2 个答案:

答案 0 :(得分:10)

首先,我建议考虑这个用户场景是否是您一直在寻找的。默认情况下,在Android UX中选择您长按的内容,这是用户习惯的模式。所以,也许你应该重新考虑整个流程。

说,你真的需要GridView.CHOICE_MODE_MULTIPLE_MODAL吗?

您可以在适配器级别处理它,只需存储选定的位置并在onClick处理程序中更新此列表:

enter image description here

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

自定义BaseAdapter以显示自定义视图:

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

自定义视图(在我的情况下 - 使用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>

代码:

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

答案 1 :(得分:0)

如果您不想使用下面的答案,并且仍希望通过正常点击实现多种模式选择,则需要模拟注释中提到的长按。如果您检查AbsListView来源,当您尝试长按时,会看到有一个名为performLongPress的方法已被触发。所以我们将通过使用java反射来做到这一点:

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

瞧!现在,对于正常点击,您具有相同的行为,就像长按一样。单击即可实现多项选择模式。不确定这是遵循所有指南的好方法,但它可以按照您的意愿工作。