背景说明
本篇内容基于百问网嵌入式Linux项目数码相框与文件浏览器和嵌入式Linux电子书阅读器
需求:在文件浏览器界面中支持双击打开TXT类型文件,进入新界面进行文本阅读和翻页控制。
实现思路说明
浏览器界面中响应双击操作,识别TXT类型文件成功后进入阅读器界面。可参考项目中图片类型(BMP,JPG,PNG)文件的处理逻辑
else if (isTextFileSupported(tPageParams.strCurPictureFile)){// 支持文本文件的编码格式DBG_PRINTF("点击打开文件 %s\n", tPageParams.strCurPictureFile);tPageParams.iPageID = ID("browse");Page("reading")->Run(&tPageParams);ShowBrowsePage(&g_tBrowsePageMenuIconsLayout);
}
核心内容:阅读器界面的设计与实现
参考项目数码相框与文件浏览器中界面框架的设计(主界面和浏览器界面),主要包含:
- UI 部分:通过Layout布局设计按钮和内容显示区域
- 事件处理:捕获输入事件并响应,完成业务逻辑
业务逻辑的设计实现参考 嵌入式Linux电子书阅读器:
-
内容显示:在指定区域内显示文本文字,直到满页或者文件尾记为一页。
-
按钮响应:
- “返回”:退出阅读器界面,跳转到浏览器界面
- “上一页”:刷新显示文本内容逻辑上前面的部分,区域满屏记为上一页。当前为第一页则不响应处理。
- “下一页”:刷新显示文本内容逻辑上后面的部分,区域满屏或者达到文件尾记为下一页。
内容显示:
static int ShowTextInReadingPage(PT_VideoMem ptVideoMem, char *strFileName)
{int iError;// 打开文本文件strncpy(g_tFileMap.strFileName, strFileName, 256);g_tFileMap.strFileName[255] = '\0';iError = MapFile(&g_tFileMap);if (iError){DBG_PRINTF("MapFile %s error!\n", strFileName);return 0;}// 确认文件编码g_ptEncodingOprForFile = SelectEncodingOprForFile(g_tFileMap.pucFileMapMem);if (!g_ptEncodingOprForFile){DBG_PRINTF("SelectEncodingOprForFile %s error!\n", strFileName);UnMapFile(&g_tFileMap);return 0;}// 第一个显示字符紧接在文件头后面g_pucLcdFirstPosAtFile = g_tFileMap.pucFileMapMem + g_ptEncodingOprForFile->iHeadLen;// 在打开的文件中标记索引位置,在显示设备上逐行逐个显示字符// 自动记录当前的进度,重新打开时恢复unsigned char *pucTextFileMemCurPos;if (g_ptCurPage){pucTextFileMemCurPos = g_ptCurPage->pucLcdFirstPosAtFile; // 上一次阅读界面的第一个字符}else{pucTextFileMemCurPos = g_pucLcdFirstPosAtFile; // 文本文件中的第一个字符}iError = ShowOnePage(pucTextFileMemCurPos, ptVideoMem);return 0;
}
函数ShowOnePage
实现的功能:
-
逐个获取文件中的字符
-
处理特殊字符,如换行
-
对于文字字符,通过字符文件获取矢量位图,调整位置后显示到 LCD 设备上
- 项目已支持相关接口:
GetCodeFrmBuf
通过字符文件获取矢量位图,MergeOneFontToVideoMem
显示单个字符到 LCD 设备上
- 项目已支持相关接口:
-
-
到达文件尾部或者满页,则完成一页显示
翻页控制
记录显示的每一页:
typedef struct PageDesc {int iPage;unsigned char *pucLcdFirstPosAtFile;unsigned char *pucLcdNextPageFirstPosAtFile;struct PageDesc *ptPrePage;struct PageDesc *ptNextPage;
} T_PageDesc, *PT_PageDesc;
通过链表管理显示页面,实现逻辑上的翻页显示:
static void RecordPage(PT_PageDesc ptPageNew)
{PT_PageDesc ptPage;if (!g_ptPages){g_ptPages = ptPageNew;}else{ptPage = g_ptPages;while (ptPage->ptNextPage){ptPage = ptPage->ptNextPage;}ptPage->ptNextPage = ptPageNew;ptPageNew->ptPrePage = ptPage;}
}