在按钮单击时通过CAB动态选择和删除列表视图项目,而不是长按

时间:2014-07-16 00:21:06

标签: android listview

我有一个带有列表视图和自定义适配器的应用程序,我将自定义对象添加到列表视图中。我知道如何通过长按列表中的一个列表项来删除对象,但我有一个垃圾桶操作栏按钮,我想要它,这样当你点击该按钮时,它会显示相同的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,但我无法选择列表中的任何项目并继续删除它们。非常感谢任何帮助。

1 个答案:

答案 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>