You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
MiNote/ui/NotesListAdapter.java

255 lines
8.8 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
* 版权所有 (c) 2010-2011The 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<Integer, Boolean> 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<Integer, Boolean>(); // 初始化选中状态集合
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<Long> getSelectedItemIds() {
HashSet<Long> itemSet = new HashSet<Long>();
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<AppWidgetAttribute> getSelectedWidget() {
HashSet<AppWidgetAttribute> itemSet = new HashSet<AppWidgetAttribute>();
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<Boolean> values = mSelectedIndex.values();
if (values == null) return 0;
int count = 0;
Iterator<Boolean> 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;
}
}
}
}