天天看點

txt閱讀器, 在别人的源碼上 增加書簽、字型縮放、書架 功能

首先說明,閱讀器 翻頁效果是下載下傳别人源碼的。 我僅僅是增加一些功能;

http://blog.csdn.net/hmg25/article/details/6419694

txt閱讀器, 在别人的源碼上 增加書簽、字型縮放、書架 功能

自定義View那個類,說實話我沒咋看(可以說沒看~)。那啥曲線原理,也不懂。。嘿嘿;

BookPageFactory 隻是看這個工具類

書簽是以xml格式存放, 代碼中生存xml檔案,及讀取;

書架是使用gridView 實作,效果還不是很好,至少有個樣子(也是網上找的...以及eoe裡一個哥們提供的,(因為我下載下傳的源碼 gridView屬性沒設定好,是以不好看。))

使用這個源碼。 首先的在SD卡下面 放一個test.txt檔案。大家随便下個小說改個名字就是;

MainReader.java

package com.zeng.reader;

import static com.zeng.reader.MarkManager.single;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
import org.xmlpull.v1.XmlSerializer;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.Window;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import android.widget.Toast;

public class MainReader extends Activity {
	/** Called when the activity is first created. */
	private PageWidget mPageWidget;
	Bitmap mCurPageBitmap, mNextPageBitmap;
	Canvas mCurPageCanvas, mNextPageCanvas;
	BookPageFactory pagefactory;

	//
	SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
				WindowManager.LayoutParams.FLAG_FULLSCREEN);
		mPageWidget = new PageWidget(this);
		setContentView(mPageWidget); 
		// 若是要修改分辨率的話, 請自己手動該 480 800 兩個值。
		mCurPageBitmap = Bitmap.createBitmap(480, 800, Bitmap.Config.ARGB_8888);
		mNextPageBitmap = Bitmap.createBitmap(480, 800, Bitmap.Config.ARGB_8888);
		//
		// 兩畫布
		mCurPageCanvas = new Canvas(mCurPageBitmap);
		mNextPageCanvas = new Canvas(mNextPageBitmap);
		pagefactory = new BookPageFactory(480, 800);
		// 設定一張背景圖檔
		pagefactory.setBgBitmap(BitmapFactory.decodeResource(this.getResources(), R.drawable.bg));
		//
		try {
			pagefactory.openbook(bookfillPath);// 打開檔案 擷取到一個緩存
			pagefactory.onDraw(mCurPageCanvas);//
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
			Toast.makeText(this, "電子書不存在,請将《test.txt》放在SD卡根目錄下", Toast.LENGTH_SHORT).show();
		}

		mPageWidget.setBitmaps(mCurPageBitmap, mCurPageBitmap);
		mPageWidget.setOnTouchListener(new OnTouchListener() {
			@Override
			public boolean onTouch(View v, MotionEvent e) {
				// TODO Auto-generated method stub

				boolean ret = false;
				if (v == mPageWidget) {
					if (e.getAction() == MotionEvent.ACTION_DOWN) {
						mPageWidget.abortAnimation();
						mPageWidget.calcCornerXY(e.getX(), e.getY());

						pagefactory.onDraw(mCurPageCanvas);
						if (mPageWidget.DragToRight()) {// 右邊點選的時候為false; 前一頁
							try {
								pagefactory.prePage();
							} catch (IOException e1) {
								// TODO Auto-generated catch block
								e1.printStackTrace();
							}
							if (pagefactory.isfirstPage())
								return false;
							pagefactory.onDraw(mNextPageCanvas);
						} else {
							try {
								pagefactory.nextPage();
							} catch (IOException e1) {
								// TODO Auto-generated catch block
								e1.printStackTrace();
							}
							if (pagefactory.islastPage())
								return false;
							pagefactory.onDraw(mNextPageCanvas);
						}
						mPageWidget.setBitmaps(mCurPageBitmap, mNextPageBitmap);
					}

					ret = mPageWidget.doTouchEvent(e);
					return ret;
				}
				return false;
			}

		});
	}

	// 菜單
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		menu.add(0, 0, 0, "添加書簽");
		menu.add(0, 1, 0, "檢視書簽");
		menu.add(0, 2, 0, "字型放大");
		menu.add(0, 3, 0, "字型縮小");
		return super.onCreateOptionsMenu(menu);
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// TODO Auto-generated method stub
		switch (item.getItemId()) {
		case 0:
			addTag();
			break;
		case 1:
			checkTag();
			break;
		case 2:
			// 這種方式調字型,不太好;
			int size = pagefactory.getM_fontSize();
			int newsize = size + 2;
			pagefactory.setM_fontSize(newsize);
			//
			int begin = pagefactory.getM_mbBufBegin();
			//
			pagefactory.setM_mbBufEnd(begin);
			try {
				pagefactory.nextPage();
				pagefactory.onDraw(mCurPageCanvas);
				pagefactory.onDraw(mNextPageCanvas);
				mPageWidget.invalidate();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			// pagefactory.clearM_lines();
			// pagefactory.onDraw(mCurPageCanvas);//
			// pagefactory.onDraw(mNextPageCanvas);//
			// mPageWidget.invalidate();

			break;
		case 3:
			int size1 = pagefactory.getM_fontSize();
			int newsize1 = size1 - 2;
			pagefactory.setM_fontSize(newsize1);
			int begin1 = pagefactory.getM_mbBufBegin();
			//
			pagefactory.setM_mbBufEnd(begin1);
			pagefactory.clearM_lines();//
			pagefactory.onDraw(mCurPageCanvas);//
			pagefactory.onDraw(mNextPageCanvas);//
			mPageWidget.invalidate();
			break;
		}
		return super.onOptionsItemSelected(item);
	}
//添加書簽
	private void addTag() {
		// 擷取3個值
		int begin = pagefactory.getM_mbBufBegin();
		int end = pagefactory.getM_mbBufEnd();
		String firstLine = ((pagefactory.getM_lines()).elementAt(0)).toString();
		String percent = pagefactory.getStrPercent();//
		String currentTime = sdf.format(new Date());
		// 建立一個書簽
		Items item = new Items(begin, end, firstLine, percent, currentTime);
		int isExist = single.isExist(bookName);
		if (isExist >= 0) {
			single.get(isExist).list.add(item);
			producXML();
			Toast.makeText(MainReader.this, "添加書簽成功", Toast.LENGTH_SHORT).show();
			return;
		}
		BookMark bm = new BookMark(bookName, item);
		single.add(bm);
		producXML();
		Toast.makeText(MainReader.this, "添加書簽成功", Toast.LENGTH_SHORT).show();
	}
	private void checkTag() {
		try {
			XmlParser.parseXml(bookMarkPath);
		} catch (XmlPullParserException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		final AlertDialog adb = new AlertDialog.Builder(this).create();
		adb.setIcon(R.drawable.face248);
		adb.setTitle("書簽");
		getData();
		LayoutInflater inflater = getLayoutInflater().from(this);
		View view = inflater.inflate(R.layout.listview, null);
		final ListView listView = (ListView) view.findViewById(R.id.listview);
		final TextView textView = (TextView) view.findViewById(R.id.listView_text);
		if (data.isEmpty()) {
			textView.setVisibility(View.VISIBLE);
			listView.setVisibility(View.GONE);
			adb.setView(view);
			adb.show();
			return;
		}

		adb.setView(view);
		adapter = new SimpleAdapter(MainReader.this, data, R.layout.list_item, new String[] { "content",
				"percent", "time" }, new int[] { R.id.textView1, R.id.textView2, R.id.textView3 });
		listView.setAdapter(adapter);
		listView.setOnItemClickListener(new OnItemClickListener() {

			@Override
			public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
				// TODO Auto-generated method stub
				int pos = single.isExist(bookName);
				BookMark bm = single.get(pos);
				Items item = bm.getList().get(position);
				// 這裡我加一個注釋, onDraw方法中 當m_lines是空的時候 ,執行pageDown() 該方法是以結尾點的
				// 位元組點為起點去下載下傳下一頁,(好像是的...),是以設定的時候開始點,結尾點,都設定為 開始點
				pagefactory.setM_mbBufEnd((int) item.getBegin());
				pagefactory.setM_mbBufBegin((int) item.getBegin());
				pagefactory.clearM_lines();
				pagefactory.onDraw(mCurPageCanvas);//
				pagefactory.onDraw(mNextPageCanvas);//
				adb.dismiss();
				mPageWidget.invalidate();
			}
		});

		listView.setOnItemLongClickListener(new OnItemLongClickListener() {

			@Override
			public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
				int pos = single.isExist(bookName);
				final BookMark bm = single.get(pos);
				Items item = bm.getList().get(position);
				final int position1 = position;// 下面使用
				AlertDialog.Builder ad = new AlertDialog.Builder(MainReader.this);
				ad.setTitle("删除該書簽").setMessage("确定删除?");
				ad.setPositiveButton("确定", new DialogInterface.OnClickListener() {

					@Override
					public void onClick(DialogInterface dialog, int which) {
						bm.getList().remove(position1);// 删除該資料
						// 再寫檔案。。
						producXML();
						getData();
						adb.cancel();
						if (data.isEmpty()) {
							textView.setVisibility(View.VISIBLE);
							listView.setVisibility(View.GONE);
							adb.show();
							return;
						}
						adapter.notifyDataSetChanged();
						adapter = new SimpleAdapter(MainReader.this, data, R.layout.list_item, new String[] {
								"content", "percent", "time" }, new int[] { R.id.textView1, R.id.textView2,
								R.id.textView3 });
						listView.setAdapter(adapter);
						adb.show();

					}
				}).setNegativeButton("取消", new DialogInterface.OnClickListener() {

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

					}
				}).show();

				return false;
			}
		});
		adb.show();
	}

	private SimpleAdapter adapter;
	ArrayList<Map<String, Object>> data;

	private void getData() {
		data = new ArrayList<Map<String, Object>>();
		if (single.count() == 0)
			return;
		int pos = single.isExist(bookName);
		BookMark bm = single.get(pos);
		for (int i = 0; i < bm.getList().size(); i++) {
			Map map = new HashMap<String, Object>();
			map.put("percent", bm.getList().get(i).getPercent());
			map.put("time", bm.getList().get(i).getTime());
			map.put("content", bm.getList().get(i).getContent());
			data.add(map);
		}
	}

	//
	private String bookName = "test";
	private long begin_pos;
	private long end_pos;
	private String content;// 隻取第一行;
	private String bookfillPath = "/sdcard/test.txt";
	private String bookMarkPath = "/sdcard/BookMark/bookmark.xml";

	/**
	 * @return 該方法是否要傳回值
	 */
	private boolean producXML() {
		//
		//

		try {
			XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
			XmlSerializer xmlSerializer = factory.newSerializer();
			//
			// xmlSerializer.setOutput(stringWriter);
			String path = "/sdcard/BookMark/";
			File file = new File(path);
			// file.mkdirs();
			// if(!file.isDirectory()){
			if (!file.exists()) {
				file.mkdirs();
			}
			File f = new File(path + "bookmark.xml");
			if (!f.exists()) {
				f = new File(path + "bookmark.xml");
			}
			FileOutputStream fos = new FileOutputStream(f);
			xmlSerializer.setOutput(fos, "utf-8");
			xmlSerializer.startDocument("utf-8", true);
			xmlSerializer.startTag(null, "books");
			if (single.count() != 0)
				for (BookMark mark : single.getList()) {

					xmlSerializer.startTag(null, "book");
					// xmlSerializer.startTag(null, "book"+" name="+bookName);
					xmlSerializer.attribute(null, "name", mark.getBookName());
					for (Items item : mark.getList()) {
						xmlSerializer.startTag(null, "items");
						xmlSerializer.attribute(null, "begin", item.getBegin() + "");
						xmlSerializer.attribute(null, "end", item.getEnd() + "");
						xmlSerializer.attribute(null, "content", item.getContent());
						xmlSerializer.attribute(null, "percent", item.getPercent());
						xmlSerializer.attribute(null, "time", item.getTime());
						xmlSerializer.endTag(null, "items");
					}
					xmlSerializer.endTag(null, "book");
				}
			xmlSerializer.endTag(null, "books");
			xmlSerializer.endDocument();
			//
			xmlSerializer.flush();
		} catch (XmlPullParserException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		} catch (IllegalStateException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}

		return true;
	}
}
           

BookPageFactory.java

package com.zeng.reader;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.io.UnsupportedEncodingException;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.text.DecimalFormat;
import java.util.Vector;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Align;

public class BookPageFactory {

	
	private File book_file = null;
	private MappedByteBuffer m_mbBuf = null;
	/**  位元組總長度  */
	private int m_mbBufLen = 0;
	/** 位元組開始位置 */
	private int m_mbBufBegin = 0;
	/** 位元組結束位置 */
	private int m_mbBufEnd = 0;
	private String m_strCharsetName = "gbk";
	private Bitmap m_book_bg = null;
	private int mWidth;
	private int mHeight;
	/**Vector<String> m_lines String型數組*/
	private Vector<String> m_lines = new Vector<String>();

	private int m_fontSize = 24;
	private int m_textColor = Color.BLACK;
	private int m_backColor = 0xffff9e85; // 背景顔色
	private int marginWidth = 15; // 左右與邊緣的距離
	private int marginHeight = 20; // 上下與邊緣的距離
	/**每頁可以顯示的行數*/
	private int mLineCount; // 每頁可以顯示的行數
	private float mVisibleHeight; // 繪制内容的寬
	private float mVisibleWidth; // 繪制内容的寬
	private boolean m_isfirstPage,m_islastPage;

	// private int m_nLineSpaceing = 5;

	private Paint mPaint;
	private Paint percentPaint;
	private String strPercent;
	public BookPageFactory(int w, int h) {
		// TODO Auto-generated constructor stub
		mWidth = w;
		mHeight = h;
		// percentPaint.設定不變樣式  ;寫百分比專用
		percentPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
		percentPaint.setTextAlign(Align.LEFT);
		percentPaint.setTextSize(24);//字型大小 24
		percentPaint.setColor(Color.BLACK);//黑體
		// 下面是幾個設定paint的。
		mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
		mPaint.setTextAlign(Align.LEFT);
		mPaint.setTextSize(m_fontSize);//字型大小 24
		mPaint.setColor(m_textColor);//黑體
		mVisibleWidth = mWidth - marginWidth * 2;// 繪制内容的寬   上下左右的邊緣都空一定的距離 是以*2
		mVisibleHeight = mHeight - marginHeight * 2;// 繪制内容的搞
		mLineCount = (int) (mVisibleHeight / m_fontSize); // 可顯示的行數 / 可顯示的高度除于每個字型的高度
	}

	public void openbook(String strFilePath) throws IOException {
		book_file = new File(strFilePath);
		long lLen = book_file.length();//算是位元組長度,有多少個位元組
		m_mbBufLen = (int) lLen;//一樣的
		//MappedByteBuffer 緩存
		m_mbBuf = new RandomAccessFile(book_file, "r").getChannel().map( FileChannel.MapMode.READ_ONLY, 0, lLen);
	}
	
	//讀取前一斷落
	protected byte[] readParagraphBack(int nFromPos) {
		int nEnd = nFromPos;
		int i;
		byte b0, b1;
		if (m_strCharsetName.equals("UTF-16LE")) {
			i = nEnd - 2;
			while (i > 0) {
				b0 = m_mbBuf.get(i);
				b1 = m_mbBuf.get(i + 1);
				if (b0 == 0x0a && b1 == 0x00 && i != nEnd - 2) {
					i += 2;
					break;
				}
				i--;
			}

		} else if (m_strCharsetName.equals("UTF-16BE")) {
			i = nEnd - 2;
			while (i > 0) {
				b0 = m_mbBuf.get(i);
				b1 = m_mbBuf.get(i + 1);
				if (b0 == 0x00 && b1 == 0x0a && i != nEnd - 2) {
					i += 2;
					break;
				}
				i--;
			}
		} else {
			i = nEnd - 1;// 之前的結束點, 往回擷取
			while (i > 0) {
				b0 = m_mbBuf.get(i);
				if (b0 == 0x0a && i != nEnd - 1) {
					i++;
					break;
				}
				i--;
			}
		}
		if (i < 0)
			i = 0;
		int nParaSize = nEnd - i;
		int j;
		byte[] buf = new byte[nParaSize];
		for (j = 0; j < nParaSize; j++) {
			buf[j] = m_mbBuf.get(i + j);
		}
		return buf;
	}


	// 讀取上一段落
	protected byte[] readParagraphForward(int nFromPos) {
		int nStart = nFromPos;
		int i = nStart;
		byte b0, b1;
		// 根據編碼格式判斷換行
		if (m_strCharsetName.equals("UTF-16LE")) {
			while (i < m_mbBufLen - 1) {
				b0 = m_mbBuf.get(i++);
				b1 = m_mbBuf.get(i++);
				if (b0 == 0x0a && b1 == 0x00) {
					break;
				}
			}
		} else if (m_strCharsetName.equals("UTF-16BE")) {
			while (i < m_mbBufLen - 1) {
				b0 = m_mbBuf.get(i++);
				b1 = m_mbBuf.get(i++);
				if (b0 == 0x00 && b1 == 0x0a) {
					break;
				}
			}
		} else {
			while (i < m_mbBufLen) {
				b0 = m_mbBuf.get(i++);
				if (b0 == 0x0a) {  // \r\n?
					break;
				}
			}
		}
		int nParaSize = i - nStart;
		byte[] buf = new byte[nParaSize];
		for (i = 0; i < nParaSize; i++) {
			buf[i] = m_mbBuf.get(nFromPos + i);
		}
		return buf;
	}

	protected Vector<String> pageDown() {
		String strParagraph = "";
		Vector<String> lines = new Vector<String>();
		while (lines.size() < mLineCount && m_mbBufEnd < m_mbBufLen) {
			byte[] paraBuf = readParagraphForward(m_mbBufEnd); // 讀取一個段落
			m_mbBufEnd += paraBuf.length;
			try {
				strParagraph = new String(paraBuf, m_strCharsetName);
			} catch (UnsupportedEncodingException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			String strReturn = "";
			if (strParagraph.indexOf("\r\n") != -1) {
				strReturn = "\r\n";
				strParagraph = strParagraph.replaceAll("\r\n", "");
			} else if (strParagraph.indexOf("\n") != -1) {
				strReturn = "\n";
				strParagraph = strParagraph.replaceAll("\n", "");
			}

			if (strParagraph.length() == 0) {
				lines.add(strParagraph);
			}
			while (strParagraph.length() > 0) { 
				float str_pixel = mPaint.measureText(strParagraph);
				System.out.println(str_pixel);
				int nSize = mPaint.breakText(strParagraph, true, mVisibleWidth, null);
				lines.add(strParagraph.substring(0, nSize));// 
				strParagraph = strParagraph.substring(nSize);// 
				if (lines.size() >= mLineCount) {
					System.out.println(lines.size());
					break;
				}
			}
			if (strParagraph.length() != 0) {
				try {
					m_mbBufEnd -= (strParagraph + strReturn).getBytes(m_strCharsetName).length;
				} catch (UnsupportedEncodingException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		return lines;//傳回下一頁的内容
	}
	//讀取前一頁的内容, 再把開始點=>結束點
	protected void pageUp() {
		if (m_mbBufBegin < 0)
			m_mbBufBegin = 0;
		Vector<String> lines = new Vector<String>();
		String strParagraph = "";
		while (lines.size() < mLineCount && m_mbBufBegin > 0) {
			Vector<String> paraLines = new Vector<String>();
			byte[] paraBuf = readParagraphBack(m_mbBufBegin);
			m_mbBufBegin -= paraBuf.length;
			try {
				strParagraph = new String(paraBuf, m_strCharsetName);
			} catch (UnsupportedEncodingException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			strParagraph = strParagraph.replaceAll("\r\n", "");
			strParagraph = strParagraph.replaceAll("\n", "");

			if (strParagraph.length() == 0) {
				paraLines.add(strParagraph);
			}
			while (strParagraph.length() > 0) {
				int nSize = mPaint.breakText(strParagraph, true, mVisibleWidth,
						null);
				paraLines.add(strParagraph.substring(0, nSize));
				strParagraph = strParagraph.substring(nSize);
			}
			lines.addAll(0, paraLines);
		}
		while (lines.size() > mLineCount) {
			try {
				m_mbBufBegin += lines.get(0).getBytes(m_strCharsetName).length;
				lines.remove(0);
			} catch (UnsupportedEncodingException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		m_mbBufEnd = m_mbBufBegin;
		return;
	}

	protected void prePage() throws IOException {
		if (m_mbBufBegin <= 0) {
			m_mbBufBegin = 0;//第一頁
			m_isfirstPage=true;
			return;
		}else m_isfirstPage=false;
		m_lines.clear();//清空
		pageUp();// m_mbBufEnd = m_mbBufBegin;
		m_lines = pageDown();
	}

	public void nextPage() throws IOException {
		if (m_mbBufEnd >= m_mbBufLen) {
			m_islastPage=true;
			return;
		}else m_islastPage=false;
		m_lines.clear();
		m_mbBufBegin = m_mbBufEnd;//把之前的結尾地方 為下一個開始位置
		m_lines = pageDown();
	}

	public void onDraw(Canvas c) {
		if (m_lines.size() == 0)
			m_lines = pageDown();//初始化時為0
		if (m_lines.size() > 0) {
			if (m_book_bg == null)
				c.drawColor(m_backColor);
			else
				c.drawBitmap(m_book_bg, 0, 0, null);
			int y = marginHeight;
			for (String strLine : m_lines) {//每讀取一行就繪一行的文字起點是marginwidth,x,marginHeight+字型大小
				y += m_fontSize;
				c.drawText(strLine, marginWidth, y, mPaint);
			}
		}
		float fPercent = (float) (m_mbBufBegin * 1.0 / m_mbBufLen);
		DecimalFormat df = new DecimalFormat("#0.0");
		 strPercent = df.format(fPercent * 100) + "%";
		int nPercentWidth = (int) percentPaint.measureText("999.9%") + 1;
		c.drawText(strPercent, mWidth - nPercentWidth, mHeight - 5, percentPaint);
	}

	public void setBgBitmap(Bitmap BG) {
		m_book_bg = BG;
	}
	
	public boolean isfirstPage() {
		return m_isfirstPage;
	}
	public boolean islastPage() {
		return m_islastPage;
	}
	
	
	// 下面是書簽 需要使用到的兩個資料
	public int getM_mbBufBegin() {
		return m_mbBufBegin;
	}

	public void setM_mbBufBegin(int m_mbBufBegin) {
		this.m_mbBufBegin = m_mbBufBegin;
	}

	public Vector<String> getM_lines() {
		return m_lines;
	}

	public void setM_lines(Vector<String> m_lines) {
		this.m_lines = m_lines;
	}

	public int getM_mbBufEnd() {
		return m_mbBufEnd;
	}

	public void setM_mbBufEnd(int m_mbBufEnd) {
		this.m_mbBufEnd = m_mbBufEnd;
	}
	public void clearM_lines(){
		this.m_lines.clear();
	}

	public int getM_fontSize() {
		return m_fontSize;
	}

	public void setM_fontSize(int m_fontSize) {
		this.m_fontSize = m_fontSize;
		mPaint.setTextSize(m_fontSize);
		mLineCount = (int) (mVisibleHeight / m_fontSize); // 可顯示的行數 / 可顯示的高度除于每個字型的高度
	}

	public String getStrPercent() {
		return strPercent;
	}

	public void setStrPercent(String strPercent) {
		this.strPercent = strPercent;
	}
	
}
           

下面是書簽相關的;

MarkManager.java。 裡面是幾個内部類,主要是管理書簽,和每個書簽的屬性

package com.zeng.reader;

import java.util.ArrayList;
import java.util.List;

public class MarkManager {
	public static final MarkManager single = new MarkManager();
	private List<BookMark> list = new ArrayList<BookMark>();

	public MarkManager() {
		// TODO Auto-generated constructor stub
	}

	public void add(BookMark bm) {
		list.add(bm);
	}

	public BookMark get(int position) {
		return list.get(position);
	}

	public int count() {
		return list.size();
	}

	public void set(int index, BookMark bm) {
		list.set(index, bm);
	}

	// 測試使用,
	public void removeAll() {
		list.clear();
	}

	public List<BookMark> getList() {
		return list;
	}

	/**
	 * 
	 * @param name
	 * @return 存在相同名字的則 傳回該位置,否則 -1;
	 */
	public int isExist(String name) {
		for (int i = 0; i < single.count(); i++) {
			BookMark bm = single.get(i);
			String str = bm.getBookName();
			if (str.equals(name))
				return i;
		}
		return -1;
	}
}

class BookMark {
	String bookName;
	List<Items> list;

	public BookMark() {
		// TODO Auto-generated constructor stub
		list = new ArrayList<Items>();
	}

	public BookMark(String bookName, Items item) {
		list = new ArrayList<Items>();
		this.bookName = bookName;
		list.add(item);
	}

	public BookMark(String bookName, List<Items> items) {
		// TODO Auto-generated constructor stub
	}

	public void setItem(Items item) {
		list.add(item);
	}

	public String getBookName() {
		return bookName;
	}

	public void setBookName(String bookName) {
		this.bookName = bookName;
	}

	public List<Items> getList() {
		return list;
	}

	public void setList(List<Items> list) {
		this.list = list;
	}
}

class Items {
	private long begin;
	private long end;
	private String content;
	private String percent;
	private String time;

	public Items() {
		// TODO Auto-generated constructor stub
	}

	public Items(long begin, long end, String content) {
		// TODO Auto-generated constructor stub
		this.begin = begin;
		this.end = end;
		this.content = content;
	}

	public Items(long begin, long end, String content, String percent,
			String time) {
		// TODO Auto-generated constructor stub
		this.begin = begin;
		this.end = end;
		this.content = content;
		this.time = time;
		this.percent = percent;
	}

	public long getBegin() {
		return begin;
	}

	public void setBegin(long begin) {
		this.begin = begin;
	}

	public long getEnd() {
		return end;
	}

	public void setEnd(long end) {
		this.end = end;
	}

	public String getContent() {
		return content;
	}

	public void setContent(String content) {
		this.content = content;
	}

	public String getPercent() {
		return percent;
	}

	public void setPercent(String percent) {
		this.percent = percent;
	}

	public String getTime() {
		return time;
	}

	public void setTime(String time) {
		this.time = time;
	}
	
}
           

解析xml  擷取書簽資訊

package com.zeng.reader;

import java.io.BufferedReader;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;

import android.util.Log;
import static com.zeng.reader.MarkManager.single;
public class XmlParser {
	public static void parseXml(String filepath)throws XmlPullParserException, IOException {
		XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
		factory.setNamespaceAware(true);
		XmlPullParser m_Parser = factory.newPullParser();
		
		FileInputStream infile = new FileInputStream(filepath);
		BufferedReader reader = new BufferedReader(new InputStreamReader(infile));
		 m_Parser.setInput(reader);
		 single.removeAll();// 或許要這一句?
		 int eventType = 0; int count = 0;int index = -1;
		 eventType = m_Parser.getEventType();
		 int columnNumber = m_Parser.getColumnNumber();
		 Log.i("abc", columnNumber+"") ;
		 //
		 BookMark bm = null;
		 while(eventType != XmlPullParser.END_DOCUMENT){
			 if(eventType == XmlPullParser.START_DOCUMENT){
				 Log.i("abc", "Start doc");
			 }else if(eventType == XmlPullParser.START_TAG){
				 Log.i("abc", "start tag"+m_Parser.getName());
				 if(m_Parser.getName().equals("books") == true){
					 
				 }else if(m_Parser.getName().equals("book") == true){
					 bm = new BookMark();
					 if(m_Parser.getAttributeName(0).equals("name") == true){
						 bm.setBookName(m_Parser.getAttributeValue(0));
					 }
				 }else if(m_Parser.getName().equals("items") == true){
					 Items item = new Items();
					 count = m_Parser.getAttributeCount();
					 for(int i = 0;i <count;i++){
						 if(m_Parser.getAttributeName(i).equals("begin") == true){
							 item.setBegin(Long.valueOf(m_Parser.getAttributeValue(i)));
						 }else if(m_Parser.getAttributeName(i).equals("end") == true){
							 item.setEnd(Long.valueOf(m_Parser.getAttributeValue(i)));
						 }else if(m_Parser.getAttributeName(i).equals("content")== true){
							 item.setContent(m_Parser.getAttributeValue(i));
						 }else if(m_Parser.getAttributeName(i).equals("percent")){
							 item.setPercent(m_Parser.getAttributeValue(i));
						 }else if(m_Parser.getAttributeName(i).equals("time")){
							 item.setTime(m_Parser.getAttributeValue(i));
						 }
					 }
					 bm.setItem(item);
					 int isExist = single.isExist(bm.getBookName());
					 if(isExist<0)
					 single.add(bm);
					 else
					 single.set(isExist, bm);
				 }
			 }else if(eventType == XmlPullParser.END_TAG){
				 if(m_Parser.getName().equals("items")){
					 
				 }
			 }else if(eventType == XmlPullParser.TEXT){
				 
			 }
			 eventType = m_Parser.next();
		 }
	}
}
           

書架的話,這個源碼暫時沒加上, 

之後再弄把。

  源碼下載下傳位址。 不需要分~~~~

http://download.csdn.net/detail/zgf1991/4345552