2

我的堆栈真的溢出了,我的意思是目前我的大脑想不出解决以下问题的方法(尽管我经历了很多天的反复试验)。我想做的只是一个用于删除目的的屏幕,例如(http://asset0.cbsistatic.com/cnwk.1d/i/tim/2010/11/18/Foreman_11654166_1073_com.probosoft.masscontactsdelete0_257x386.png

我有一个这样的列表视图项目的布局(log_view.xml):

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:padding="5dp" >

    <TextView
        android:id="@+id/date_view"
        android:gravity="top|left"
        android:textStyle="bold"

        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentLeft="true" />

    <TextView
        android:id="@+id/value_view"
        android:gravity="top|left"
        android:layout_width="match_parent"
        android:layout_height="match_parent"

        android:layout_below="@+id/date_view"
        android:layout_alignParentLeft="true" />

     <CheckBox 
        android:id="@+id/del_box"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:layout_marginRight="5dp"
        android:visibility="gone"

        android:focusable="false"
    android:focusableInTouchMode="false" />

</RelativeLayout>

这是我的自定义适配器:

class LogViewAdapter extends ArrayAdapter<Log>  {   
    public ArrayList<Boolean> checkList;
    private int layoutResourceId;
    private List<Log> logList;

    Context context;

    public LogViewAdapter(Context context, int layoutResourceId, List<Log> data) {
        super(context, R.layout.log_view, data);

        this.layoutResourceId = layoutResourceId;
        this.logList = data;
        this.context = context;

        checkList = new ArrayList<Boolean>();
        for (int i = 0; i < logList.size(); i ++)   {
            checkList.add(false);
        }
    }

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        LogHolder logholder = null;

        // Unidentified view            
        if(convertView == null) {
            LayoutInflater inflater = ((Activity)context).getLayoutInflater();
            convertView = inflater.inflate(layoutResourceId, parent, false);

            // Create a new holder
            logholder = new LogHolder();

            logholder.del_box = (CheckBox)convertView.findViewById(R.id.del_box);
            logholder.del_box.setChecked(false);

            final int iFinal = position;
            logholder.del_box.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    checkList.set(iFinal, buttonView.isChecked());
                }
            });

            logholder.date_view = (TextView)convertView.findViewById(R.id.date_view);
            logholder.value_view = (TextView)convertView.findViewById(R.id.value_view);

            convertView.setTag(logholder);
        }

        // Identified view
        else    {
            logholder = (LogHolder) convertView.getTag();
        }

        if (null != logList)    {
            if (null == checkList.get(position))    {
                android.util.Log.e("getView", "Checklist null at " + position);
            }

            //logholder.del_box.setChecked((boolean)checkList.get(position));
            logholder.date_view.setText(logList.get(position).date);
            logholder.value_view.setText(logList.get(position).value);
        }

        android.util.Log.e("getView", " at " + position + ", value = " + logholder.value_view.getText().toString());
        return convertView;
    }

    static class LogHolder  {
        TextView date_view;
        TextView value_view;
        CheckBox del_box;
    }
}

这是我的活动:

public class LoggingActivity extends Activity   {

    //private EditText edt_name;
    //private EditText edt_value;
    private List<Log> logList;
    private LogViewAdapter lw_adapter;
    private ListView listView;


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.log_list);
        //setContentView(android.R.layout.simple_list_item_multiple_choice);

        logList = loadLog();
        listView = (ListView)findViewById(R.id.log_list);

        lw_adapter = new LogViewAdapter(this, R.layout.log_view, logList);
        //lw_adapter = new LogViewAdapter(this, android.R.layout.simple_list_item_multiple_choice, logList);

        listView.setAdapter(lw_adapter);
    }

    /** implements for the MENU soft-key. Android 2.3.x */
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.layout.log_menu, menu);

        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // IMPORTANT: listView.getChildAt(index) will only return the
        // VISIBLE views in our current screen
        if (null == listView)   {
            android.util.Log.e("onOptionsItemSelected", "list view null");
            return true;
        }

        for (int i = 0; i < listView.getChildCount(); i++) {
            if (null == listView.getChildAt(i)) continue;

            CheckBox cb = (CheckBox) listView.getChildAt(i).findViewById(R.id.del_box);
            if (null == cb) {
                android.util.Log.e("CB", "CheckBox at i = " + i + " null");
                return true;
            }

            final int iFinal = i + listView.getFirstVisiblePosition();
            cb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    listView.setItemChecked(iFinal, buttonView.isChecked());
                    lw_adapter.checkList.set(iFinal, buttonView.isChecked());
                }
            });

            SparseBooleanArray selectedItems = listView.getCheckedItemPositions();

            for (int j = 0; j < selectedItems.size(); j++) {
                if (selectedItems.get(j)) {
                    android.util.Log.e("CHECKED", "Row "+ j + ", value = " + logList.get(j).value);
                }

                else    {
                    android.util.Log.e("CHECKED", "Row "+ j + " not checked");
                }
            }

            cb.setVisibility(View.VISIBLE);
            cb.setEnabled(true);
        }

        File folder = new File(Environment.getExternalStorageDirectory(), "50802566/logs");

        // Handle item selection
        switch (item.getItemId()) {
            case R.id.log_sort:
                Collections.sort(logList, Log.COMPARE_BY_VALUE);
                lw_adapter.notifyDataSetChanged();

                return true;
            case R.id.log_del:
                for (int i = 0; i < logList.size(); i++) {
                    if (null == lw_adapter.checkList.get(i))    {
                        android.util.Log.e("DEL", "checklist["+ i + "] = null");
                        continue;
                    }

                    if (true == lw_adapter.checkList.get(i)) {
                        // Delete correlative xml file
                        Date date = null;
                        try {
                            date = new SimpleDateFormat("dd/MM/yyyy - HH:mm:ss").parse(logList.get(i).date);
                        } catch (ParseException e) {
                            e.printStackTrace();
                        }

                        String filename = new SimpleDateFormat("dd_MM_yyyy - HH_mm_ss").format(date) + ".xml";
                        File toDelete = new File(folder, filename);
                        if (!toDelete.delete()) {
                            android.util.Log.e("DEL", "File " + filename + ": not deleted or not existed");
                        }

                        // Update the UI
                        //lw_adapter.remove(logList.get(i));
                        //lw_adapter.checkList.remove(i);

                        logList.set(i, null);
                        lw_adapter.checkList.set(i, null);
                        android.util.Log.e("DEL", "Deleted " + i + ", size now = " + logList.size());
                    }  
                }

                for (int i = 0; i < logList.size(); i ++)   {
                    if (null == logList.get(i)) {
                        logList.remove(i);
                        lw_adapter.checkList.remove(i);
                    }
                }

                lw_adapter.notifyDataSetChanged();

                // Refresh the checklist
                for (int i = 0; i < lw_adapter.checkList.size(); i ++)  {
                    lw_adapter.checkList.set(i, false);
                }

                for (int i = 0; i < listView.getChildCount(); i++) {
                    if (null == listView.getChildAt(i)) continue;
                    CheckBox cb = (CheckBox) listView.getChildAt(i).findViewById(R.id.del_box);
                    cb.setChecked(false);
                }

                return true;

            default:
                return super.onOptionsItemSelected(item);
        }
    }

    private ArrayList<Log> loadLog()    {
        /** Access folder "my_logs" in external memory */
        File baseDir = new File(Environment.getExternalStorageDirectory().getAbsolutePath() +
                                File.separator +
                                "50802566/logs");
        if (!baseDir.exists())  {   baseDir.mkdirs();   }
        File[] list_file = baseDir.listFiles();

        /** For internal memory */
        //File[] list_file = this.getFilesDir().listFiles();

        for (int i = 0; i < list_file.length; i ++) {
            //android.util.Log.e("PRINTLN", list_file[i].getPath());
        }

        int l = list_file.length;

        ArrayList<Log> list = new ArrayList<Log>();

        while (l-- > 0) {
            File file = list_file[l];

            FileInputStream fin = null;
            LogReader logr = new LogReader();

            try {
                fin = new FileInputStream(file);
                list.add(list_file.length - l - 1, logr.read(fin));
                fin.close();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (XmlPullParserException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return list;
    }
}

问题是:

  1. 我无法跟踪每个 CheckBox 的布尔值。例如,如果我对 logList(我的数据库)进行排序,然后将“notifyDataSetChanged”添加到 listView,但我的 checkList(包含 CheckBox 的布尔值)仍然相同,并且会发生奇怪的事情。如何将一个列表的所有排序操作完全应用于另一个列表?(IMO,“同步排序”或类似的东西......)

  2. 如您所见,我尝试通过从其行中获取 del_box(我的 CheckBox id)来解决#1,然后将其“OnCheckedChangeListener”设置为进行分配(一旦检查,它将更新布尔列表中的相对值“清单”)。但是奇怪的事情又发生了:

    • 当检查一行并向下滚动时,我看到另一个已检查。
    • 向后滚动时,前一个选中的...未选中(当然是自动的)。

也许适配器正在重新使用错误的视图/值,但我不知道如何让它做正确的事情......>“<

您的帮助和指导很棒。你的示例代码对我来说非常完美......(我现在真的很累>“<)

更新:

我找到了一种方法来(以某种方式)解决它,但也许它违反了 Android 的 API 行为......如果你有更安全的解决方案,请告诉我^^

正如我在第二条评论中提到的,这里是代码:

@Override
    public void onCheckedChanged(CompoundButton cb, boolean isChecked) {
        int graphicalPos = -1;

        // This is top view on the screen for sure
        if (((View)cb.getParent()).getTop() < 0)    {
            graphicalPos = 0;
        }

        else if (((View)cb.getParent()).getTop() == 0)  {
            graphicalPos = (int) (((View)cb.getParent()).getTop() / ((View)cb.getParent()).getHeight());
        }

        else if (((View)cb.getParent()).getTop() > 0)   {
            graphicalPos = (int) (((View)cb.getParent()).getTop() / ((View)cb.getParent()).getHeight());
            if (listView.getChildAt(0).getTop() < 0)    {
                graphicalPos = graphicalPos + 1;
            }

            else    {
                android.util.Log.e("NOT PLUS", "First Top = " + listView.getChildAt(0).getTop());
            }
        }

        int dataPos = graphicalPos + listView.getFirstVisiblePosition();

        lw_adapter.checkList.set(dataPos, isChecked);
        android.util.Log.e("onCheckedChanged", "Checked row " + dataPos + ", graphicalPos = " + graphicalPos + ", top = " + ((View)cb.getParent()).getTop() + ", firstVisible = " + listView.getFirstVisiblePosition());
    }
4

0 回答 0