Как запретить режим близкого действия, когда ни один элемент не выбран
Я использовал режим действия, чтобы показать режим выбора, но когда счетчик выбранных элементов равен 0, он автоматически выйдет из режима действия. Я хочу оставаться в режиме выбора, если пользователь не нажмет клавишу возврата.
ModeCallback mModeCallBack = new ModeCallback();
mGridview.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
mGridview.setMultiChoiceModeListener(mModeCallBack);
private class ModeCallback implements GridView.MultiChoiceModeListener {
...
}
3 ответа
Я исправил эту проблему.
@Override
public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {
...
mCheckedCount = mGridview.getCheckedItemCount();
// if we unselect the last item, cout is 0, we set it to -1, so it will not exit action mode(because if cout==0, mode.finish()).
// if we select 1 item, we should plus this "1" back. unless the count will be woring.
if (mCheckedCount == 0) {
Utils.modifyFileValue(mGridview, "mCheckedItemCount", mCheckedCount + (checked ? 1 : -1));
}
String title = "";
// we must get the count again, because we changed it.
mCheckedCount = mGridview.getCheckedItemCount();
title = mContext.getResources().getString(R.string.select_albums, mCheckedCount > 0 ? mCheckedCount : 0);
mSelectedConvCount.setText(title);
....
if (checked) {
mSelectedIds.add(selectedId);
} else {
mSelectedIds.remove(selectedId);
}
}
public static void modifyFileValue(Object object, String filedName, int filedValue) {
//for my case, I want to get mCheckedItemCount in AbsListView.class, but i passed Gridview, so it should getSuperclass(). because GridView don't have mCheckedItemCount.
Class classType = object.getClass().getSuperclass();
Field fild = null;
try {
fild = classType.getDeclaredField(filedName);
fild.setAccessible(true);
fild.set(object, filedValue);
} catch (NoSuchFieldException ex) {
ex.printStackTrace();
} catch (Exception ex) {
ex.printStackTrace();
}
}
Попробуйте это, может ли это решить вашу проблему
public void onItemCheckedStateChanged(ActionMode mode, int position,
long id, boolean checked) {
if (position == theInitialPosition)
return; // so we start the action mode but there aren't any items checked
}
int selectCount = gridView.getCheckedItemCount();
if (selectCount > 0) {
notify = true;
dataArray.add(position);
// if you select another item you'll have two selected items(because of the dummy item) so you need to take care of it
switch (selectCount) {
case 1:
mode.setSubtitle("One item added ");
break;
default:
mode.setSubtitle("" + selectCount
+ " items added to favorites");
break;
}
}
}
Или же...
public boolean onItemLongClick(AdapterView<?> parent, View view,
int position, long id) {
if (mActionMode != null) {
return false;
}
selectedItem = position;
// start the action mode using the ActionMode.Callback defined above
mActionMode = MyActivity.this
.startActionMode(mActionModeCallback);
view.setSelected(true);
return true;
}
});
}
private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() {
// called when the action mode is created; startActionMode() was called
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
// Inflate a menu resource providing context menu items
MenuInflater inflater = mode.getMenuInflater();
// assumes that you have "contexual.xml" menu resources
inflater.inflate(R.menu.xxxxxxx, menu);
return true;
}
Проблема связана с этим фрагментом негибкого кода в AbsListView.java, который безоговорочно отклоняет ActionMode, когда последний элемент отменяется:
class MultiChoiceModeWrapper implements MultiChoiceModeListener {
...
@Override
public void onItemCheckedStateChanged(ActionMode mode,
int position, long id, boolean checked) {
mWrapped.onItemCheckedStateChanged(mode, position, id, checked);
// If there are no items selected we no longer need the selection mode.
if (getCheckedItemCount() == 0) {
mode.finish();
}
}
}
Поскольку AbsListView не предлагает никаких хуков, чтобы законно помешать этому жесткому поведению, вы вынуждены прибегнуть к уродливому хаку, возвращающему ложное значение из getCheckedItemCount из вашего собственного подкласса AbsListView, когда оно вызывается вышеприведенным кодом:
public class ActionModeHackGridView extends GridView {
...
@Override
public int getCheckedItemCount() {
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
String name = ActionModeHackGridView.class.getName();
for (int i = 0; i < stackTrace.length; i++) {
// First find this method in the stack
if (stackTrace[i].getClassName().equals(name)
&& stackTrace[i].getMethodName().equals("getCheckedItemCount")) {
// ...then examine the caller of this method
if (stackTrace[i + 1].getClassName().equals(
"android.widget.AbsListView$MultiChoiceModeWrapper")
&& stackTrace[i + 1].getMethodName().equals("onItemCheckedStateChanged")) {
// Return a non-zero value so AbsListView doesn't dismiss the ActionMode
return 1;
}
break;
}
}
return super.getCheckedItemCount();
}
}
Вы можете использовать тот же хак в любом подклассе AbsListView (например, ListView).