/* * 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. */ // NotesListItem.java - 便签列表项自定义视图 // 主要功能:显示便签或文件夹列表项的完整视图,包括图标、文本、时间等 package net.micode.notes.ui; // ======================= 导入区域 ======================= // Android基础 import android.content.Context; // 上下文 import android.text.format.DateUtils; // 日期工具,用于相对时间显示 // Android视图 import android.view.View; // 视图基类 // Android控件 import android.widget.CheckBox; // 复选框 import android.widget.ImageView; // 图片视图 import android.widget.LinearLayout; // 线性布局容器 import android.widget.TextView; // 文本视图 // 应用内部资源 import net.micode.notes.R; // 资源文件R类 // 应用数据模型 import net.micode.notes.data.Notes; // Notes主类 // 应用工具 import net.micode.notes.tool.DataUtils; // 数据工具 // 应用资源解析 import net.micode.notes.tool.ResourceParser.NoteItemBgResources; // 列表项背景资源 // ======================= 便签列表项视图 ======================= /** * NotesListItem - 便签列表项自定义视图 * 继承自LinearLayout,表示便签列表中的单个项 * 功能:显示便签/文件夹的完整信息,包括标题、时间、图标、背景等 * 职责:数据绑定、视图更新、背景选择 */ public class NotesListItem extends LinearLayout { // ======================= 成员变量 ======================= /** 提醒图标 - 显示便签是否有提醒 */ private ImageView mAlert; /** 置顶图标 - 显示便签是否置顶 */ private ImageView mPinned; /** 标题文本 - 显示便签摘要或文件夹名称 */ private TextView mTitle; /** 时间文本 - 显示修改时间(相对时间) */ private TextView mTime; /** 联系人姓名文本 - 通话记录专用,显示联系人姓名 */ private TextView mCallName; /** 便签数据项 - 当前项绑定的数据 */ private NoteItemData mItemData; /** 复选框 - 多选模式下显示,用于选择操作 */ private CheckBox mCheckBox; // ======================= 构造函数 ======================= /** * 构造函数 * 初始化列表项视图,加载布局并查找子视图 * @param context 上下文 */ public NotesListItem(Context context) { super(context); // 1. 加载布局文件 // R.layout.note_item: 列表项布局 // 第三个参数true: 将布局添加到当前LinearLayout inflate(context, R.layout.note_item, this); // 2. 查找并保存子视图引用 mAlert = (ImageView) findViewById(R.id.iv_alert_icon); mPinned = (ImageView) findViewById(R.id.iv_pinned_icon); mTitle = (TextView) findViewById(R.id.tv_title); mTime = (TextView) findViewById(R.id.tv_time); mCallName = (TextView) findViewById(R.id.tv_name); mCheckBox = (CheckBox) findViewById(android.R.id.checkbox); } // ======================= 数据绑定方法 ======================= /** * 绑定数据到视图 * 根据便签数据类型和状态更新所有UI元素 * 绑定流程: * 1. 处理选择模式复选框 * 2. 根据便签类型设置不同显示 * 3. 更新标题、时间、图标 * 4. 设置合适的背景 * * @param context 上下文,用于获取资源和字符串 * @param data 便签数据项 * @param choiceMode 是否在选择模式中 * @param checked 该项是否被选中 */ public void bind(Context context, NoteItemData data, boolean choiceMode, boolean checked) { // 1. 处理选择模式复选框 if (choiceMode && data.getType() == Notes.TYPE_NOTE) { // 选择模式且是便签类型:显示复选框 mCheckBox.setVisibility(View.VISIBLE); mCheckBox.setChecked(checked); } else { // 非选择模式或非便签类型:隐藏复选框 mCheckBox.setVisibility(View.GONE); } // 保存数据引用 mItemData = data; // 2. 根据便签类型设置不同显示 if (data.getId() == Notes.ID_CALL_RECORD_FOLDER) { // 情况1:通话记录文件夹 bindCallRecordFolder(context, data); } else if (data.getParentId() == Notes.ID_CALL_RECORD_FOLDER) { // 情况2:通话记录文件夹中的便签 bindCallRecordNote(context, data); } else { // 情况3:普通文件夹或便签 bindNormalItem(context, data); } // 3. 更新时间显示(所有类型都显示) mTime.setText(DateUtils.getRelativeTimeSpanString(data.getModifiedDate())); // 4. 设置背景 setBackground(data); } // ======================= 通话记录文件夹绑定 ======================= /** * 绑定通话记录文件夹 * 特殊显示:文件夹图标 + 便签数量 * @param context 上下文 * @param data 文件夹数据 */ private void bindCallRecordFolder(Context context, NoteItemData data) { // 隐藏联系人姓名 mCallName.setVisibility(View.GONE); // 显示提醒图标(文件夹图标) mAlert.setVisibility(View.VISIBLE); // 设置主标题样式 mTitle.setTextAppearance(context, R.style.TextAppearancePrimaryItem); // 设置标题文本:文件夹名称 + 文件数量 mTitle.setText(context.getString(R.string.call_record_folder_name) + context.getString(R.string.format_folder_files_count, data.getNotesCount())); // 设置文件夹图标 mAlert.setImageResource(R.drawable.call_record); } // ======================= 通话记录便签绑定 ======================= /** * 绑定通话记录便签 * 特殊显示:联系人姓名 + 提醒图标 * @param context 上下文 * @param data 便签数据 */ private void bindCallRecordNote(Context context, NoteItemData data) { // 显示联系人姓名 mCallName.setVisibility(View.VISIBLE); mCallName.setText(data.getCallName()); // 设置副标题样式 mTitle.setTextAppearance(context,R.style.TextAppearanceSecondaryItem); // 设置标题文本(格式化摘要) mTitle.setText(DataUtils.getFormattedSnippet(data.getSnippet())); // 根据是否有提醒设置图标 if (data.hasAlert()) { mAlert.setImageResource(R.drawable.clock); mAlert.setVisibility(View.VISIBLE); } else { mAlert.setVisibility(View.GONE); } } // ======================= 普通项绑定 ======================= /** * 绑定普通文件夹或便签 * 通用显示逻辑 * @param context 上下文 * @param data 便签/文件夹数据 */ private void bindNormalItem(Context context, NoteItemData data) { // 隐藏联系人姓名 mCallName.setVisibility(View.GONE); // 设置主标题样式 mTitle.setTextAppearance(context, R.style.TextAppearancePrimaryItem); if (data.getType() == Notes.TYPE_FOLDER) { // 文件夹:显示名称 + 文件数量 mTitle.setText(data.getSnippet() + context.getString(R.string.format_folder_files_count, data.getNotesCount())); mAlert.setVisibility(View.GONE); // 文件夹不显示提醒图标 } else { // 普通便签:显示格式化摘要 mTitle.setText(DataUtils.getFormattedSnippet(data.getSnippet())); // 根据是否有提醒设置图标 if (data.hasAlert()) { mAlert.setImageResource(R.drawable.clock); mAlert.setVisibility(View.VISIBLE); } else { mAlert.setVisibility(View.GONE); } // 根据是否置顶设置置顶图标 if (data.isPinned()) { mPinned.setVisibility(View.VISIBLE); } else { mPinned.setVisibility(View.GONE); } } } // ======================= 背景设置 ======================= /** * 设置列表项背景 * 根据便签类型和位置选择不同的背景图片 * 背景选择规则: * 1. 便签:根据位置选择不同背景(首项、中间项、末项、单独项) * 2. 文件夹:统一使用文件夹背景 * * @param data 便签数据项 */ private void setBackground(NoteItemData data) { int id = data.getBgColorId(); // 获取背景颜色ID if (data.getType() == Notes.TYPE_NOTE) { // 便签类型:根据位置选择背景 if (data.isSingle() || data.isOneFollowingFolder()) { // 单独项或文件夹后的唯一便签:单独项背景 setBackgroundResource(NoteItemBgResources.getNoteBgSingleRes(id)); } else if (data.isLast()) { // 最后一项:底部圆角背景 setBackgroundResource(NoteItemBgResources.getNoteBgLastRes(id)); } else if (data.isFirst() || data.isMultiFollowingFolder()) { // 第一项或文件夹后的多个便签之一:顶部圆角背景 setBackgroundResource(NoteItemBgResources.getNoteBgFirstRes(id)); } else { // 中间项:普通直角背景 setBackgroundResource(NoteItemBgResources.getNoteBgNormalRes(id)); } } else { // 文件夹类型:统一使用文件夹背景 setBackgroundResource(NoteItemBgResources.getFolderBgRes()); } } // ======================= 数据获取方法 ======================= /** * 获取便签数据项 * 用于获取当前视图绑定的数据 * @return 便签数据项 */ public NoteItemData getItemData() { return mItemData; } }