/* * 版权所有 (c) 2010-2011,The MiCode 开源社区 (www.micode.net) * * 本软件根据 Apache 许可证 2.0 版("许可证")发布; * 除非符合许可证,否则不得使用此文件。 * 您可以在以下网址获取许可证副本: * * http://www.apache.org/licenses/LICENSE-2.0 * * 除非法律要求或书面同意,软件 * 根据许可证分发的内容按"原样"提供, * 不附带任何明示或暗示的保证或条件。 * 请参阅许可证,了解有关权限和限制的具体语言。 */ package net.micode.notes.ui; import android.content.Context; import android.database.Cursor; import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.widget.CursorAdapter; import net.micode.notes.data.Notes; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; /** * 笔记列表适配器(继承自CursorAdapter) * 功能:管理笔记列表的数据展示,支持多选模式、数据过滤和Widget相关操作 * 职责: * 1. 将Cursor数据转换为NotesListItem视图 * 2. 处理多选模式下的选中状态管理 * 3. 统计可操作的笔记数量(非文件夹项) * 4. 提供批量操作相关接口(全选、获取选中项等) */ public class NotesListAdapter extends CursorAdapter { private static final String TAG = "NotesListAdapter"; private Context mContext; // 上下文 private HashMap mSelectedIndex; // 选中项位置集合(键:列表位置,值:是否选中) private int mNotesCount; // 可操作的笔记数量(非文件夹项) private boolean mChoiceMode; // 是否为多选模式 // 内部类:用于封装Widget相关属性(ID和类型) public static class AppWidgetAttribute { public int widgetId; // Widget ID public int widgetType; // Widget类型 } /** * 构造方法 * @param context 上下文 */ public NotesListAdapter(Context context) { super(context, null); // 调用父类构造方法(传入空Cursor,后续通过changeCursor设置) mSelectedIndex = new HashMap(); // 初始化选中状态集合 mContext = context; mNotesCount = 0; // 初始化可操作笔记数量 } /** * 创建新视图:返回NotesListItem实例 * @param context 上下文 * @param cursor 数据Cursor * @param parent 父视图组 * @return 列表项视图 */ @Override public View newView(Context context, Cursor cursor, ViewGroup parent) { return new NotesListItem(context); // 使用自定义列表项视图 } /** * 绑定视图:将Cursor数据填充到NotesListItem中 * @param view 列表项视图 * @param context 上下文 * @param cursor 数据Cursor */ @Override public void bindView(View view, Context context, Cursor cursor) { if (view instanceof NotesListItem) { // 从Cursor创建数据对象 NoteItemData itemData = new NoteItemData(context, cursor); // 绑定数据到视图,传入多选模式状态和选中状态 ((NotesListItem) view).bind(context, itemData, mChoiceMode, isSelectedItem(cursor.getPosition())); // 根据位置判断是否选中 } } /** * 设置指定位置的选中状态 * @param position 列表位置 * @param checked 是否选中 */ public void setCheckedItem(final int position, final boolean checked) { mSelectedIndex.put(position, checked); // 存储选中状态 notifyDataSetChanged(); // 通知数据集变化,更新视图 } /** * 判断是否处于多选模式 * @return true=多选模式,false=普通模式 */ public boolean isInChoiceMode() { return mChoiceMode; } /** * 设置多选模式状态(同时清空选中状态) * @param mode 多选模式开关 */ public void setChoiceMode(boolean mode) { mSelectedIndex.clear(); // 清空所有选中状态 mChoiceMode = mode; } /** * 全选/全不选操作 * @param checked 是否全选 */ public void selectAll(boolean checked) { Cursor cursor = getCursor(); // 获取当前Cursor if (cursor == null) return; for (int i = 0; i < getCount(); i++) { if (cursor.moveToPosition(i)) { // 移动到指定位置 // 仅处理笔记类型(非文件夹) if (NoteItemData.getNoteType(cursor) == Notes.TYPE_NOTE) { setCheckedItem(i, checked); // 设置选中状态 } } } } /** * 获取所有选中项的ID集合(仅笔记和通话记录项,排除根文件夹) * @return 选中项ID集合 */ public HashSet getSelectedItemIds() { HashSet itemSet = new HashSet(); for (Integer position : mSelectedIndex.keySet()) { if (mSelectedIndex.get(position)) { // 仅处理选中的位置 Long id = getItemId(position); // 获取项ID(来自Cursor的_id字段) if (id == Notes.ID_ROOT_FOLDER) { // 根文件夹ID为特殊值,忽略(防止误操作) Log.d(TAG, "Wrong item id, should not happen"); } else { itemSet.add(id); } } } return itemSet; } /** * 获取所有选中项的Widget属性集合(用于桌面小部件操作) * @return Widget属性集合 */ public HashSet getSelectedWidget() { HashSet itemSet = new HashSet(); for (Integer position : mSelectedIndex.keySet()) { if (mSelectedIndex.get(position)) { // 仅处理选中的位置 Cursor c = (Cursor) getItem(position); // 获取对应Cursor if (c != null) { AppWidgetAttribute widget = new AppWidgetAttribute(); NoteItemData item = new NoteItemData(mContext, c); widget.widgetId = item.getWidgetId(); // 获取Widget ID widget.widgetType = item.getWidgetType(); // 获取Widget类型 itemSet.add(widget); } else { Log.e(TAG, "Invalid cursor"); return null; // 无效Cursor时返回null } } } return itemSet; } /** * 获取选中项数量 * @return 选中项数量 */ public int getSelectedCount() { Collection values = mSelectedIndex.values(); if (values == null) return 0; int count = 0; Iterator iter = values.iterator(); while (iter.hasNext()) { if (iter.next()) count++; // 统计值为true的数量 } return count; } /** * 判断是否全选(选中数量等于可操作笔记数量) * @return true=全选,false=未全选 */ public boolean isAllSelected() { int checkedCount = getSelectedCount(); return (checkedCount != 0 && checkedCount == mNotesCount); // 非零且等于可操作数量 } /** * 判断指定位置是否选中 * @param position 列表位置 * @return true=选中,false=未选中 */ public boolean isSelectedItem(final int position) { // 默认返回false,若集合中无该位置则视为未选中 return mSelectedIndex.get(position) != null && mSelectedIndex.get(position); } /** * 内容变化时的回调(当数据更新时触发) */ @Override protected void onContentChanged() { super.onContentChanged(); calcNotesCount(); // 重新计算可操作笔记数量 } /** * 更换Cursor时的回调(如数据刷新或查询条件变更) * @param cursor 新的Cursor */ @Override public void changeCursor(Cursor cursor) { super.changeCursor(cursor); calcNotesCount(); // 重新计算可操作笔记数量 } /** * 计算可操作笔记数量(非文件夹项) */ private void calcNotesCount() { mNotesCount = 0; for (int i = 0; i < getCount(); i++) { Cursor c = (Cursor) getItem(i); // 获取第i项的Cursor if (c != null) { // 判断是否为笔记类型(TYPE_NOTE) if (NoteItemData.getNoteType(c) == Notes.TYPE_NOTE) { mNotesCount++; // 累计数量 } } else { Log.e(TAG, "Invalid cursor"); return; } } } }