标签:
1,布局设置,LiearLayout 上中下三部分,其中小说主题内容部分为自定义view,比例是1:8:1
2,创建数据库表 两张表txt表和page表,两张表进行主外键关联
public class DBHelper extends SQLiteOpenHelper { public DBHelper(Context context) { super(context, "read.db", null, 1); } public DBHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) { super(context, name, factory, version); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL("create table txt(id Integer primry key,full_path text,now_page integer,over_flag integer)"); db.execSQL("create table page(id integer primary key,txt_id integer,page_num integer,content text)"); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } } 文本表<span style="font-size:12px;">public class TxtDB { public static void insertData(String fullPath) { String sql = "select id from txt where full_path=?"; Cursor c = Globals.helper.getReadableDatabase().rawQuery(sql, new String[]{fullPath}); if (!c.moveToFirst()) {//如果不存在数据则插入数据 sql = "insert into txt(id,full_path,now_page,over_flag) values(?,?,?,?)"; Globals.helper.getWritableDatabase().execSQL(sql, new Object[]{1,fullPath,1,0}); } c.close(); } public static Map<String, Object> loadData(String fullPath) { Map<String, Object> map = new HashMap<>(); String sql = "select id,now_page,over_flag from txt where full_path=?"; Cursor c = Globals.helper.getReadableDatabase().rawQuery(sql, new String[]{fullPath}); while (c.moveToNext()) { map.put("txtId", c.getInt(0)); map.put("nowPage", c.getInt(1)); map.put("overFlag", c.getInt(2)); } c.close(); return map; } public static void updateOverFlag(String fullPath) { String sql = "update txt set over_flag=1 where full_path=?"; Globals.helper.getWritableDatabase().execSQL(sql, new Object[]{fullPath}); } } </span>分页表<span style="font-size:12px;">public class PageDB { private static int pageNum; public static void insertDate(Map<String, Object> map) { String sql = "insert into page(txt_id,page_num,content) values(?,?,?)"; Globals.helper.getWritableDatabase().execSQL(sql, new Object[]{map.get("txtId"), map.get("pageNum"), map.get("content")}); } public static String findContent(int txtId, int pageNum) { String content = null; String sql = "select content from page where txt_id=? and page_num=?"; Cursor c = Globals.helper.getReadableDatabase().rawQuery(sql, new String[]{txtId + "", pageNum + ""}); while (c.moveToNext()) { content = c.getString(0); } c.close(); return content; } public static int findPageNum(int txtId){ String sql="select count(*) from page where txt_id=?"; Cursor c= Globals.helper.getReadableDatabase().rawQuery(sql,new String[]{txtId+""}); while(c.moveToNext()){ pageNum=c.getInt(0); } c.close(); return pageNum; } }</span>
3,定义一个全局可以使用的类Globals ,在里面设置页面内容,每行显示的字数,字间距,行间距,页边距,获得安卓设备的屏幕宽度和高度
public class Globals {
public static int SCREEN_WIDTH;
public static int SCREEN_HEIGHT;
public static int LINE_CHAR_COUNT=20;//每行显示20个字
public static int CHAR_SEP=2;//字间距
public static int PAGE_SEP=5;//页边距
public static int LINE_SEP=2;//行间距
public static int CHAR_SIZE;//字符大小,需计算,保证能根据屏幕大小自适应
public static int LINE_COUNT;//每页显示的行数,需计算。
public static void init(Activity a){
SCREEN_WIDTH=a.getWindowManager().getDefaultDisplay().getWidth();//获得屏幕宽度
SCREEN_HEIGHT=a.getWindowManager().getDefaultDisplay().getHeight();//获得屏幕高度
CHAR_SIZE=(SCREEN_WIDTH-PAGE_SEP*2-(LINE_CHAR_COUNT-1)*CHAR_SEP)/LINE_CHAR_COUNT;//计算出字符大小
LINE_COUNT=SCREEN_HEIGHT*4/5/(CHAR_SIZE+LINE_SEP);//计算每页显示的行数,并跟布局相适应,占屏幕的五分之四
}
}
4,自定义MyView,滑动翻页
<pre name="code" class="java">public class MyView extends View {
private String content;
private MainActivity a;
private float startX;
private float nowX;
private String preContent;//准备上一页和下一页的内容
private String nextContent;
public MyView(Context context) {
super(context);
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
a = (MainActivity) context;
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();//重新调用onDraw方法
} else if (event.getAction() == MotionEvent.ACTION_UP) {
if (Math.abs(nowX - startX) >= 50) {//nowX和startX的绝对值大于50 的话才执行翻页
if (nowX > startX) {//上一页
if (a.getNowPageNum() > 1) {
a.setNowPageNum(a.getNowPageNum() - 1);//翻到上一页
changeData();
}
}
if (nowX < startX) {//下一页
if (a.getNowPageNum() < a.getPageNum()) {
a.setNowPageNum(a.getNowPageNum() + 1);//翻到下一页
changeData();
}
}
}
startX = 0;
nowX = 0;
}
return false;
}
});
}
public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public void changeData() {
content = PageDB.findContent((int) a.getTxtMap().get("txtId"),a.getNowPageNum());
if (a.getNowPageNum() > 1) {//当前页不是第一页的时候
preContent = PageDB.findContent((int) a.getTxtMap().get("txtId"), a.getNowPageNum() - 1);
} else {
preContent = null;
}
if (a.getNowPageNum() < a.getPageNum()) {//当前页不是最后一页
nextContent = PageDB.findContent((int) a.getTxtMap().get("txtId"),a.getNowPageNum()+ 1);
} else {
nextContent = null;
}
a.getHandler().sendEmptyMessage(1);
super.postInvalidate();//调用OnDraw方法;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (content != null) {
String[] allValues = content.split(Globals.END_FLAG);
for (int i = 0; i < allValues.length; i++) {
for (int j = 0; j < allValues[i].length(); j++) {
if (j + i * Globals.char_line_conut < content.length()) {
Paint paint = new Paint();
paint.setColor(Color.BLACK);
paint.setTextSize(Globals.char_size);
canvas.drawText(String.valueOf(allValues[i].charAt(j)),
Globals.page_sep + j * (Globals.char_size + Globals.char_sep) + (nowX-startX),
i * (Globals.char_size + Globals.line_sep), paint);
}
}
}
}
if (nowX > startX && preContent != null) {
String[] allValues = preContent.split(Globals.END_FLAG);
for (int i = 0; i < allValues.length; i++) {
for (int j = 0; j < allValues[i].length(); j++) {
if (j + i * Globals.char_line_conut < content.length()) {
Paint paint = new Paint();
paint.setColor(Color.BLACK);
paint.setTextSize(Globals.char_size);
canvas.drawText(String.valueOf(allValues[i].charAt(j)),
Globals.page_sep + j * (Globals.char_size + Globals.char_sep) +(nowX-startX) -Globals.screen_width,
i * (Globals.char_size + Globals.line_sep), paint);
}
}
}
}
if (nowX < startX && nextContent != null) {
String[] allValues = nextContent.split(Globals.END_FLAG);
for (int i = 0; i < allValues.length; i++) {
for (int j = 0; j < allValues[i].length(); j++) {
if (j + i * Globals.char_line_conut < content.length()) {
Paint paint = new Paint();
paint.setColor(Color.BLACK);
paint.setTextSize(Globals.char_size);
canvas.drawText(String.valueOf(allValues[i].charAt(j)),
Globals.page_sep + j * (Globals.char_size + Globals.char_sep) +(nowX-startX) +Globals.screen_width,
i * (Globals.char_size + Globals.line_sep), paint);
}
}
}
}
}
}
<pre name="code" class="java">public class MainActivity extends AppCompatActivity {
static MyView contentView;
static TextView pageView;
private Map<String, Object> txtMap;
private Map<String, Object> pageMap = new HashMap<>();
private StringBuffer sb = new StringBuffer();
private int lineCount = 0;//每页的行数
static int pageNum = 1;//总页数
static int nowPageNum = 1;//当前页数
private String fullPath;
static Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what == 0) {
pageView.setText("正在分页,已经分解:" + pageNum);
} else if (msg.what == 1) {
pageView.setText("分页已经完成" + nowPageNum + "/" + pageNum);
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Globals.init(this);
setContentView(R.layout.activity_main);
contentView = (MyView) findViewById(R.id.content_view);
pageView = (TextView) findViewById(R.id.page_view);
fullPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/xiyouji.txt";//获取文件路径
TxtDB.insertIntoTxt(fullPath);
txtMap = TxtDB.loadTxtByFullpath(fullPath);
if ((int) txtMap.get("overFlag") == 0) {
//还未进行分页
new Thread() {
@Override
public void run() {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(fullPath), "GBK"));
String line = null;
while ((line = br.readLine()) != null) {
while (line.length() > Globals.char_line_conut) {
String str = line.substring(0, Globals.char_line_conut);
line = line.substring(Globals.char_line_conut);
addLine(str);
}
addLine(line);//行余下的不足以凑成一行的字数添加成一行
}
br.close();
handler.sendEmptyMessage(1);
TxtDB.updateOverFlag(fullPath);
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
} else {
//已经分页完成
pageNum = PageDB.getPageCount((int) txtMap.get("txtId"));
nowPageNum = (int) txtMap.get("nowPage");
contentView.changeData();
}
}
@Override
protected void onDestroy() {
TxtDB.updateNowPaga((int) txtMap.get("nowPage"), fullPath);
super.onDestroy();
}
public void addLine(String str) {//行凑成页之后存放到数据库中
sb.append(str);
sb.append(Globals.END_FLAG);
lineCount++;
if (lineCount == Globals.line_count) {
pageMap.put("txtid", txtMap.get("txtId"));
pageMap.put("pagenum", pageNum++);
pageMap.put("content", sb.toString());
PageDB.insertIntoPageDB(pageMap);
if (pageNum == 10) {
contentView.changeData();
}
handler.sendEmptyMessage(0);
sb = new StringBuffer();
lineCount = 0;//再次初始化供下次循环使用
}
}
public Map<String, Object> getTxtMap() {
return txtMap;
}
public void setTxtMap(Map<String, Object> txtMap) {
this.txtMap = txtMap;
}
public int getPageNum() {
return pageNum;
}
public void setPageNum(int pageNum) {
this.pageNum = pageNum;
}
public int getNowPageNum() {
return nowPageNum;
}
public void setNowPageNum(int nowPageNum) {
this.nowPageNum = nowPageNum;
}
public Handler getHandler() {
return handler;
}
public void setHandler(Handler handler) {
this.handler = handler;
}
public Map<String, Object> getPageMap() {
return pageMap;
}
}
标签:
原文地址:http://blog.csdn.net/zhm0303/article/details/51328586