背景说明
本篇内容基于百问网嵌入式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;
}
}