今天讲阅读页,这作为嘎嘎读书系列的最后一篇文章吧,然后我会开始另外的项目分享,废话不说。先上截图。


            还记得上篇文章最后的提醒么,大家必须先具备了自定义view的重绘等相关知识,才能做出阅读页。首先去百度下“android自定义view”这个关键词吧。我先来说下为什么要使用android的自定义view。

            大家会发现譬如ireader 书旗等读书软件,都会有一个近似真实的翻页效果的阅读页,而android原生的view能够承接字体的比如textview,edit 都是不能够满足此效果的,这个时候,原生那些好用的view或者>p.measureText方法来测试一下,将200个字中前17个字拿出来,构成字符串,调用p.measureText(str) 如果返回值小于400 就测试18个字,18个字还小,就测试19个字,直到超过400停止,比如此时发现时20个字超过400,那么合适的字数就是19,那么将200个字的前19个字取出,将来放在第一行,剩下的字开始组装下一行的文字,依次循环,直到200个字都用光,我们就可以得到很多一行一样的文字。

     接下来,我们就需要将这些分好的行文字分页,因为任何一篇正常的文章都不可能一屏将所有文字都显示完全,分页的规则很简单,类似于分行,只不过并不需要measure方法,譬如24号字,而手机屏幕可以绘制范围是720高,那么大概能承担720/24=30行文字,而事实上 如果我们真这么干,那么最后文字将会挤在一起没法阅读。因为我们忘了其实有个行距的概念,这个也是可以自己估计的,比如我们要单倍的行距,也就是说两行文字间相隔一行文字的距离,那么我们手机屏幕一屏可以绘制的行数就是720/48=15行左右,而根据不同手机,或者我们的审美感觉,可以自定义比较合适的行距来调节一屏可绘制行数。这个就看个人的喜好了。

    最后我们讲准备好的15行文字封转到一个数据结构中,为绘制做准备,当onDraw被调用时,就在屏幕上对应的位置绘制出每行文字,一屏文字就绘制完毕,而且你会看到距离什么的都刚刚好,而如果还有剩余的文字,那么这些文字当然就成为下一页要绘制的文字,那么下一页只要仿照此页的做法,绘制文字,最终总会将所有文字绘制到屏幕上。而我们要的读书的效果就有了。

    讲到这里,大家应该有一个初步概念,我们必须先将一个长文字按照画笔和屏幕的设置,分割成行以及页的数据结构,然后交由view来有序绘制。而将来我要用view显示任何一段文字,只要将这段文字传入view,view的工作就是先将文字分析,然后绘制。这样一个大概的流程就形成了。

    下面先贴出来用来存储被分割后文字的数据结构:

    1.一行文字的存储数据结构:

     

package com.prince.gagareader.bean;

public class StringRulerBean {
	private int start;
	private int end;
	public int getStart() {
		return start;
	}
	public void setStart(int start) {
		this.start = start;
	}
	public int getEnd() {
		return end;
	}
	public void setEnd(int end) {
		this.end = end;
	}
	public StringRulerBean(int start, int end) {
		super();
		this.start = start;
		this.end = end;
	}
	
}

    从上面可以看出,我这个数据结构中并没有记录具体的字符串,而是记录了这个行子串的开头和结尾在原串中的位置,这当然是考虑节约内存,因为一篇文章的文字时比较多的,而如果每个结构都存储一个子串,会给内存带来双倍的开销。

    2.一页文字的存储数据结构:

package com.prince.gagareader.bean;

import java.util.ArrayList;
import java.util.List;
/**
 * 每页数据的封装
 * @author gagaprince
 *
 */
public class PrepageBean {
	/**
	 * 一页文字的开头结尾
	 */
	private StringRulerBean all;
	/**
	 * 一页文字 每行的开头结尾
	 */
	private List
    
    
     
      lines;
	public StringRulerBean getAll() {
		return all;
	}
	public void setAll(StringRulerBean all) {
		this.all = all;
	}
	public List
     
     
      
       getLines() {
		return lines;
	}
	public void setLines(List
      
      
       
        lines) {
		this.lines = lines;
	}
	public PrepageBean(){
		lines = new ArrayList
       
       
        
        ();
	}
}

        上面的代码中 使用了一个list来存储每行的数据,同时有一个StringRulerBean>

        我特别气愤的是我写了两个小时的东西,竟然没有保存下来,我都点保存了,结果竟然!没了!还找不回来了!伤心!这个编辑器太坑了。nnd!算了 不写了,大家应该没有看到关于动画 帧 双缓冲的内容!因为点了发表文章之后发现!直接给我阉割掉了!nnd!气死我了!老子不写了!起码有一千字不见了!我灰常生气!下面贴出来源码大家自己看吧!我就当我写了.....顺便提醒下大家用这个csdn的编辑器 不要用那个直接往里面贴源码的那个功能!估计就是那个功能坑的爹啊!老老实实用代码片吧!编辑器!我去年买了个表!!!!

         除此之外就是一些事件侦听的添加,以及和activity之间的交互等等。这里就略过不说了。我下面将整个阅读页需要用到的代码完整的贴在下方。有兴趣的同学可以捏着鼻子读一读。

         xml文件:

        Readview.java文件:

package com.prince.gagareader.view;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.Paint.FontMetrics;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewTreeObserver;

import com.prince.gagareader.R;
import com.prince.gagareader.bean.ChapterBean;
import com.prince.gagareader.bean.PrepageBean;
import com.prince.gagareader.bean.StringRulerBean;
import com.prince.gagareader.util.SharedPreferencesUtil;

public class ReaderView extends View{
	private Context context;
	public boolean hasLoadData = false;
	
	private int[] imgs={R.drawable.spring,R.drawable.nightstyle,R.drawable.sky,R.drawable.fenhong,R.drawable.yellow,R.drawable.yanpi,R.drawable.huyan,R.drawable.jiushu};
	private Bitmap bgBitmap;
	
	private Bitmap topBitmap;	//翻页时上层图片
	private Bitmap bottomBitmap;	//翻页时下层图片
	private Bitmap realBitmap;		//正式绘制的图片
	private Canvas topCanvas;
	private Canvas bottomCanvas;
	private Canvas realCanvas;
	
	private Paint textPaint;
	private Paint batterPaint;
	private Paint titlePaint;
	
	private int viewWidth;
	private int viewHeight;
	private boolean hasMeasured = false;
	private boolean pageClock = false;	//翻页动画锁
	private boolean touchMoveClock=false;//手指滑动锁,在按下屏幕时解锁 在需要加载下一张时加锁 并停止move操作
	private boolean loadDataClock = false;	//加载数据锁,在加载数据时 不再触发 excuteNext pre方法 加载完毕后解锁
	private int textSize =24;
	private int marginTop = 25;
	private int marginBottom=25;
	private int marginLeft = 25;
	private int marginRight = 15;
	
	private int currentBegin=0;
	
	private String textData="";
	private ChapterBean currentChapter;
	
	public static final int TRANSFORMLEFT=-1;
	public static final int TRANSFORMINIT=0;
	public static final int TRANSFORMRIGHT=1;
	private float touchStartX=-1;	//记录touchdown时手指位置
	private float touchStartY=-1;
	private int transFormDir = TRANSFORMINIT;	//滑动翻页时 
	
	private List
     
     
      
       needLoadDataListenners;
	private OnLoadDataCompleteImpl onLoadDataComplete;
	
	private int yuChapterCount=-1;
	private float batterLevel=-1f;
	private String chapterName;
	
	private boolean drawing = false;
	
	private OnMiddleClick middleClickListenner;
	
	
	
	public ReaderView(Context context) {  
        super(context);  
    }
	
	public ReaderView(Context context, AttributeSet attrs) {
		super(context, attrs);
		this.context = context;
		initBean();
		initTextPaint();
		initPreDrawListenner();
	}
	private void initBean(){
		needLoadDataListenners = new ArrayList
      
      
       
       ();
		onLoadDataComplete = new OnLoadDataCompleteImpl();
		SharedPreferencesUtil su = SharedPreferencesUtil.getInstance();
		textSize = su.getContextFontSize(context);
		bgBitmap = BitmapFactory.decodeResource(this.getContext().getResources(), imgs[su.getContextBg(context)]);
	}
	private void initTextSize(){
		if(textSize==-1){
			textSize = viewWidth/20;
			initTextPaint();
		}
	}
	/**
	 * 更新背景
	 * @param bgindex
	 */
	public void updateBg(int bgindex){
		bgBitmap = BitmapFactory.decodeResource(this.getContext().getResources(), imgs[bgindex]);
		SharedPreferencesUtil su = SharedPreferencesUtil.getInstance();
		int currentIndex = su.getContextBg(context);
		su.setContextBg(bgindex, context);
		int color = Color.BLACK;
		if(bgindex==1){
			color = Color.rgb(90, 90, 90);
			su.setContextLight(currentIndex, context);
		}
		textPaint.setColor(color);
		batterPaint.setColor(color);
		titlePaint.setColor(color);
		preparedTextBitmap(topCanvas, currentBegin);
		drawAllBitmap(0);
		postInvalidate();
	}
	
	public int getJindu(){
		return currentBegin+1;
	}
	public int getAllPage(){
		int allPageSize = currentChapter.getPages().size();
		return allPageSize;
	}
	public void setJindu(int despage){
		if(despage==getAllPage()){
			despage--;
		}
		if(despage
       
       
        
         lines = page.getLines();
			int lineHeight = getFontHeight();
			for(int i=0;i
        
        
         
         10){
					if(currentBegin==0){
						touchMoveClock = true;
						excuteNeedPre();
						return false;
					}
					transFormDir=TRANSFORMRIGHT;
					preparedTextBitmap(topCanvas, currentBegin-1);
					preparedTextBitmap(bottomCanvas, currentBegin);
				}else if(moveX<-10){
					if(currentBegin==currentChapter.getPages().size()-1){
						touchMoveClock = true;
						excuteNeedNext();
						return false;
					}
					transFormDir=TRANSFORMLEFT;
					preparedTextBitmap(topCanvas, currentBegin);
					preparedTextBitmap(bottomCanvas, currentBegin+1);
				}else{
					return true;
				}
			}
			if(moveX>0){
				if(transFormDir==TRANSFORMLEFT){
					drawAllBitmap(0);
				}else{
					drawAllBitmap((int)moveX-viewWidth);
				}
			}else{
				if(transFormDir==TRANSFORMLEFT){
					drawAllBitmap((int)moveX);
				}else{
					drawAllBitmap(-viewWidth);
				}
			}
			return true;
		case MotionEvent.ACTION_UP:
			if(!pageClock){
				stopDraw();
			}
			if(touchMoveClock){
				return false;
			}
			float upX = event.getX();
			if(transFormDir==TRANSFORMINIT){//只是点击 没有手动滑动操作翻页
				if(upX
         
         
           viewWidth-viewWidth/3){ goNextPage(-viewWidth/2,-1); }else{ // 点击屏幕中央 if(middleClickListenner!=null){ middleClickListenner.onClick(); } } }else{//由滑动操作就从此时坐标继续滑动操作 float upMoveX = upX-touchStartX; if(transFormDir==TRANSFORMLEFT){ if(upMoveX<0){ goNextPage((int)upMoveX,-1); } }else{ if(upMoveX>0){ goPrePage((int)upMoveX-viewWidth,-1); } } transFormDir = TRANSFORMINIT; } break; } return super.onTouchEvent(event); } /** * 下翻页 */ private void goNextPage(final int leftx,final int despage){ if(pageClock)return; if(currentBegin == currentChapter.getPages().size()-1){ excuteNeedNext(); return; } pageClock = true; //加锁 preparedTextBitmap(topCanvas, currentBegin); if(despage!=-1){ preparedTextBitmap(bottomCanvas, despage); }else{ preparedTextBitmap(bottomCanvas, currentBegin+1); } beginDraw(); new Thread(new Runnable() { int left=leftx; int v=15; public void run() { //left-=viewWidth/3; if(left<=50-viewWidth){ left=-viewWidth; } drawAllBitmap(left); while(left>-viewWidth){ try { Thread.sleep(1); } catch (InterruptedException e) { pageClock = false; e.printStackTrace(); } left-=v; v+=1; if(left<=-viewWidth){ left=-viewWidth; } drawAllBitmap(left); } if(despage!=-1){ currentBegin = despage; }else{ currentBegin++; } excuteNeedChangeBookMark(); pageClock = false; stopDraw(); } }).start(); } /** * 上翻页 */ private void goPrePage(final int leftx,final int despage){ if(pageClock)return; if(currentBegin ==0){ excuteNeedPre(); return; } pageClock = true; //加锁 if(despage!=-1){ preparedTextBitmap(topCanvas, despage); }else{ preparedTextBitmap(topCanvas, currentBegin-1); } preparedTextBitmap(bottomCanvas, currentBegin); beginDraw(); new Thread(new Runnable() { int left=leftx; int v=15; public void run() { //left+=viewWidth/2; if(left>=0){ left=0; } drawAllBitmap(left); while(left<0){ try { Thread.sleep(1); } catch (InterruptedException e) { pageClock = false; e.printStackTrace(); } left+=v; v+=1; if(left>=0){ left=0; } drawAllBitmap(left); } if(despage!=-1){ currentBegin=despage; }else{ currentBegin--; } excuteNeedChangeBookMark(); pageClock = false; stopDraw(); } }).start(); } public void excuteNeedReloadCurrent(){ if(loadDataClock)return; if(needLoadDataListenners!=null){ loadDataClock = true; int size = needLoadDataListenners.size(); for(int i=0;i 
          
            0){ hasLoadData = true; }else{ loadDataClock = false; } } } private void excuteNeedNext(){ if(loadDataClock)return; if(needLoadDataListenners!=null){ loadDataClock = true; preparedTextBitmap(topCanvas, currentBegin); int size = needLoadDataListenners.size(); for(int i=0;i 
           
             =0){ left=0; stopDraw(); } drawAllBitmap(left); while(left<0){ try { Thread.sleep(1); } catch (InterruptedException e) { pageClock = false; e.printStackTrace(); } left+=v; v+=1; if(left>=0){ left=0; } drawAllBitmap(left); } pageClock = false; stopDraw(); } }).start(); } @Override public void onError() { loadDataClock = false; } @Override public void onInitComplete() { goNext(); } private void goNext(){ reload(); loadDataClock = false; pageClock = true; preparedTextBitmap(bottomCanvas, currentBegin); beginDraw(); new Thread(new Runnable() { int left=0; int v=15; public void run() { //left-=viewWidth/2; if(left<=-viewWidth){ left=-viewWidth; stopDraw(); } drawAllBitmap(left); while(left>-viewWidth){ try { Thread.sleep(1); } catch (InterruptedException e) { pageClock = false; e.printStackTrace(); } left-=v; v+=1; if(left<=50-viewWidth){ left=-viewWidth; } drawAllBitmap(left); } pageClock = false; stopDraw(); } }).start(); } } public int getCurrentBegin() { return currentBegin; } public void setCurrentBegin(int currentBegin) { this.currentBegin = currentBegin; } public int getYuChapterCount() { return yuChapterCount; } public void setYuChapterCount(int yuChapterCount) { this.yuChapterCount = yuChapterCount; } public String getChapterName() { return chapterName; } public void setChapterName(String chapterName) { this.chapterName = chapterName; } private void batteryLevel() { BroadcastReceiver batteryLevelReceiver = new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { context.unregisterReceiver(this); int rawlevel = intent.getIntExtra("level", -1);//获得当前电量 int scale = intent.getIntExtra("scale", -1); float level = -1; if (rawlevel >= 0 && scale > 0) { level = (float)rawlevel/ scale; batterLevel = level; } } }; IntentFilter batteryLevelFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); context.registerReceiver(batteryLevelReceiver, batteryLevelFilter); } public void resizeFontSize(int fontsize){ textSize = fontsize; textPaint.setTextSize(textSize); int allpageCount = getAllPage(); int currentPage = currentBegin; reload(); int nowAllpageCount = getAllPage(); currentBegin = currentPage*nowAllpageCount/allpageCount; loadDataClock = false; excuteNeedChangeBookMark(); pageClock = true; preparedTextBitmap(bottomCanvas, currentBegin); beginDraw(); new Thread(new Runnable() { int left=0; int v=15; public void run() { //left-=viewWidth/2; if(left<=-viewWidth){ left=-viewWidth; stopDraw(); } drawAllBitmap(left); while(left>-viewWidth){ try { Thread.sleep(1); } catch (InterruptedException e) { pageClock = false; e.printStackTrace(); } left-=v; v+=1; if(left<=50-viewWidth){ left=-viewWidth; } drawAllBitmap(left); } pageClock = false; stopDraw(); } }).start(); } public interface OnMiddleClick{ public void onClick(); } public void setOnMiddleClick(OnMiddleClick middleClickListenner){ this.middleClickListenner = middleClickListenner; } }

        activity文件:

package com.prince.gagareader;

import java.io.IOException;
import java.lang.reflect.Field;

import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.provider.Settings;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;

import com.prince.gagareader.bean.BookBean;
import com.prince.gagareader.bean.BookMarkBean;
import com.prince.gagareader.bean.ContentBean;
import com.prince.gagareader.util.DateProvider;
import com.prince.gagareader.util.NovelUtil;
import com.prince.gagareader.util.SharedPreferencesUtil;
import com.prince.gagareader.view.ReaderView;
import com.prince.gagareader.view.ReaderView.NeedLoadDataListenner;
import com.prince.gagareader.view.ReaderView.OnMiddleClick;
import com.prince.gagareader.view.ReaderView.OnloadDataComplete;
import com.umeng.analytics.MobclickAgent;

import dalvik.system.TemporaryDirectory;

public class ReaderActivity extends Activity {
	private ReaderView readerView;
	private Handler handler;
	
	private String nid;
	private BookBean bookBean;
	private BookMarkBean bookMark;
	
	private LinearLayout dengLinear;
	private LinearLayout bottemButtonLinear;
	private LinearLayout muluButtonLinear;
	private LinearLayout bgiconLinear;
	private LinearLayout bgbuttonLinear;
	private LinearLayout lightseekBarLinear;
	private LinearLayout lightbuttonlinear;
	private SeekBar lightSeekBar;
	private LinearLayout jinduseekBarLinear;
	private SeekBar jinduSeekBar;
	private LinearLayout jinduButtonLinear;
	private SeekBar fontsizeSeekBar;
	private LinearLayout fontsizeButtonLinear;
	private LinearLayout fontsizeBarLinear;
	private LinearLayout nightlinear;
	
	private RelativeLayout allView;
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.reader);
        initView();
        initHandler();
        initData();
        addListenner();
        beginReader();
    }
    private void initData(){
    	Intent intent=getIntent();
		nid = intent.getStringExtra("nid");
		if(nid==null)nid="0dbe15224f0324a86d527972466e3adc";
		//先从书架初始化,在从网络初始化
		SharedPreferencesUtil su = SharedPreferencesUtil.getInstance();
		bookBean = su.getBookBeanByNid(nid, this);
		if(bookBean==null){
			handler.postDelayed(new Runnable() {
				@Override
				public void run() {
					try {
						bookBean = DateProvider.getInstance().getBookBeanByNid(nid);
						sendMsgBean(1);
					} catch (IOException e) {
						e.printStackTrace();
					} catch (JSONException e) {
						e.printStackTrace();
					}
				}
			},20);
		}else{
			sendMsgBean(1);
		}
    }
    private void initHandler(){
    	handler = new Handler(){
			@Override  
            public void handleMessage(Message msg) {
				 super.handleMessage(msg);  
	                switch (msg.what) {  
	                case 1://数据加载完成 显示
	                	preparedPage();
	                	break;
	                case 2:
	                	break;
	                default:  
	                    break;  
	                }  
			}
		};
    }
    
    private void preparedPage(){
    	Intent intent=getIntent();
    	String currentChapterStr = intent.getStringExtra("currentChapter");
    	if(bookBean!=null){
    		bookBean.setOnline(false);
    	}
    	if(currentChapterStr!=null){
    		int currentChapter = Integer.parseInt(currentChapterStr);
    		if(bookBean!=null){
    			SharedPreferencesUtil su = SharedPreferencesUtil.getInstance();
    			int currentChapterDB = bookBean.getCurrentCount();
    			if(currentChapter==currentChapterDB){
    				bookMark = su.getBookMarkByNid(nid, this);
    				if (bookMark==null) {
						bookMark = new BookMarkBean(1, 0);
					}
    				su.addBookBean(bookBean, this);
    			}else{
    				bookMark = new BookMarkBean(currentChapter, 0);
    				bookBean.setCurrentCount(currentChapter);
    				su.addBookBeanIfExist(bookBean, this);
    				su.setBookMark(nid, currentChapter, 0, this);
    			}
    		}
    	}else{
    		SharedPreferencesUtil su = SharedPreferencesUtil.getInstance();
    		su.addBookBean(bookBean, this);
    		bookMark = su.getBookMarkByNid(nid, this);
			if (bookMark==null) {
				bookMark = new BookMarkBean(1, 0);
			}
    	}
    	readerView.addNeedLoadDataListenner(new MyNeedLoadData());
    	if(!readerView.hasLoadData){
    		readerView.excuteNeedReloadCurrent();
    	}
    }
    
    private void initView(){
    	readerView = (ReaderView) findViewById(R.id.myReaderView);
    	dengLinear = (LinearLayout) findViewById(R.id.dengshengLinear);
    	bottemButtonLinear = (LinearLayout)findViewById(R.id.buttonBottemLinear);
    	muluButtonLinear = (LinearLayout)findViewById(R.id.muluButtonLinear);
    	bgiconLinear = (LinearLayout)findViewById(R.id.bgiconLinear);
    	bgbuttonLinear = (LinearLayout)findViewById(R.id.bgbuttonLinear);
    	lightseekBarLinear = (LinearLayout)findViewById(R.id.lightseekBarLinear);
    	lightbuttonlinear = (LinearLayout)findViewById(R.id.lightbuttonlinear);
    	lightSeekBar = (SeekBar)findViewById(R.id.lightseekBar);
    	jinduseekBarLinear = (LinearLayout)findViewById(R.id.jinduseekBarLinear);
    	jinduSeekBar = (SeekBar)findViewById(R.id.jinduseekBar);
    	jinduButtonLinear = (LinearLayout)findViewById(R.id.jinduButtonLinear);
    	fontsizeBarLinear = (LinearLayout)findViewById(R.id.fontsizeseekBarLinear);
    	fontsizeSeekBar = (SeekBar)findViewById(R.id.fontsizeseekBar);
    	fontsizeButtonLinear = (LinearLayout)findViewById(R.id.fontsizeButtonLinear);
    	nightlinear = (LinearLayout)findViewById(R.id.nightlinear);
    	allView = (RelativeLayout)findViewById(R.id.allView);
    }
    
    private void addListenner(){
    	readerView.setOnMiddleClick(new OnMiddleClick() {
			@Override
			public void onClick() {
				if(dengLinear.getVisibility()==View.INVISIBLE){
					showCtrl();
				}else{
					hideCtrl();
				}
			}
		});
    	muluButtonLinear.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				Intent intent = new Intent(ReaderActivity.this,
						MuluActivity.class);
				String nid = bookBean.getNid();
				String name = bookBean.getNovelName();
				intent.putExtra("nid", nid);
				intent.putExtra("cid", bookBean.getCurrentCount());
				intent.putExtra("novelName", name);
				intent.putExtra("isreading", true);
				startActivityForResult(intent, 0);
				hideCtrl();
			}
		});
    	bgbuttonLinear.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				bottemButtonLinear.setVisibility(View.INVISIBLE);
				bgiconLinear.setVisibility(View.VISIBLE);
			}
		});
    	lightbuttonlinear.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				bottemButtonLinear.setVisibility(View.INVISIBLE);
			 	lightSeekBar.setMax(255); 
		        int normal = Settings.System.getInt(getContentResolver(), 
		                Settings.System.SCREEN_BRIGHTNESS, 255); 
		        lightSeekBar.setProgress(normal); 
		        bottemButtonLinear.setVisibility(View.INVISIBLE);
				lightseekBarLinear.setVisibility(View.VISIBLE);
			}	
		});
    	jinduButtonLinear.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				int allPageSize = readerView.getAllPage();
				jinduSeekBar.setMax(allPageSize);
				int jindu = readerView.getJindu();
				jinduSeekBar.setProgress(jindu); 
				bottemButtonLinear.setVisibility(View.INVISIBLE);
				jinduseekBarLinear.setVisibility(View.VISIBLE);
			}
		});
    	fontsizeButtonLinear.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				SharedPreferencesUtil su = SharedPreferencesUtil.getInstance();
				int fontsize = su.getContextFontSize(ReaderActivity.this);
				fontsizeSeekBar.setMax(20);
				fontsizeSeekBar.setProgress(fontsize-10); 
				bottemButtonLinear.setVisibility(View.INVISIBLE);
				fontsizeBarLinear.setVisibility(View.VISIBLE);
			}
		});
    	LinearLayout linearTemp = (LinearLayout)findViewById(R.id.topbgiconLinear);
    	int childsize = linearTemp.getChildCount();
    	for(int i=0;i
    
    
     
      0 && tmpFloat <= 1) { 
                    wl.screenBrightness = tmpFloat; 
                } 
                getWindow().setAttributes(wl);
			}
			
			@Override
			public void onStartTrackingTouch(SeekBar seekBar) {}
			
			@Override
			public void onProgressChanged(SeekBar seekBar, int progress,
					boolean fromUser) {}
		});
    	jinduSeekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
			@Override
			public void onStopTrackingTouch(SeekBar seekBar) {
				int tmpInt = seekBar.getProgress(); 
				readerView.setJindu(tmpInt);
			}
			@Override
			public void onStartTrackingTouch(SeekBar seekBar) {}
			@Override
			public void onProgressChanged(SeekBar seekBar, int progress,
					boolean fromUser) {}
    	});
    	fontsizeSeekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
			@Override
			public void onStopTrackingTouch(SeekBar seekBar) {
				int tmpInt = seekBar.getProgress(); 
				int fontsize = tmpInt+10;
				SharedPreferencesUtil su = SharedPreferencesUtil.getInstance();
				int currentSize = su.getContextFontSize(ReaderActivity.this);
				if(currentSize!=fontsize){
					su.setContextFontSize(fontsize, ReaderActivity.this);
					readerView.resizeFontSize(fontsize);
				}
			}
			@Override
			public void onStartTrackingTouch(SeekBar seekBar) {}
			@Override
			public void onProgressChanged(SeekBar seekBar, int progress,
					boolean fromUser) {}
    	});
    	dengLinear.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				excuteNightButton();
			}
		});
    	nightlinear.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				excuteNightButton();
			}
		});
    }
    
    protected void onActivityResult(int requestCode, int resultCode, Intent data){
    	if(requestCode==0&&resultCode==RESULT_OK){
    		int cid = Integer.parseInt(data.getStringExtra("currentChapter"));
    		SharedPreferencesUtil su = SharedPreferencesUtil.getInstance();
			int currentChapterDB = bookBean.getCurrentCount();
			if(cid!=currentChapterDB){
				bookMark = new BookMarkBean(cid, 0);
				bookBean.setCurrentCount(cid);
				su.addBookBeanIfExist(bookBean, this);
				su.setBookMark(nid, cid, 0, this);
				readerView.excuteNeedReloadCurrent();
				hideCtrl();
			}
    	}
    	super.onActivityResult(requestCode,resultCode, data);   
    }
    
    private void excuteNightButton(){
    	SharedPreferencesUtil su = SharedPreferencesUtil.getInstance();
		int currentBg = su.getContextBg(ReaderActivity.this);
		if(currentBg==1){
			int newBg = su.getContextLight(ReaderActivity.this);
			readerView.updateBg(newBg);
		}else{
			readerView.updateBg(1);
		}
		hideCtrl();
    }
    
    /**
     * 显示控制面板
     */
    private void showCtrl(){
    	quitFullScreen();
    	allView.setPadding(0, -getStatusBarHeight(this), 0, 0);
    	dengLinear.setVisibility(View.VISIBLE);
    	bottemButtonLinear.setVisibility(View.VISIBLE);
    	SharedPreferencesUtil su = SharedPreferencesUtil.getInstance();
    	int currentBg = su.getContextBg(this);
    	ImageView nightimg = (ImageView)findViewById(R.id.nightimg);
    	TextView nighttv = (TextView)findViewById(R.id.nighttv);
    	if(currentBg==1){
    		nightimg.setBackgroundResource(R.drawable.dayicon);
    		nighttv.setText("白天");
    	}else{
    		nightimg.setBackgroundResource(R.drawable.nighticon);
    		nighttv.setText("黑夜");
    	}
    }
    /**
     * 隐藏控制面板
     */
    private void hideCtrl(){
    	setFullScreen();
    	allView.setPadding(0, 0, 0, 0);
    	dengLinear.setVisibility(View.INVISIBLE);
    	bottemButtonLinear.setVisibility(View.INVISIBLE);
    	bgiconLinear.setVisibility(View.INVISIBLE);
    	lightseekBarLinear.setVisibility(View.INVISIBLE);
    	jinduseekBarLinear.setVisibility(View.INVISIBLE);
    	fontsizeBarLinear.setVisibility(View.INVISIBLE);
    }
    private void beginReader(){
    	/*handler.post(new Runnable() {
			@Override
			public void run() {
				try {
					String content = getContentBycid(""+chapter);
					readerView.setTextData(content);
					readerView.initData();
				} catch (IOException e) {
					//网络异常
					e.printStackTrace();
				} catch (JSONException e) {
					//解析出错
					e.printStackTrace();
				}
			}
		});*/
    }
    
    private void sendMsgBean(int msgWhat){
		Message message = new Message();  
        message.what = msgWhat;
        handler.sendMessage(message);
	}
    
    private ContentBean getContentBycid(String cid) throws IOException, JSONException{
    	if(bookBean!=null){
    		String nid = bookBean.getNid();
    		String novelContent = NovelUtil.getInstance().preparedNovelByNidCid(nid, cid);
    		JSONObject textJson = new JSONObject(novelContent).getJSONObject("result");
    		String content = "        "+textJson.getString("content").trim().replaceAll("B#R", "\n        ");
    		String title = textJson.getString("ctitle");
    		return  new ContentBean(content, title);
    	}
		return null;
    }
    
    class MyNeedLoadData implements NeedLoadDataListenner{
		@Override
		public void needNext(final OnloadDataComplete call) {
			if(bookBean!=null){
				int allChapterCount = bookBean.getAllChapterCount();
				final int currentChapter = bookBean.getCurrentCount();
				if(currentChapter
     
     
      
      1){
					bookBean.setCurrentCount(currentChapter-1);
					SharedPreferencesUtil su = SharedPreferencesUtil.getInstance();
					su.addBookBeanIfExist(bookBean, ReaderActivity.this);
					preparedReaderData(call, currentChapter-1,0);
				}
			}
		}

		@Override
		public void reloadCurrent(OnloadDataComplete call) {
			Log.e("reload",bookMark+"");
			if(bookBean!=null&&bookMark!=null){
				final int currentChapter = bookBean.getCurrentCount();
				Log.e("reloadcurrent", bookMark.getCurrentPage()+"");
				readerView.setCurrentBegin(bookMark.getCurrentPage());
				preparedReaderData(call, currentChapter,2);
			}
		}

		@Override
		public void needChangeBookMark(int currentBegin) {
			bookMark.setCurrentCount(bookBean.getCurrentCount());
			bookMark.setCurrentPage(currentBegin);
			Log.e("changeBookMark", currentBegin+"");
			SharedPreferencesUtil.getInstance().setBookMark(nid, bookMark, ReaderActivity.this);
		}
    }
    
    private void preparedReaderData(final OnloadDataComplete call,final int currentChapter,final int flag){
    	handler.post(new Runnable() {
			@Override
			public void run() {
				ContentBean contentBean;
				try {
					contentBean = getContentBycid(""+currentChapter);
					readerView.setTextData(contentBean.getContent());
					readerView.setChapterName(contentBean.getTitle());
					readerView.setYuChapterCount(bookBean.getAllChapterCount()-currentChapter);
					if(flag==1){
						call.onNextComplete();
					}else if(flag==2){
						call.onInitComplete();
					}else{
						call.onPreComplete();
					}
				} catch (IOException e) {
					call.onError();
					e.printStackTrace();
				} catch (JSONException e) {
					call.onError();
					e.printStackTrace();
				}
			}
		});
    }
    
    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
		if(event.getKeyCode()==KeyEvent.KEYCODE_BACK&& event.getAction() == KeyEvent.ACTION_DOWN){
			SharedPreferencesUtil su = SharedPreferencesUtil.getInstance();
			if(!su.isBookExist(bookBean, this)){
				showIsAddDialog();
			}else{
				ReaderActivity.this.finish();
			}
			return true;
		}
		return super.dispatchKeyEvent(event);
	}
    
    /**
	 * 显示退出提示
	 */
	private void showIsAddDialog(){
		new AlertDialog.Builder(ReaderActivity.this)
		.setTitle("温馨提示")
		.setMessage("是否将此书加入书架,方便以后阅读")
		.setPositiveButton("加入书架",
				new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog,
							int which) {
						SharedPreferencesUtil su = SharedPreferencesUtil.getInstance();
						su.addBookBean(bookBean, ReaderActivity.this);
						ReaderActivity.this.finish();
					}
				})
		.setNegativeButton("取消",
				new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog,
							int which) {
						ReaderActivity.this.finish();
					}
				}).create().show();
	}
	
	private void setFullScreen()
    {
      getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
    }
    //[代码] 退出全屏函数:
    private void quitFullScreen()
    {
      final WindowManager.LayoutParams attrs = getWindow().getAttributes();
      attrs.flags &= (~WindowManager.LayoutParams.FLAG_FULLSCREEN);
      getWindow().setAttributes(attrs);
      getWindow().clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
    }
    
    public static int getStatusBarHeight(Context context){    
        Class
      
       c = null;    
        Object obj = null;    
        Field field = null;    
        int x = 0,
        statusBarHeight = 0;    
        try{    
            c= Class.forName("com.android.internal.R$dimen");    
            obj= c.newInstance();    
            field= c.getField("status_bar_height");    
            x= Integer.parseInt(field.get(obj).toString());    
            statusBarHeight= context.getResources().getDimensionPixelSize(x);    
        }catch(Exception e1) {    
            e1.printStackTrace();    
        }
        return statusBarHeight;   
    }
    
    public void onResume() {
		super.onResume();
		MobclickAgent.onResume(this);
	}
	public void onPause() {
		super.onPause();
		MobclickAgent.onPause(this);
	}
}

         

         到此为止,整个项目就算我得不得完了。简单总结下项目中需要用到的知识点:文件读写,线程,url请求,自定义view ,SharedPreferences,listview,gridview,android的service...等等吧。欢迎大家下载试用,并给我提好的建议。下载地址在第一篇文章中。

        虽然我知道我该说的可能没说到,不该说的有点啰嗦,但毕竟这是我第一次分享,还是请见谅啦!而且最主要的是记录下我的实践经历,同时给需要帮助的人一点点提示。我并不认为我写的代码多么的好,所以你既不用恭维也不用讽刺,相信未来我的代码世界会越来越丰富,希望大家一起努力。而我近期也会分享另一个项目。是一个音乐电台的应用。如果说电子书是享受眼睛的,那么下一个电台应用就是给耳朵用的。敬请期待!