我有一个带有列表视图和自定义适配器的应用程序,我将自定义对象添加到列表视图中。我知道如何通过长按列表中的一个列表项来删除对象,但我有一个垃圾桶操作栏按钮,我想要它,这样当你点击该按钮时,它会显示相同的CAB,就好像你长按列表项,我希望用户能够选择多个列表项,然后单击CAB上的删除按钮。
我尝试过:
package viva.inspection.com.inspectionpicker;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.SparseBooleanArray;
import android.view.ActionMode;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AbsListView;
import android.widget.Adapter;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.GregorianCalendar;
import java.util.HashSet;
import java.util.List;
import viva.inspection.com.inspectionpicker.R;
public class ListActivity extends Activity {
private static ArrayList<InspectionItem> inspections;
private static final String s = "inspection list";
public static final String PREFS_NAME = "MyPrefsFile";
ListView inspectionList;
private final int GET_VALUE=111;
private final int GET_VAL = 11;
private MyAdapter listviewadapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list);
SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
inspectionList = (ListView) findViewById(R.id.listView);
inspectionList.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
inspections = new ArrayList<InspectionItem>();
inspections.add(new InspectionItem(new GregorianCalendar(7,15,14), "hi", "hi", "hi", "hi", "hi", "hi", "hi", "hi", "hi", "hi", new ArrayList<String>()));
if(getIntent().getStringExtra("NEW_VALUE") != null) {
//addItems(getIntent().getStringExtra("NEW_VALUE"));
SharedPreferences.Editor edit = settings.edit();
edit.putString("myKey", TextUtils.join(",", inspections));
edit.commit();
}
if(!(settings.getString("myKey", "hi").equals("hi"))) {
//We have saved values. Grab them.
} else {
//We have no saved values
inspections = new ArrayList<InspectionItem>();
inspections.add(new InspectionItem(new GregorianCalendar(7,15,14), "hi", "hi", "hi", "hi", "hi", "hi", "hi", "hi", "hi", "hi", new ArrayList<String>()));
}
listviewadapter = new MyAdapter(this, R.layout.row_layout,
inspections);
inspectionList.setAdapter(listviewadapter);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.list, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
switch(id) {
case R.id.action_settings:
return true;
case R.id.action_new:
Intent intent = new Intent(this, InitialChoose.class);
startActivity(intent);
return true;
case R.id.action_delete:
inspectionList.setOnItemSelectedListener(new ActionBarCallBack());
startActionMode(new ActionBarCallBack());
//mActionMode.finish();
return true;
}
return super.onOptionsItemSelected(item);
}
class ActionBarCallBack implements ListView.OnItemSelectedListener, ActionMode.Callback {
ActionMode activeMode;
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case R.id.delete:
// Calls getSelectedIds method from ListViewAdapter Class
SparseBooleanArray selected = listviewadapter
.getSelectedIds();
// Captures all selected ids with a loop
for (int i = (selected.size() - 1); i >= 0; i--) {
if (selected.valueAt(i)) {
InspectionItem selecteditem = listviewadapter
.getItem(selected.keyAt(i));
// Remove selected items following the ids
listviewadapter.remove(selecteditem);
}
}
// Close CAB
mode.finish();
return true;
default:
return false;
}
}
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
mode.getMenuInflater().inflate(R.menu.cab_menu, menu);
return true;
}
@Override
public void onDestroyActionMode(ActionMode mode) {
// TODO Auto-generated method stub
listviewadapter.removeSelection();
}
@Override
public boolean onPrepareActionMode(final ActionMode mode, Menu menu) {
// TODO Auto-generated method stub
return false;
}
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
listviewadapter.toggleSelection(i);
final int checkedCount = inspectionList.getCheckedItemCount();
// Set the CAB title according to total checked items
activeMode.setTitle(checkedCount + " Selected");
}
@Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
}
/*
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(resultCode==RESULT_OK){
if(requestCode == GET_VALUE){
if(data.getStringExtra("NEW_VALUE")!=null && data.getStringExtra("NEW_VALUE").length()>0){
addItems(data.getStringExtra("NEW_VALUE"));
SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
SharedPreferences.Editor edit = settings.edit();
edit.putString("myKey", TextUtils.join(",", inspections));
edit.commit();
}
}
}
} */
}
基本上,使用此代码,如果我单击垃圾桶操作栏按钮,则会显示CAB,但我无法选择列表中的任何项目并继续删除它们。非常感谢任何帮助。
答案 0 :(得分:2)
这是一个棘手的问题。我在列表中使用CheckedTextView
进行了多次选择,但是当列表滚动时,适配器重新使用旧视图,有时会检查错误的项目。为了克服这个问题,我使用了所有当前检查项目的数组,因此适配器可以知道应该检查哪些项目。
在返回原始列表之前,您需要调用notifyDataSetChanged(),它会通知重新绘制可见视图,因此取消选中/删除选择(取决于您在CAB上选择的操作)。
package com.example.simon.cabdelete;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.util.SparseBooleanArray;
import android.view.ActionMode;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.CheckedTextView;
import android.widget.ListView;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Simon on 2014 Jul 18.
*/
public class MainActivity extends Activity {
private final static String TAG = "MainActivity";
MyAdapter mAdapter;
ListView mListView;
List<String> mListArray;
SparseBooleanArray mCheckedItems;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mListView = (ListView) findViewById(R.id.listView);
// Default list item click listener
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener(){
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// Do something on normal click
}
});
mCheckedItems = new SparseBooleanArray();
int size = 20;
mListArray = new ArrayList<String>(size);
for (int i=0; i<size; i++)
mListArray.add("Item "+i);
mAdapter = new MyAdapter(this, R.layout.list_item, mListArray);
mListView.setAdapter(mAdapter);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
switch (id) {
case R.id.action_settings:
break;
case R.id.action_delete:
startActionMode(new ActionBarCallBack());
break;
}
return super.onOptionsItemSelected(item);
}
public class MyAdapter extends ArrayAdapter<String> {
List<String> items;
int itemResource;
LayoutInflater inflater;
public MyAdapter(Context ctx, int resource, List<String> objects) {
super(ctx, resource, objects);
this.items = objects;
this.itemResource = resource;
this.inflater = ((MainActivity)ctx).getLayoutInflater();
}
@Override
public View getView(int pos, View convertView, ViewGroup parent) {
// (Re)Use convertView
if (convertView == null) {
convertView = inflater.inflate(itemResource, parent, false);
}
CheckedTextView checkView = (CheckedTextView) convertView;
checkView.setText(items.get(pos));
if (mCheckedItems.get(pos))
checkView.setChecked(true);
else
checkView.setChecked(false);
return convertView;
}
}
public class ActionBarCallBack implements ListView.OnItemClickListener,
ActionMode.Callback {
ActionMode actionMode;
AdapterView.OnItemClickListener previousListener;
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
Log.v(TAG, "Action mode started");
actionMode = mode;
mode.getMenuInflater().inflate(R.menu.cab_menu, menu);
previousListener = mListView.getOnItemClickListener();
mListView.setOnItemClickListener(this);
mCheckedItems = new SparseBooleanArray(mListView.getCount());
return true;
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case R.id.delete:
Log.v(TAG, "Deleting "+mCheckedItems.size()+" items");
for (int i= mCheckedItems.size()-1; i>=0; i--) {
int key = mCheckedItems.keyAt(i);
Log.v(TAG, "Removing array item @ " + key);
mListArray.remove(key);
}
mode.finish();
return true;
default:
return false;
}
}
@Override
public void onDestroyActionMode(ActionMode mode) {
Log.v(TAG, "Exiting action mode.");
mListView.setOnItemClickListener(previousListener);
mCheckedItems.clear();
mAdapter.notifyDataSetChanged();
}
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
CheckedTextView checkView = (CheckedTextView) view;
boolean state = checkView.isChecked();
checkView.setChecked(!state);
if (!mCheckedItems.get(position))
mCheckedItems.put(position, true);
else
mCheckedItems.delete(position);
actionMode.setTitle(mCheckedItems.size() + " Items selected");
Log.v(TAG, "Action item @ " + position +
" clicked. It's state now is " + state);
}
}
}
这是我的xml文件创建整个外观:
<强> RES /布局/ activity_main.xml中:强>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context=".MainActivity">
<ListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:drawSelectorOnTop="true"/>
<!-- Note that drawSelectorOnTop is important as it lets
the CheckedTextViews to be clicked in a normal way too-->
</RelativeLayout>
<强> RES /布局/ list_item.xml 强>:
<CheckedTextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:background="@drawable/list_selector"/>
<强> RES /抽拉/ list_selector.xml 强>:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/item_default" android:state_checked="false"/>
<item android:drawable="@color/item_checked" android:state_checked="true"/>
</selector>
<强> RES /值/ colors.xml 强>:
<resources>
<color name="item_default">#33B5E5</color>
<color name="item_checked">#0095CC</color>
</resources>