package com.example.mytxtreader;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.RelativeLayout;
import com.example.mytxtreader.MySeekBar.OnSeekBarChangeListener;
/**
* @author ludonghui
* 设计思想:写此demo时,刚开始接触Android,对canvas还不了解,所以并没有采用自定义控件
* 的方式来画出文本,而是用的系统的TextView控件
* 用内存映射的方式读取文件,每次读取固定大小,再用scorllTo函数实现上下移动和翻页功能
*/
@SuppressLint("HandlerLeak")
public class TxtContent extends Activity implements MyTextView.scrollInterface {
//test
private MappedByteBuffer m_mbBuf = null; //内存映射,
private long m_mbBufLen = 0; //目标文件的总长度,字节数
private final int ONCE_SIZE = 4096; //每次读取的字节数,要求大于2*每页最大字节数,否则会有BUG
private String m_strCurPage = null; //当前显示在TextView控件里的内容
private int m_sizeCount = 1; //此次读取了一个PAGESIZE还是两个PAGESIZE
private int m_totalCount = 0; //目标文件的总读取次数
private int m_curIndex = 0; //当前读取的次数序号
private int nTextHeight = 0; //当前TextView控件里的文本高度 行数*行高
private int m_curPageHeigh = 0; //当前ONCE_SIZE的文本高度
private int m_nextPageHeight = 0; //下一个ONCE_SIZE的文本高度,用于计算ScrollTo()的参数
private int m_pageHeight = 0; //当前文本框的高度,用于翻页计算
private int m_endScroll = 0; //最后一页的ScrollTo位置
private final int OFFSETPARA = 20; //每页下移的偏移量参数,防止可以看到部分上一行的内容
private String filenameString; //目标文件路径
private static final String gbk = "GBK"; //
private static final String utf8 = "UTF-8";
private static final String unicode = "UTF-16LE";
private static final String unicodeBigEnd = "UTF-16BE";
private static final int PROCESSMAX = 1000; //PROCESS的最大值
private String defaultCode = gbk; //当前编码格式
private MyTextView tvMain; //复写的TextView类,实现滑动效果
private MySeekBar seekBar; //复写的竖直SeekBar
private Button btnPreButton;
private Button btnNextButton;
private Button btnAutoStroll;
private boolean isScroll = false; //是否正在自动滚屏
private int scrollCount = 0; //已滚屏次数
private int m_scrollStep = 5; //每次滚屏的高度
private final int SCROLL_BEGIN = 1;
private final int SCROLL_END = 2;
private final int SCROLL_STOP = 3;
private int m_bgID = 1; //背景
private int m_textSize = 18; //字号大小
private int m_process = 0; //当前进度
private final String SAVEBG = "bgID";
private final String SAVETEXTSIZE = "textsize";
private final int CLBACK = 0xFF1A1A1A;
private final int CLWHITE = 0xFFEEEEEE;
private SpeekUtil speekUtil; //TTS类
private Context context;
private String m_strTTS; //当前TTS播报内容,即当前可见文本内容
/* (non-Javadoc)
* @see com.example.mytxtreader.MyTextView.scrollInterface#scrollBy(int)
* 点击屏幕移动时操作,移动文本,设置TTS播报内容,刷新进度条
*/
@Override
public void scrollBy(int dely) {
if (dely > 0) {
textMoveDown(dely);
getTTSContent();
refreshProcess();
}
if (dely < 0) {
textMoveUp(-dely);
getTTSContent();
refreshProcess();
}
}
Handler strollHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case SCROLL_BEGIN:
if ((m_curIndex >= m_totalCount - m_sizeCount)
&& (tvMain.getScrollY() >= m_endScroll)) {
strollHandler.sendEmptyMessage(SCROLL_END);
scrollCount = 0;
}
else {
textMoveDown(m_scrollStep);
scrollCount++;
if (scrollCount % (tvMain.getLineHeight()/m_scrollStep) == 0) {
scrollCount = 0;
getTTSContent();
refreshProcess();
}
strollHandler.sendEmptyMessageDelayed(SCROLL_BEGIN, 30);
}
break;
case SCROLL_END:
strollHandler.removeMessages(SCROLL_BEGIN);
strollHandler.removeMessages(SCROLL_STOP);
isScroll = false;
scrollCount = 0;
break;
case SCROLL_STOP:
strollHandler.removeMessages(SCROLL_BEGIN);
strollHandler.removeMessages(SCROLL_END);
isScroll = false;
scrollCount = 0;
break;
default:
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_txt_content);
btnPreButton = (Button) findViewById(R.id.viewtxt_pre_button);
btnPreButton.setOnClickListener(new BtnClickListener());
btnNextButton = (Button) findViewById(R.id.viewtxt_next_button);
btnNextButton.setOnClickListener(new BtnClickListener());
btnAutoStroll = (Button) findViewById(R.id.viewtxt_auto_scroll_button);
btnAutoStroll.setOnClickListener(new BtnClickListener());
seekBar = (MySeekBar) findViewById(R.id.seekBar1);
seekBar.setMax(PROCESSMAX);
seekBar.setOnSeekBarChangeListener(onSeekBarChangeListener);
// seekBar.setThumbOffset(5);
try {
readFile();
}
catch (Exception e) {
Log.e("Debug", "Read file error");
}
context = this;
}
@Override
protected void onDestroy() {
super.onDestroy();
saveParam(filenameString);
}
/**
* @param index
* 防止当前字符被截断造成乱码
* @return
*/
private int GetCurWordCutLen(int index) {
if (index <= 0) {
return 0;
}
if (defaultCode == gbk) {
// GBK编码规则:0x81~0xFE 0x40~0xFE,
int i = 0;
int curByte = m_mbBuf.get(index) & 0xFF;
int lastByte = m_mbBuf.get(index - 1) & 0xFF;
if (curByte >= 0x40 && curByte <= 0xFE) {
while (lastByte >= 0x81 && lastByte <= 0xFE && index - i - 1 >= 0) {
i++;
lastByte = m_mbBuf.get(index - i - 1) & 0xFF;
}
}
if (i % 2 == 0) {
return index;
}
else {
return index - 1;
}
}
if (defaultCode == utf8) {
// UTF8编码规则
// 000080 - 0007FF 编码规则 110xxxxx 10xxxxxx
// 000800 - 00FFFF 编码规则 1110xxxx 10xxxxxx 10xxxxxx
// 010000 - 10FFFF 编码规则 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
int curByte = m_mbBuf.get(index) & 0xFF;
while (curByte >= 0x80 && curByte <= 0xBF) {
index--;
curByte = m_mbBuf.get(index) & 0xFF;
}
return index;
}
return index;
}
//
private String readMappedByteBuffer(int pageIndex) {
return readMappedByteBuffer(pageIndex, 1);
}
/**
* @param index
* @param count
* @return
* 读取当前ONCE_SIZE的内容
*/
private String readMappedByteBuffer(int index, int count) {
if (index >= m_totalCount || index < 0) {
return null;
}
int start = index * ONCE_SIZE;
start = GetCurWordCutLen(start);
long len = 0;
if (ONCE_SIZE <= m_mbBufLen) {
len = (start + ONCE_SIZE * count <= m_mbBufLen) ? ONCE_SIZE * count : m_mbBufLen
- start;
}
else {
len = m_mbBufLen;
}
byte pageBuf[] = new byte[(int) len];
for (int i = 0; i < len; i++) {
pageBuf[i] = m_mbBuf.get(start + i);
}
String string = null;
try {
string = new String(pageBuf, defaultCode);
}
catch (Exception e) {
Log.e("Debug", "Get string from byte[]");
}
return string;
}
/**
* 获取当前TTS播报的文本
*/
private void getTTSContent() {
// int scrollY = (tvMain.GetMyScrollY() > 0) ? tvMain.GetMyScrollY() +
// 50 : 0;
// int line = tvMain.getLayout().getLineForVertical(
// scrollY - tvMain.getTotalPaddingTop());
int line = tvMain.GetMyScrollY() / tvMain.getLineHeight();
if (line >= tvMain.getLineCount() - 1) {
return;
}
int st = tvMain.getLayout().getOffsetForHorizontal(line, 0 - tvMain.get
没有合适的资源?快使用搜索试试~ 我知道了~
Txt文本阅读器电子书
共54个文件
png:20个
xml:18个
java:7个
5星 · 超过95%的资源 需积分: 49 86 下载量 182 浏览量
2015-07-11
09:29:34
上传
评论 1
收藏 1.8MB ZIP 举报
温馨提示
1.阅读txt文本,自动识别ANSI,UTF-8,UNICODE,UNICODE-BIGEND4种编码格式 2.自动滚屏,上/下翻页,点击滑动。 3.竖状seekBar,可跳转至文本的任意位置 4.秒读大文本文件,实测50M的文本完全hold住 5.可TTS播报,用的是在网上下载的讯飞jar和别人的appid 6.可换背景,调整字体大小,并记忆保存 7.记忆每个文件的上次读取进度
资源推荐
资源详情
资源评论
收起资源包目录
TxtView.zip (54个子文件)
TxtView
res
drawable-ldpi
values-v11
styles.xml 324B
menu
list_view.xml 188B
txt_content.xml 491B
main.xml 358B
values-v14
styles.xml 381B
drawable-hdpi
ic_launcher.png 7KB
thumb.xml 360B
volumecontrol.png 4KB
mainbg.png 12KB
volumecontrolover.png 4KB
bg.png 527KB
progress.xml 982B
drawable-xhdpi
ic_launcher.png 12KB
drawable
bg_s2.png 8KB
mainbg_s.png 1KB
mainbg_s2.png 3KB
mainbg_s_checked.png 1KB
mainbg_s2_checked.png 1KB
bg_s1.png 5KB
bg_s_checked.png 11KB
bg_s.png 13KB
mainbg_s1.png 3KB
mainbg_s3.png 3KB
bg_s2_checked.png 7KB
bg_s3.png 14KB
mainbg_select.xml 488B
bg_select.xml 472B
drawable-xxhdpi
ic_launcher.png 24KB
values
strings.xml 408B
styles.xml 680B
dimens.xml 213B
drawable-mdpi
ic_launcher.png 4KB
layout
activity_txt_content.xml 2KB
activity_main.xml 627B
mydialog.xml 4KB
activity_list_view.xml 489B
values-w820dp
dimens.xml 373B
readme.pages 132KB
.DS_Store 10KB
src
com
example
mytxtreader
MySeekBar.java 5KB
MyDialog.java 3KB
.DS_Store 6KB
MyTextView.java 6KB
ListViewActivity.java 3KB
MainActivity.java 2KB
SpeekUtil.java 2KB
TxtContent.java 19KB
.DS_Store 6KB
.DS_Store 6KB
.DS_Store 6KB
AndroidManifest.xml 2KB
libs
armeabi-v7a
armeabi
Msc.jar 430KB
android-support-v4.jar 741KB
x86
.DS_Store 8KB
共 54 条
- 1
资源评论
- ZuoHaiHuiHui2015-07-11将目标API等级改成18即可用,对初学者很有帮助
luna1121
- 粉丝: 1
- 资源: 1
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功