现在的位置: 首页 > 移动开发 > 正文

Android实战之小说阅读器,带有水平翻页,记录上次读取页码数

2019年10月11日 移动开发 ⁄ 共 20641字 ⁄ 字号 评论关闭

实现的效果图:

实现的步骤:

一,建立布局文件:3个布局xml

1,activity_main.xml:显示sdcard卡中所有的文件夹及文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <TextView
        android:id="@+id/title_text"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:gravity="center_vertical"
        android:text="当前位置: /mnt/sdcard"
        android:textSize="14sp" />
    <ListView
        android:id="@+id/list"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="8"
        android:cacheColorHint="#00000000" >
    </ListView>
</LinearLayout>

2.file_line.xml主要填充list中的文本数据

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal" >
    <TextView
        android:id="@+id/file_img"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1" />
    <TextView
        android:id="@+id/file_name"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="4"
        android:textSize="14sp" />
</LinearLayout>

3.activity_detail.xml:这是小说显示的显示界面

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ffffff"
    android:orientation="vertical" >
    <TextView
        android:id="@+id/txt_title"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" /> 

//这里自定义一个MyView用以显示小说的文本内容
    <com.example.ebook.view.MyView
        android:id="@+id/txt_content"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="8"
       />
<TextView
        android:id="@+id/txt_page"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:gravity="center"
        android:textColor="#000000"
        android:textSize="14sp" />
</LinearLayout>

二、java代码部分:现在com.example.ebook.dbc包中创建DataBaseConnection类中建两个数据库:txt.db  和  page.db

package com.example.ebook.dbc;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;

public class DataBaseConnection extends SQLiteOpenHelper {
public DataBaseConnection(Context ctx){
super(ctx,"txt.db",null,1);
}
public DataBaseConnection(Context context, String name,
CursorFactory factory, int version) {
super(context, name, factory, version);
}
@Override
public void onCreate(SQLiteDatabase db) {
//初始化文本表
String sql = "CREATE TABLE txt (" +
"id integerprimarykey," +
"full_path
text ," +
"now_page
integer ," +
"over_flag
integer " +
")";
db.execSQL(sql);
//初始化页码表
sql ="CREATE TABLE page(" +
"id integerprimary key," +
"txt_id
integer ," +
"page_num
integer ," +
"content
text " +
")";
db.execSQL(sql);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

}
}

2.在util包中建类Globals:

package com.example.ebook.util;
import java.util.HashMap;
import java.util.Map;
import android.app.Activity;
import com.example.ebook.R;
import com.example.ebook.dbc.DataBaseConnection;
public class Globals {
public static int SCREEN_WIDTH;
public static int SCREEN_HEIGHT;

//建立一个map集合,里面封装了所有的扩展名对应的图片,以便进行文件图片的显示
public static Map<String,Integer> allIconImgs = new HashMap<String,Integer>();
public static DataBaseConnection dbc;
//每行显示的字数
public static int LINE_CHAR_COUNT = 20;
//字符间隔
public static int CHAR_SEP = 2;
//页边距
public static int PAGE_SEP = 20;
//每个字的大小
public static int CHAR_SIZE;
//行间隔
public static int LINE_SEP;
//计算行数
public static int LINE_COUNT;
//每一行文本之间的间隔文字
public static String TXT_SEP_FLAG = "LINE_SEP_FLAG_BU_NENG_CHONG_FU";

public static void init(Activity a){
SCREEN_WIDTH = a.getWindowManager().getDefaultDisplay().getWidth();
SCREEN_HEIGHT = a.getWindowManager().getDefaultDisplay().getHeight();

//初始化数据库
dbc = new DataBaseConnection(a);
dbc.getWritableDatabase();

//初始化所有扩展名和图片的对应的关系
allIconImgs.put("txt", R.drawable.txt_file);
allIconImgs.put("mp3", R.drawable.mp3_file);
allIconImgs.put("mp4", R.drawable.mp4_file);
allIconImgs.put("bmp", R.drawable.image_file);
allIconImgs.put("gif", R.drawable.image_file);
allIconImgs.put("png", R.drawable.image_file);
allIconImgs.put("jpg", R.drawable.image_file);
allIconImgs.put("dir_open", R.drawable.open_dir);
allIconImgs.put("dir_close", R.drawable.close_dir);

//计算数字= 屏幕宽度“字”总宽度/行字数 
//屏幕宽度“字”总宽度 = 屏幕宽度 - 页边距 * 2 - 字符间隔宽度
//字符间隔宽度 = (字符数-1)* 字符间距
CHAR_SIZE =(SCREEN_WIDTH - (PAGE_SEP * 2) - (LINE_CHAR_COUNT - 1)
* CHAR_SEP)/LINE_CHAR_COUNT;
//只使用屏幕高度的4/5来显示文字内容,计算所显示出的行数
//行数 = (屏幕*4/5)/(字的高度+行间距)
LINE_COUNT = SCREEN_HEIGHT * 4 / 5 / (CHAR_SIZE + LINE_SEP);
}

}

3.在com.example.ebook.util中添加TxtDAOUtil类

package com.example.ebook.util;
import java.util.HashMap;
import java.util.Map;
import android.database.Cursor;
public class TxtDAOUtil {
public static void insertData(String fullPath){
//先判断之前是否添加过
String sql = "SELECT id FROM txt WHERE full_path =?";
Cursor c = Globals.dbc.getReadableDatabase().rawQuery(sql,
new String[]{fullPath});

if(!c.moveToFirst()){
//数据库中没有这条数据,就需要添加,默认设置用户打开的页面是第一页, 同时还没有完成分页的操作
sql = "INSERT INTO txt (full_path,now_page,over_flag) VALUES (?,1,0)";

Globals.dbc.getWritableDatabase().execSQL(sql,new Object[]{fullPath});
}
c.close();

}

public static void updateOverFlag(int id){
String sql = "UPDATE txt SET over_flag =1 WHERE id =?";
Globals.dbc.getWritableDatabase().execSQL(sql, new Object[]{id});
}

public static void updateNowPage(int id,int nowPage){
String sql = "UPDATE txt SET now_page =? WHERE id =?";
Globals.dbc.getWritableDatabase().execSQL(sql, new Object[]{nowPage,id});
}

public static Map<String,Object> getTxtDataByFullPath(String fullPath){
Map<String,Object> map = new HashMap<String,Object>();
String sql = "SELECT id,now_page,over_flag FROM txt WHERE full_path = ?";
Cursor c = Globals.dbc.getReadableDatabase().rawQuery(sql,
new String[]{fullPath});
c.moveToFirst();
map.put("id", c.getInt(0));
map.put("nowPage", c.getInt(1));
map.put("overFlag", c.getInt(2));

return map;
}
}

4在com.example.ebook.util中建立PageDAOUtil

package com.example.ebook.util;
import java.util.Map;
import android.database.Cursor;
public class PageDAOUtils {
public static void insertData(Map<String, Object> map) {
String sql = "INSERT INTO page (txt_id,page_num,content) VALUES (?,?,?)";
Globals.dbc.getWritableDatabase().execSQL(
sql,
new Object[] { map.get("txtId"), map.get("pageNum"),
map.get("content") });
}
public static int getAllCount(int txtId) {
String sql = "SELECT COUNT(*) FROM page WHERE txt_id = ?";
Cursor c = Globals.dbc.getReadableDatabase().rawQuery(sql,
new String[] { String.valueOf(txtId) });
c.moveToFirst();
int count = c.getInt(0);
c.close();
return count;
}

public static void deletePageData(int txtId) {
String sql = "DELETE FROM page WHERE txt_id =?";
Globals.dbc.getWritableDatabase().execSQL(sql, new Object[] { txtId });
}

public static String getPageContent(int txtId, int pageNum) {
String sql = "SELECT content FROM page WHERE txt_id = ? AND page_num = ?";
Cursor c = Globals.dbc.getReadableDatabase()
.rawQuery(
sql,
new String[] { String.valueOf(txtId),
String.valueOf(pageNum) });

c.moveToFirst();
String content = c.getString(0);

c.close();
return content;
}
}

5. com.example.ebook.adapter中建立FileAdapter,这是解决sdcard卡显示布局的

package com.example.ebook.adapter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import com.example.ebook.R;
import com.example.ebook.util.Globals;
import android.content.ContentValues;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView.LayoutParams;
import android.widget.BaseAdapter;
import android.widget.TextView;

public class FileAdapter extends BaseAdapter {
private Context ctx;
private List<Map<String,Object>> allValues = new ArrayList<Map<String,Object>>();
public FileAdapter(Context ctx, List<Map<String, Object>> allValues) {
this.ctx = ctx;
this.allValues = allValues;
}

@Override
public int getCount() {
return allValues.size();
}

@Override
public Object getItem(int position) {
return allValues.get(position);
}

@Override
public long getItemId(int position) {
return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null){
convertView = LayoutInflater.from(ctx).inflate(R.layout.file_line, 
null);

//设置高度
convertView.setLayoutParams(new LayoutParams(
LayoutParams.MATCH_PARENT, Globals.SCREEN_HEIGHT /9));
}

//取得图片组件
TextView fileImg = (TextView) convertView.findViewById(R.id.file_img);
fileImg.getLayoutParams().height = Globals.SCREEN_HEIGHT/9;
TextView fileName = (TextView) convertView.findViewById(R.id.file_name);
//取得数据,设置到组件里
Map<String,Object> map = allValues.get(position);
//设置内容,文字
fileName.setText(map.get("fileName").toString());
//图片要根据扩展名取得
String extName = map.get("extName").toString();
//取得图片的id
int imgId = Globals.allIconImgs.get(extName);
//设置图片
fileImg.setBackgroundResource(imgId);
return convertView;
}
}

6.在package com.example.ebook中建立一个MainActivity类

package com.example.ebook;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.app.Activity;
import android.app.AlertDialog.Builder;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.os.Bundle;
import android.os.Environment;
import android.view.KeyEvent;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.ListView;
import android.widget.TextView;
import com.example.ebook.adapter.FileAdapter;
import com.example.ebook.util.Globals;
import com.example.ebook.util.TxtDAOUtil;

public class MainActivity extends Activity {
private TextView titleText;
private ListView list;
private FileAdapter adapter;
private List<Map<String,Object>> allValues = new ArrayList<Map<String,Object>>();

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

Globals.init(this);
setContentView(R.layout.activity_main);
//取得组件
titleText = (TextView) findViewById(R.id.title_text);
list = (ListView) findViewById(R.id.list);

//准备数据
//取得SD卡根目录
File root = Environment.getExternalStorageDirectory();
loadFileData(root);

//建立Adapter
adapter = new FileAdapter(this, allValues);
list.setAdapter(adapter);
//加入监听事件
list.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
//取得当前操作的数据
Map<String,Object> map = allValues.get(arg2);
//判断所有点的是文件还是文件夹
boolean dirFlag = (Boolean) map.get("dirFlag");
if(dirFlag){
//文件夹
//建立该文件的File对象
//取得绝对路劲
String fullPath = (String) map.get("fullPath");
//建立File
File dir = new File(fullPath);

//先清空原有的数据
allValues.clear();

if(!Environment.getExternalStorageDirectory()
.getAbsolutePath().equals(fullPath)){

//加入返回上一级的操作数
Map<String,Object> parent = new HashMap<String,Object>();
parent.put("fileName", "返回上一级");
parent.put("extName", "dir_open");
parent.put("dirFlag", true);
parent.put("fullPath", dir.getParent());

//保存一个标志
parent.put("flag", "TRUE");
//将这一行加入到数据集合中
allValues.add(parent);
}

//加入新数据
loadFileData(dir);
//使用Adapter通知界面ListView,数据已经被修改了,你也要一起改
adapter.notifyDataSetChanged();
}else{
//将该文件保存到文本表中
TxtDAOUtil.insertData(map.get("fullPath").toString());

//切换界面
Intent in = new Intent(MainActivity.this,DetailActivity.class);
in.putExtra("fullPath", map.get("fullPath").toString());
startActivity(in);
}
}
});
list.setOnItemLongClickListener(new OnItemLongClickListener() {

@Override
public boolean onItemLongClick(AdapterView<?> arg0, View arg1,
final int arg2, long arg3) {
//取得数据
Map<String,Object> map = allValues.get(arg2);
final File f = new File(map.get("fullPath").toString());

if(f.isFile()){
//弹出确认框
Builder builder = new Builder(MainActivity.this);
builder.setTitle("提示");
builder.setMessage("确认要删除该文件(" + f.getName() + ")吗?");
builder.setPositiveButton("确定",new OnClickListener() {

@Override
public void onClick(DialogInterface dialog, int which) {
//将SD卡中的文件删除
if(f.exists()){
f.delete();
}

//将列表中的数据删除
allValues.remove(arg2);
//通知
adapter.notifyDataSetChanged();
}
});
builder.setNegativeButton("取消", new OnClickListener() {

@Override
public void onClick(DialogInterface dialog, int which) {

}
});
builder.create().show();
}
return false;
}
});
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
//根据keyCode判断用户按下了那个键
if(keyCode == KeyEvent.KEYCODE_BACK){
//判断当前是否在SD卡根目录下。
//取得第一行数据
Map<String,Object> map = allValues.get(0);
if("TRUE".equals(map.get("flag"))){
//里面,需要返回上一级
list.performItemClick(list.getChildAt(0),
0, list.getChildAt(0).getId());
}else{
//弹出提示框
Builder builder = new Builder(MainActivity.this);
builder.setTitle("提示");
builder.setMessage("亲,真的要离开我吗?");
builder.setPositiveButton("真的", new OnClickListener() {

@Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
builder.setNegativeButton("取消", new OnClickListener() {

@Override
public void onClick(DialogInterface dialog, int which) {

}
});
builder.create().show();
}
return false;
}

return super.onKeyDown(keyCode, event);
}

private void loadFileData(File dir) {
//列出该目录下的所有文件
File[] allFiles = dir.listFiles();
//设置当前位置的提示信息
titleText.setText("当前位置:"+ dir.getAbsolutePath());

//判断
if(allFiles != null){
//循环
for(int i=0;i<allFiles.length;i++){
File f = allFiles[i];
Map<String,Object> map = new HashMap<String,Object>();
map.put("fileName", f.getName());
//多保存一个文件的绝对路径,方便在进行点击时使用
map.put("fullPath", f.getAbsolutePath());
//判断是文件夹还是文件
if(f.isDirectory()){
//是文件夹
map.put("extName", "dir_close");
map.put("dirFlag", true);
}else{
//是文件,截取出扩展名
String extName = f.getName()
.substring(f.getName().lastIndexOf(".")+1)
.toLowerCase();
map.put("extName", extName);
map.put("dirFlag", false);
}
//只有文件夹或是文本文件才要显示
if(f.isDirectory() || "txt".equals(map.get("extName"))){
allValues.add(map);
}
}
}
}
}


7.在 com.example.ebook.view中建立MyView类

package com.example.ebook.view;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;
import com.example.ebook.DetailActivity;
import com.example.ebook.R;
import com.example.ebook.util.Globals;
import com.example.ebook.util.PageDAOUtils;
public class MyView extends View {
private int pageNum;
private int txtId;

// 多查询上一页和下一页的文本,作为缓存保存下来,一边翻页时显示使用
private String preContent;
private String content;
private String nextContent;

// 加入监听,可以让当前的内容,跟着手指一起移动
// 开始时按下的位置
private float startX = 0;
// 移动后的位置
private float nowX = 0;
// 准备好TxtPage
private TextView txtPage;
public MyView(Context context) {
super(context);
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
// 为自己加入监听,这里的点击事件不需要实现,但是要写
this.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
}
});
this.setOnTouchListener(new OnTouchListener() {

@Override
public boolean onTouch(View v, MotionEvent event) {
// 判断当前操作的状态
if (event.getAction() == MotionEvent.ACTION_DOWN) {
// 按下是,记录横坐标的位置
startX = event.getX();
} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
nowX = event.getX();
// 平移界面中绘制的内容。
postInvalidate();
} else if (event.getAction() == MotionEvent.ACTION_UP) {
// 翻页操作
// 判断手指的位置
nowX = event.getX();
if (Math.abs(nowX - startX) < 50) {
// 不变
} else if (nowX > startX) {
// 翻上一页
if (pageNum > 1) {
pageNum--;
// 重新查询当前页的数据
changePage();
}
} else {
// 翻下一页
if (pageNum < PageDAOUtils.getAllCount(txtId)) {
pageNum++;
changePage();
}
}
nowX = 0;
startX = 0;
}
return false;
}

});
}

public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}

public void initPage(int txtId, int pageNum) {
this.txtId = txtId;
this.pageNum = pageNum;
changePage();
}
private void changePage() {
// 查询当前页的文本内容,并刷新显示到界面上
content = PageDAOUtils.getPageContent(txtId, pageNum);
// 同时查询出上一页和下一页的数据
if (pageNum > 1) {
// 有上一页
preContent = PageDAOUtils.getPageContent(txtId, pageNum - 1);
} else {
preContent = null;
}
if (pageNum < PageDAOUtils.getAllCount(txtId)) {
// 有下一页
nextContent = PageDAOUtils.getPageContent(txtId, pageNum + 1);
} else {
nextContent = null;
}

DetailActivity a = (DetailActivity) getContext();

if (txtPage == null) {
txtPage = (TextView) a.findViewById(R.id.txt_page);
}
// 改变底部的显示文字
txtPage.setText("分页完成,当前:" + pageNum + "/"
+ PageDAOUtils.getAllCount(txtId));

// 修改Activity中的nowPage
a.setNowPage(pageNum);
// 刷新显示内容
super.postInvalidate();
}
// 绘制组件中的具体内容
@Override
protected void onDraw(Canvas canvas) {
// 先清空之前绘制的所有内容
super.onDraw(canvas);
if (content != null) {
// 拆分每页的文本,变成每行的文本形式
String[] allStr = content.split(Globals.TXT_SEP_FLAG);

// 建立绘制参数对象
Paint paint = new Paint();
// 通过该对象设置绘制的颜色,文字大小,填充状态等信息
paint.setTextSize(Globals.CHAR_SIZE);
paint.setColor(Color.BLACK);
// 循环绘制 当前页的文字
for (int i = 0; i < allStr.length; i++) {
for (int j = 0; j < allStr[i].length(); j++) {
// 文字需要根据手指的移动位置有一个偏移
canvas.drawText(String.valueOf(allStr[i].charAt(j)),
Globals.PAGE_SEP + j
* (Globals.CHAR_SIZE + Globals.CHAR_SEP)
+ (nowX - startX), (i + 1)
* (Globals.CHAR_SIZE + Globals.LINE_SEP),
paint);
}
}

// 绘制上一页或下一页的文字
if (nowX < startX && nextContent != null) {
allStr = nextContent.split(Globals.TXT_SEP_FLAG);

// 正在翻向下一页,需要将下一页的内容显示出来
for (int i = 0; i < allStr.length; i++) {
for (int j = 0; j < allStr[i].length(); j++) {
// 文字需要根据手指的移动位置有一个偏移
canvas.drawText(
String.valueOf(allStr[i].charAt(j)),
Globals.PAGE_SEP
+ j
* (Globals.CHAR_SIZE + Globals.CHAR_SEP)
+ (nowX - startX)
+ Globals.SCREEN_WIDTH,
(i + 1)
* (Globals.CHAR_SIZE + Globals.LINE_SEP),
paint);
}
}
}
if (nowX > startX && preContent != null) {
allStr = preContent.split(Globals.TXT_SEP_FLAG);
// 正在翻向上一頁,需要將上一頁的內容显示出来
for (int i = 0; i < allStr.length; i++) {
for (int j = 0; j < allStr[i].length(); j++) {
// 文字需要根据手指的移动位置有一个偏移
canvas.drawText(
String.valueOf(allStr[i].charAt(j)),
Globals.PAGE_SEP
+ j
* (Globals.CHAR_SIZE + Globals.CHAR_SEP)
+ (nowX - startX)
- Globals.SCREEN_WIDTH,
(i + 1)
* (Globals.CHAR_SIZE + Globals.LINE_SEP),
paint);
}
}
}
}
}
}

8。最后建立DetailActivity

package com.example.ebook;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
import android.R.integer;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.TextView;
import com.example.ebook.util.Globals;
import com.example.ebook.util.PageDAOUtils;
import com.example.ebook.util.TxtDAOUtil;
import com.example.ebook.view.MyView;
public class DetailActivity extends Activity {

//声明这个handler类
private Handler handler;
//文本信息
private Map<String,Object> txtMap;
private Map<String,Object> pageMap = new HashMap<String,Object>();

private int lineCount;
private int pageNum;
private StringBuilder builder;
private String fullPath;
//取得底部显示分页的信息
private TextView txtPage;
//显示文本内容的标志
private boolean showedFlag = false;
//当前的页数
private int nowPage = 1;
public int getNowPage() {
return nowPage;
}

public void setNowPage(int nowPage) {
this.nowPage = nowPage;
}
private MyView txtContent;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail);
txtPage = (TextView) findViewById(R.id.txt_page);
txtContent = (MyView) findViewById(R.id.txt_content);

//接受传入的文本,查询数据库中该文件是否完成了分页
fullPath = getIntent().getStringExtra("fullPath");
txtMap  = TxtDAOUtil.getTxtDataByFullPath(fullPath);
//建立Handler
handler = new Handler(){
@Override
public void handleMessage(Message msg) {
if(msg.what == 0){
//显示已经处理好的页面
txtPage.setText("已经处理好了:"+(pageNum - 1)+"页的数据");
}else{
txtPage.setText("分页完成,当前:1/"+(pageNum-1));
}
}
};

//判断当前的文本是否被分页完成,如果没有被分页过,就需要自己进行分页处理
if((Integer)(txtMap.get("overFlag"))==0){
//首先这里必须子进程对内容进行读取,防止主线程读取卡屏
Thread t = new Thread(){
@Override
public void run() {
//进行分页的处理,就是要读取文本
try{
//将之前分页处理的结果删除,防止之前分页到一半,用户退出造成问题
PageDAOUtils.deletePageData((Integer) txtMap.get("id"));

//windows上的文本必须转码 
BufferedReader reader = new BufferedReader(
new InputStreamReader(new FileInputStream(
new File(fullPath)),"GBK"));
String line = null;
builder = new StringBuilder();

//计算已经读取的内容,在手机上显示的行数,当满足一页时,将其保存到数据库里,再重新计算行数,以便保存下一页
lineCount = 0;
//当前加入了的页数
pageNum = 1;

while((line = reader.readLine()) != null){
//对line进行拆分
//通过一个循环来截取内容
while(line.length() > 20){
//截取出一行
String tempStr = line.substring(0, 20);
addPageLineData(tempStr);

//截取后半部分,继续循环
line = line.substring(20);
}
//这里应该剩下一行,对该行也进行相同的处理
addPageLineData(line);
}
//剩下不到一页的内容,也要保存到数据库里
pageMap.put("txtId", txtMap.get("id"));
pageMap.put("pageNum", pageNum++);
pageMap.put("content", builder.toString());

PageDAOUtils.insertData(pageMap);
//如果整个文件都读取完成了,但还没有显示数据,就需要自己进行显示处理
if(!showedFlag){
showedFlag = true;
txtContent.initPage((Integer) txtMap.get("id"), 1);
}
//修改状态
TxtDAOUtil.updateOverFlag((Integer) txtMap.get("id"));
handler.sendEmptyMessage(1);
reader.close();
}catch(Exception e){
e.printStackTrace();
}
}
};
t.start();
}else{
//如果已经初始化好了分页
//需要显示出上次看到的位置
showedFlag = true;
txtContent.initPage((Integer)txtMap.get("id"), (Integer)txtMap.get("nowPage"));
}
}
@Override
protected void onDestroy() {
//退出时,需要记录下当前看到的页数
TxtDAOUtil.updateNowPage((Integer) txtMap.get("id"), nowPage);
super.onDestroy();
}
private void addPageLineData(String lineData) throws InterruptedException {
lineCount++;
builder.append(lineData);
builder.append(Globals.TXT_SEP_FLAG);

if(lineCount == Globals.LINE_COUNT){
//满一页,就需要保存
pageMap.put("txtId", txtMap.get("id"));
pageMap.put("pageNum", pageNum++);
pageMap.put("content", builder.toString());

PageDAOUtils.insertData(pageMap);

handler.sendEmptyMessage(0);
//如果已经够了10页,就可以显示了
if(!showedFlag){
showedFlag =  true;
txtContent.initPage((Integer) txtMap.get("id"), 1);
}

Thread.sleep(5);
//添加后,都需要将一些数据清空
builder = new StringBuilder();
lineCount = 0;
}
}
}

全部代码上传完毕,在翻页效果时,有那种说面的效果必须是需要算法的。这里后期的文章里将尝试解决。需要素材或是源码,评价中说明下

抱歉!评论已关闭.