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.
note/NotesListAdapter.java

382 lines
15 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.

/*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
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;
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;
public static class AppWidgetAttribute {
public int widgetId;
public int widgetType;
};
public NotesListAdapter(Context context) {
super(context, null);
mSelectedIndex = new HashMap<Integer, Boolean>();
mContext = context;
mNotesCount = 0;
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return new NotesListItem(context);
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
if (view instanceof NotesListItem) {
NoteItemData itemData = new NoteItemData(context, cursor);
((NotesListItem) view).bind(context, itemData, mChoiceMode,
isSelectedItem(cursor.getPosition()));
}
}
public void setCheckedItem(final int position, final boolean checked) {
mSelectedIndex.put(position, checked);
notifyDataSetChanged();
}
public boolean isInChoiceMode() {
return mChoiceMode;
}
public void setChoiceMode(boolean mode) {
mSelectedIndex.clear();
mChoiceMode = mode;
}
public void selectAll(boolean checked) {
Cursor cursor = getCursor();
for (int i = 0; i < getCount(); i++) {
if (cursor.moveToPosition(i)) {
if (NoteItemData.getNoteType(cursor) == Notes.TYPE_NOTE) {
setCheckedItem(i, checked);
}
}
}
}
public HashSet<Long> getSelectedItemIds() {
HashSet<Long> itemSet = new HashSet<Long>();
for (Integer position : mSelectedIndex.keySet()) {
if (mSelectedIndex.get(position) == true) {
Long id = getItemId(position);
if (id == Notes.ID_ROOT_FOLDER) {
Log.d(TAG, "Wrong item id, should not happen");
} else {
itemSet.add(id);
}
}
}
return itemSet;
}
public HashSet<AppWidgetAttribute> getSelectedWidget() {
HashSet<AppWidgetAttribute> itemSet = new HashSet<AppWidgetAttribute>();
for (Integer position : mSelectedIndex.keySet()) {
if (mSelectedIndex.get(position) == true) {
Cursor c = (Cursor) getItem(position);
if (c != null) {
AppWidgetAttribute widget = new AppWidgetAttribute();
NoteItemData item = new NoteItemData(mContext, c);
widget.widgetId = item.getWidgetId();
widget.widgetType = item.getWidgetType();
itemSet.add(widget);
/**
* Don't close cursor here, only the adapter could close it
*/
} else {
Log.e(TAG, "Invalid cursor");
return null;
}
}
}
return itemSet;
}
public int getSelectedCount() {
Collection<Boolean> values = mSelectedIndex.values();
if (null == values) {
return 0;
}
Iterator<Boolean> iter = values.iterator();
int count = 0;
while (iter.hasNext()) {
if (true == iter.next()) {
count++;
}
}
return count;
}
public boolean isAllSelected() {
int checkedCount = getSelectedCount();
return (checkedCount != 0 && checkedCount == mNotesCount);
}
public boolean isSelectedItem(final int position) {
if (null == mSelectedIndex.get(position)) {
return false;
}
return mSelectedIndex.get(position);
}
@Override
protected void onContentChanged() {
super.onContentChanged();
calcNotesCount();
}
@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);
if (c != null) {
if (NoteItemData.getNoteType(c) == Notes.TYPE_NOTE) {
mNotesCount++;
}
} else {
Log.e(TAG, "Invalid cursor");
return;
}
}
}
}
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;
// NotesListAdapter类继承自CursorAdapter是一个用于适配便签列表数据到ListView等列表视图组件的适配器类
// 它负责将从数据库查询获取的Cursor数据转换为适合展示的视图项并处理了列表项的选择、计数以及与小部件相关属性获取等功能逻辑。
public class NotesListAdapter extends CursorAdapter {
// 用于日志记录的标签,方便在日志输出中识别该类相关的日志信息。
private static final String TAG = "NotesListAdapter";
// 用于存储上下文信息,方便后续在创建视图、获取资源等操作中使用。
private Context mContext;
// 使用HashMap来存储列表项的选中状态键为列表项的位置索引值为布尔类型表示是否被选中以此记录用户在多选模式下对各列表项的选择情况。
private HashMap<Integer, Boolean> mSelectedIndex;
// 用于记录便签的数量,通过遍历游标数据统计得出,便于后续判断全选等相关逻辑时使用。
private int mNotesCount;
// 用于标记当前列表是否处于多选模式,控制相关的界面交互和数据处理逻辑,例如是否显示多选菜单、是否响应多选相关操作等。
private boolean mChoiceMode;
// 内部静态类用于封装与便签关联的小部件的属性信息包含小部件的ID和类型两个成员变量方便在处理便签与小部件关联操作时传递和使用相关数据。
public static class AppWidgetAttribute {
public int widgetId;
public int widgetType;
};
// 构造函数接收上下文对象作为参数调用父类构造函数传入上下文和空游标初始化同时初始化选中状态的HashMap和记录便签数量的变量并保存传入的上下文信息。
public NotesListAdapter(Context context) {
super(context, null);
mSelectedIndex = new HashMap<Integer, Boolean>();
mContext = context;
mNotesCount = 0;
}
// 重写父类的方法,用于创建一个新的视图对象来展示列表项,在这里返回一个自定义的`NotesListItem`视图对象,该对象负责具体的便签数据展示布局和渲染。
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return new NotesListItem(context);
}
// 重写父类的方法,用于将数据绑定到已创建的视图对象上进行展示,在这里从游标中获取便签数据封装成`NoteItemData`对象,
// 然后调用`NotesListItem`的`bind`方法将数据、多选模式状态以及该项是否被选中的信息传递进去,完成数据与视图的绑定展示。
@Override
public void bindView(View view, Context context, Cursor cursor) {
if (view instanceof NotesListItem) {
NoteItemData itemData = new NoteItemData(context, cursor);
((NotesListItem) view).bind(context, itemData, mChoiceMode,
isSelectedItem(cursor.getPosition()));
}
}
// 用于设置指定位置的列表项的选中状态,将位置索引和对应的选中状态存入`mSelectedIndex` HashMap中并通知数据集已改变使得列表视图能够更新相应的显示状态。
public void setCheckedItem(final int position, final boolean checked) {
mSelectedIndex.put(position, checked);
notifyDataSetChanged();
}
// 用于判断当前列表是否处于多选模式,外部代码可以调用该方法获取相应的状态信息,以决定是否显示多选相关的界面元素或执行相应逻辑。
public boolean isInChoiceMode() {
return mChoiceMode;
}
// 用于设置列表的多选模式状态,当进入或退出多选模式时调用该方法,会先清空之前的选中状态记录,然后更新`mChoiceMode`变量,以切换相应的操作逻辑和界面显示。
public void setChoiceMode(boolean mode) {
mSelectedIndex.clear();
mChoiceMode = mode;
}
// 用于全选或取消全选所有符合条件(通常是便签类型为普通便签)的列表项,通过遍历游标中的所有记录,根据便签类型判断是否进行选中状态设置,实现批量选中或取消选中的功能。
public void selectAll(boolean checked) {
Cursor cursor = getCursor();
for (int i = 0; i < getCount(); i++) {
if (cursor.moveToPosition(i)) {
if (NoteItemData.getNoteType(cursor) == Notes.TYPE_NOTE) {
setCheckedItem(i, checked);
}
}
}
}
// 用于获取所有已选中列表项的ID集合遍历`mSelectedIndex`中所有被标记为选中的位置索引,通过`getItemId`方法获取对应项的ID
// 并添加到`HashSet`集合中返回同时对特殊的根文件夹ID情况进行日志记录因为可能不符合预期的选中逻辑
public HashSet<Long> getSelectedItemIds() {
HashSet<Long> itemSet = new HashSet<Long>();
for (Integer position : mSelectedIndex.keySet()) {
if (mSelectedIndex.get(position) == true) {
Long id = getItemId(position);
if (id == Notes.ID_ROOT_FOLDER) {
Log.d(TAG, "Wrong item id, should not happen");
} else {
itemSet.add(id);
}
}
}
return itemSet;
}
// 用于获取所有已选中列表项关联的小部件属性集合,遍历`mSelectedIndex`中所有被标记为选中的位置索引,通过`getItem`方法获取对应位置的游标数据,
// 进而创建`AppWidgetAttribute`对象并填充小部件的ID和类型信息添加到`HashSet`集合中返回,同时对游标无效的情况进行日志记录并返回`null`。
public HashSet<AppWidgetAttribute> getSelectedWidget() {
HashSet<AppWidgetAttribute> itemSet = new HashSet<AppWidgetAttribute>();
for (Integer position : mSelectedIndex.keySet()) {
if (mSelectedIndex.get(position) == true) {
Cursor c = (Cursor) getItem(position);
if (c!= null) {
AppWidgetAttribute widget = new AppWidgetAttribute();
NoteItemData item = new NoteItemData(mContext, c);
widget.widgetId = item.getWidgetId();
widget.widgetType = item.getWidgetType();
itemSet.add(widget);
/**
* Don't close cursor here, only the adapter could close it
*/
} else {
Log.e(TAG, "Invalid cursor");
return null;
}
}
}
return itemSet;
}
// 用于获取当前已选中列表项的数量,通过获取`mSelectedIndex`中所有值(即各位置的选中状态)的集合,然后遍历该集合统计值为`true`(表示选中)的个数并返回。
public int getSelectedCount() {
Collection<Boolean> values = mSelectedIndex.values();
if (null == values) {
return 0;
}
Iterator<Boolean> iter = values.iterator();
int count = 0;
while (iter.hasNext()) {
if (true == iter.next()) {
count++;
}
}
return count;
}
// 用于判断是否所有符合条件通常是便签类型相关限定的列表项都已被选中通过比较已选中的数量和总的便签数量来确定若已选中数量不为0且等于便签数量则返回`true`,表示全选状态。
public boolean isAllSelected() {
int checkedCount = getSelectedCount();
return (checkedCount!= 0 && checkedCount == mNotesCount);
}
// 用于判断指定位置的列表项是否被选中,先判断对应位置在`mSelectedIndex`中的值是否为`null`(未记录则视为未选中),
// 若不为`null`则返回该位置记录的选中状态(`true`表示选中,`false`表示未选中)。
public boolean isSelectedItem(final int position) {
if (null == mSelectedIndex.get(position)) {
return false;
}
return mSelectedIndex.get(position);
}
// 重写父类的方法,当数据集内容发生变化时会被调用,在这里调用`calcNotesCount`方法重新计算便签的数量,以保证相关统计数据的准确性。
@Override
protected void onContentChanged() {
super.onContentChanged();
calcNotesCount();
}
// 重写父类的方法,当游标数据发生改变(比如重新查询获取了新的数据)时会被调用,同样在这里调用`calcNotesCount`方法重新计算便签的数量,以适配新的数据情况。
@Override
public void changeCursor(Cursor cursor) {
super.changeCursor(cursor);
calcNotesCount();
}
// 私有方法用于计算便签的数量通过遍历游标中的所有记录根据记录对应的便签类型判断是否为普通便签若是则数量加1最终得到总的便签数量并更新`mNotesCount`变量。
private void calcNotesCount() {
mNotesCount = 0;
for (int i = 0; i < getCount(); i++) {
Cursor c = (Cursor) getItem(i);
if (c!= null) {
if (NoteItemData.getNoteType(c) == Notes.TYPE_NOTE) {
mNotesCount++;
}
} else {
Log.e(TAG, "Invalid cursor");
return;
}
}
}
}