我实现了GridView并激活了
mGridView.setChoiceMode(GridView.CHOICE_MODE_MULTIPLE_MODAL);
模式。现在,当我对一个项目执行长按时,我可以从网格中选择多个项目。我希望通过正常的短按实现此行为。这可能吗?
答案 0 :(得分:10)
首先,我建议考虑这个用户场景是否是您一直在寻找的。默认情况下,在Android UX中选择您长按的内容,这是用户习惯的模式。所以,也许你应该重新考虑整个流程。
说,你真的需要GridView.CHOICE_MODE_MULTIPLE_MODAL
吗?
您可以在适配器级别处理它,只需存储选定的位置并在onClick
处理程序中更新此列表:
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();
}
}
});
瞧!现在,对于正常点击,您具有相同的行为,就像长按一样。单击即可实现多项选择模式。不确定这是遵循所有指南的好方法,但它可以按照您的意愿工作。