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

还记得上篇文章最后的提醒么,大家必须先具备了自定义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 Listlines;
public StringRulerBean getAll() {
return all;
}
public void setAll(StringRulerBean all) {
this.all = all;
}
public ListgetLines() {
return lines;
}
public void setLines(Listlines) {
this.lines = lines;
}
public PrepageBean(){
lines = new ArrayList();
}
}

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

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

除此之外就是一些事件侦听的添加,以及和activity之间的交互等等。这里就略过不说了。我下面将整个阅读页需要用到的代码完整的贴在下方。有兴趣的同学可以捏着鼻子读一读。
xml文件:
        其中引用了一个自定义view 即刚才讲的那个view
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 ListneedLoadDataListenners;
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(despagelines = page.getLines();
int lineHeight = getFontHeight();
for(int i=0;i10){
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(upXviewWidth-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;i0 && 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(currentChapter1){
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){
Classc = 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...等等吧。欢迎大家下载试用,并给我提好的建议。下载地址在第一篇文章中。
虽然我知道我该说的可能没说到,不该说的有点啰嗦,但毕竟这是我第一次分享,还是请见谅啦!而且最主要的是记录下我的实践经历,同时给需要帮助的人一点点提示。我并不认为我写的代码多么的好,所以你既不用恭维也不用讽刺,相信未来我的代码世界会越来越丰富,希望大家一起努力。而我近期也会分享另一个项目。是一个音乐电台的应用。如果说电子书是享受眼睛的,那么下一个电台应用就是给耳朵用的。敬请期待!

我的首个电子书软件--嘎嘎读书 的开发(八)相关推荐

  1. 我的首个电子书软件--嘎嘎读书 的开发(三)

    接上篇,这篇文章接着介绍书架页,不过附带将菜单页也一起说了吧,毕竟两个页面功能是在一起的.大家一定体验过一些软件的侧边栏效果,比如人人网客户端 百度美拍等等.我就仿照做了这样一个效果.效果图如下哦~ ...

  2. 我的首个电子书软件--嘎嘎读书 的开发(四)

    今天事情比较多,直接入主题,这次我介绍电子书的推荐页,先上一张推荐页的截图,看下效果. 正常的思路来讲 这是一个结构比较多样的页面,特别是内容是比较动态的页面,因为推荐的内容会不定期的更换,一般这样的 ...

  3. epub 电子书软件代码销售

    epub 电子书软件代码销售 本套代码用来读取epub 格式电子书. 主要面向:有一定开发能力的人员,和有一定制作水平的朋友们. 用途:自己开发学习,钻研,出appstore 应用,卖钱,加广告赚钱等 ...

  4. 在Ubuntu18.04.2LTS上安装电子书软件

    在Ubuntu18.04.2LTS上安装电子书软件 一.前言      很多时候我们想在Ubuntu上阅读电子书,但是Ubuntu上的软件对于这种阅读的界面支持并不好,因此我们需要自己加入喜欢的阅读器 ...

  5. 推荐一款很好的全平台电子书软件:StartReader

    背景:最近正发愁寻找一款全平台.支持epub的电子书软件,对比了几款后,能做到全平台的电子书软件寥寥无几,但是发现一款精品软件StartReader,它的免费功能基本已经满足所有需求. 定位:支持WI ...

  6. 软件项目管理读书报告

    软件项目管理读书报告 项目管理是项目管理在领域的应用.它结合了行业特点并且运用了项目管理技术.理念和方法,包含着多个知识领域(如时间管理.成本管理.质量管理.风险管理.人力资源管理.沟通交流管理及采购 ...

  7. 云原生IDE:iVX首个通用且强大无代码开发平台

    云原生IDE:iVX首个通用且强大无代码开发平台 1.前言:iVX是什么? 2.iVX--首个通用无代码开发平台 首个 开发平台 无代码 通用 3.iVX系统架构 应用架构概览 前端技术框架 后台技术 ...

  8. SkyEye(一种软件模拟的系统开发平台)

    一.SkyEye介绍 1.SkyEye的起源和发展 2002年11月,一个偶然的机会,一群操作系统的爱好者在网上进行聊天,成立了一个TM-Linux兴趣小组,希望要做一些感兴趣的事情.当时在清华大学计 ...

  9. 软件项目管理0717:开发一定要了解客户

    软件项目管理0717:开发一定要了解客户 今天遇到一个问题,客户在使用我们平台的时候,遇到一个问题,但是他在跟我们测试同事沟通的过程中越沟通越绕,客户直接懵掉了,测试也一肚子气. 及时介入后发现开发没 ...

最新文章

  1. Apache Flink 漫谈系列(12) - Time Interval(Time-windowed) JOIN...
  2. 5G时代下的网络营销对移动端网站建设形成怎样的冲击?
  3. 2038: [2009国家集训队]小Z的袜子(hose)+莫队入门
  4. mysql象限和投影_Camera类之orthographic-摄像机投影模式(第100篇随笔)
  5. Java I/O模型从BIO到NIO和Reactor模式
  6. WebRTC手记之初探
  7. OpenCV Features2D和全息照相法查找已知物体
  8. python链表的实现,有注释
  9. 纯干货 | UI界面中按钮设计汉堡按钮\菜单
  10. 带父节点的平衡二叉树_平衡二叉树 通俗易懂
  11. Linux文件系统:ext2/ext3
  12. 【CF633H】Fibonacci-ish II 莫队+线段树
  13. java.sql.SQLException: Incorrect string value: '\xF0\x9F\x91\xBD\xF0\x9F…' 问题汇总
  14. leetcode——第322题——零钱兑换
  15. c++win32项目 如何显示后再删除一个绘图_iMATLAB 绘图扩展函数系列 | 让你绘图更自由(进阶专辑开篇)!...
  16. BUUCTF 命令执行/文件包含类型部分wp
  17. linux内存管理笔记(三十九)----kswapd内存回收
  18. ssh免密码登录配置方法,(图示加命令)
  19. ubuntu显示器分辨率不对_Ubuntu安装事宜之一 — 屏幕分辨率问题
  20. 【Python技巧】(虚拟环境报错、pycharm)无法加载文件 ...\venv\Scripts\activate.ps1,因为在此系统上禁止运行脚本。

热门文章

  1. VisionSeed:一颗让 AI 开发遍地开花的种子!
  2. JAVA计算机毕业设计智慧后勤系统Mybatis+源码+数据库+lw文档+系统+调试部署
  3. 同频干扰信号 仿真 matlab,直接序列扩频系统抗同频干扰的MATLAB仿真8.29(可靠性分析12月)...
  4. LeetCode 807 保持城市天际线
  5. 旁路openwrt启用ipv6
  6. 荣耀android应用程序未安装,荣耀7安装不了软件/安装失败解决方法介绍
  7. HEIC图片转JPG和其他格式
  8. TDengine 签约航天五院,助力航天事业信息化
  9. excel 这也许是史上最好最全的VLOOKUP函数教程
  10. ug建模文本怎么竖着_UG三维建模一个文字模型,换个角度竟然是一个新的文字!...