package com.novelbook.android.utils; import android.app.ProgressDialog; import android.content.ContentValues; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Region; import android.graphics.Typeface; import android.os.AsyncTask; import android.os.Handler; import android.os.Message; import android.util.DisplayMetrics; import android.util.Log; import android.view.WindowManager; import android.widget.Toast; import com.novelbook.android.R; import com.novelbook.android.bean.NovelSites; import com.novelbook.android.bean.Site; import com.novelbook.android.db.Chapter; import com.novelbook.android.db.Novel; import com.novelbook.android.netutils.NetUtil; import com.novelbook.android.view.PageWidget; import org.litepal.LitePal; import java.io.File; import java.io.IOException; import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; //import static com.baidu.tts.loopj.AsyncHttpClient.log; public class PageFactory implements ChangeSource{ private static final String TAG = "PageFactory"; private static PageFactory pageFactory; private Context mContext; private Config config; //当前的书本 // private File book_file = null; // 默认背景颜色 private int m_backColor = 0xffff9e85; //页面宽 private int mWidth; //页面高 private int mHeight; //文字字体大小 private float m_fontSize ; //时间格式 private SimpleDateFormat sdf; //时间 private String date; //进度格式 private DecimalFormat df ; //电池边界宽度 private float mBorderWidth; // 上下与边缘的距离 private float marginHeight ; //满屏 差异 private float screenHeihtDiff ; // 左右与边缘的距离 private float measureMarginWidth ; // 左右与边缘的距离 private float marginWidth ; //状态栏距离底部高度 private float statusMarginBottom; //行间距 private float lineSpace; //段间距 private float paragraphSpace; //段间距相对行间距的倍数 private final float prate = 1.3f; //字高度 private float fontHeight; //字体 private Typeface typeface; //文字画笔 private Paint mPaint; //加载画笔 private Paint waitPaint; //文字颜色 private int m_textColor = Color.rgb(50, 65, 78); // 绘制内容的宽 private float mVisibleHeight; // 绘制内容的宽 private float mVisibleWidth; // 每页可以显示的行数 private int mLineCount; //电池画笔 private Paint mBatterryPaint ; //电池字体大小 private float mBatterryFontSize; //背景图片 private Bitmap m_book_bg = null; //当前显示的文字 // private StringBuilder word = new StringBuilder(); //当前总共的行 // private Vector m_lines = new Vector<>(); // // 当前页起始位置 // private long m_mbBufBegin = 0; // // 当前页终点位置 // private long m_mbBufEnd = 0; // // 之前页起始位置 // private long m_preBegin = 0; // // 之前页终点位置 // private long m_preEnd = 0; // 图书总长度 // private long m_mbBufLen = 0; private Intent batteryInfoIntent; //电池电量百分比 private float mBatteryPercentage; //电池外边框 private RectF rect1 = new RectF(); //电池内边框 private RectF rect2 = new RectF(); //文件编码 // private String m_strCharsetName = "GBK"; //当前是否为第一页 private boolean m_isfirstPage; //当前是否为最后一页 private boolean m_islastPage; //书本widget private PageWidget mBookPageWidget; // //书本所有段 // List allParagraph; // //书本所有行 // List allLines = new ArrayList<>(); //现在的进度 private float currentProgress; //目录 // private List directoryList = new ArrayList<>(); //书本路径 private String bookPath = ""; //书本名字 private String bookName = ""; private Novel mBook; //书的目录列表 private List mChapters; //当前章节 // private Chapter mCurrentChapter; //书本章节 private int currentChapter = 0; //当前电量 private int level = 0; private BookUtil mBookUtil; private PageEvent mPageEvent; private TRPage currentPage; private TRPage prePage; private TRPage cancelPage; private long openBookPosition=0;//打开书本时的章节位置 ContentValues values = new ContentValues(); private List currentChaptPages; private List tmpChaptPages; private List nextChaptPages; private List preChaptPages; private AdInterface mAd; private BookTask bookTask; private boolean isShowPrePage; //往前翻页到上一章时,从该章最后一页开始显示 public void setAd(AdInterface ad){ mAd =ad; } Handler handler = new Handler() { @Override public void handleMessage(Message msg) { int wt = msg.what; handlerMsg(msg); dismissProgressDialog(); } }; void handlerMsg(Message msg) { if (msg.what == 1) { Log.d(TAG, String.format("prepare book handler get notic to download chapter %s , mBook is null? %s",currentChapter, mBook==null ) ); if (mBook != null) { changeChapter(currentChapter); }else{ mStatus = Status.FAIL; drawStatus(mBookPageWidget.getCurPage()); drawStatus(mBookPageWidget.getNextPage()); } }else if(msg.what==2){ mStatus = Status.FINISH; Log.d(TAG, String.format("prepare book ready to open currentChapter %s ",currentChapter ) ); drawStatus(mBookPageWidget.getCurPage()); drawStatus(mBookPageWidget.getNextPage()); changeChapter(currentChapter,tmpChaptPages); pageFactory.setBusy(false); } } Map fileRetryCnt = new HashMap(); private List loadCurrentChapt(int chaptId){ Log.d(TAG, String.format("prepare book, loadCurrentChapt chaptId %s, getChapters().size() %s ,currentChapter %s ---------------------------------->",chaptId,getChapters().size() ,currentChapter) ); long startTime= new Date().getTime(); if(tmpChaptPages==null){ tmpChaptPages = new ArrayList(); } tmpChaptPages.clear(); tmpChaptPages.add(new TRPage()); if (fileRetryCnt.containsKey(chaptId)) { fileRetryCnt.put(chaptId, fileRetryCnt.get(chaptId) + 1); } else { fileRetryCnt.clear();//只保留一个章节数据 fileRetryCnt.put(chaptId, 1); } Log.d(TAG, String.format("prepare book loadCurrentChapt %s, rertying count %s ",chaptId, fileRetryCnt.get(chaptId))); if(fileRetryCnt.get(chaptId) > Constants.retryCnt){ mStatus = Status.FAIL; drawStatus(mBookPageWidget.getCurPage()); drawStatus(mBookPageWidget.getNextPage()); return tmpChaptPages; } mStatus = Status.OPENING; drawStatus(mBookPageWidget.getCurPage()); drawStatus(mBookPageWidget.getNextPage()); final File file = new File(getChapterFileName(chaptId)); if (!file.exists()) { //待下载 chaptId = chaptId > getChapters().size() ? getChapters().size() : chaptId; chaptId = chaptId > 0 ? chaptId : 1; } final int chid = chaptId; if(!mBook.isLocalBook()) { /* mStatus = Status.OPENING; drawStatus(mBookPageWidget.getCurPage()); drawStatus(mBookPageWidget.getNextPage());*/ // final File file = new File(getChapterFileName(chaptId)); Log.d(TAG, String.format("prepare book to open chapter %s ,file is exist ? %s",chaptId,file.exists() ) ); if (!file.exists()) { mStatus = Status.OPENING; if( !NetUtil.isNetworkConnected()){ //TODO: 500错误处理 mStatus = Status.NETWORKFAILE; drawStatus(mBookPageWidget.getCurPage()); drawStatus(mBookPageWidget.getNextPage()); return tmpChaptPages; } if(getChapters().size()==0 && mBookUtil.muluRetryCount>=Constants.retryCnt) { Log.d(TAG, String.format("prepare book download mulu 失败,重试次数: %s ,thread.name %s",mBookUtil.muluRetryCount,Thread.currentThread().getName() ) ); mBookUtil.muluRetryCount=0; mStatus = Status.FAIL; drawStatus(mBookPageWidget.getCurPage()); drawStatus(mBookPageWidget.getNextPage()); return tmpChaptPages; } // showProgressDialog(); new Thread() { @Override public void run() { Log.d(TAG, String.format("prepare book to download chapter %s ,thread.name %s",chid,Thread.currentThread().getName() ) ); mBookUtil.chaptChars(chid); super.run(); }}.start(); new Thread() { @Override public void run() { int slepttime =0; while( !file.exists() && slepttime <60 && mBookUtil.muluRetryCount=Constants.retryCnt){ mStatus = Status.FAIL; } Log.d(TAG, String.format("prepare book to download chapter %s ,handler notice changeChapter %s",chid, currentChapter ) ); //notice file done handler.sendEmptyMessage(1); super.run(); }}.start(); drawStatus(mBookPageWidget.getCurPage()); drawStatus(mBookPageWidget.getNextPage()); return tmpChaptPages; } } pageFactory.setBusy(true); // chaptId = mChapters!=null && mChapters.size() <= chaptId ? 1 : chaptId; new Thread() { @Override public void run() { super.run(); Log.d(TAG, String.format("changing Source prepare book to open chapter %s, currentChapter %s ",chid ,currentChapter ) ); long time1 =new Date().getTime() - startTime; Log.d(TAG, "loadCurrentChapt: time1: " +time1); // startTime = new Date().getTime(); char[] chars = mBookUtil.chaptChars(chid); long time2 =new Date().getTime() - startTime; Log.d(TAG, "loadCurrentChapt: time2: " +time2); // String s = new String(chars); // Log.d(TAG, String.format("prepare book open chapter %s,chars %s ",chaptId ,s ) ); mBookUtil.setBookLen(chars.length); mBookUtil.setChapterNo(chid); // TRPage page = new TRPage(); tmpChaptPages.clear(); long length =0; int pageNo =0; while(length m_lines,Boolean updateChapter) { mAd.hideSystemUI(); if(m_lines.size()==0){ return; } // Log.d(TAG, String.format(" prepare book onDraw chapter %s, getChapters().size() %s ",currentChapter ,getChapters().size() ) ); if (getChapters().size() > 0 && updateChapter) { // Log.d(TAG, String.format(" prepare book onDraw chapter to getCurrentChapter(),currentChapter %s ",currentChapter ) ); currentChapter = getCurrentChapter(); // Log.d(TAG, String.format(" prepare book onDraw chapter after getCurrentChapter(),currentChapter %s ",currentChapter ) ); } // Log.d(TAG, String.format(" prepare book onDraw chapter _____________ %s ",currentChapter ) ); //更新数据库进度 if ( mStatus ==Status.FINISH && currentPage != null && mBook != null){ new Thread() { @Override public void run() { super.run(); if(mBook.getLastReadChapt() !=currentChapter || mBook.getLastReadPos()!=currentPage.getBegin()) { if(currentChapter >1) { mBook.setLastReadChapt(currentChapter); }else{ mBook.setToDefault("lastReadChapt"); } mBook.setLastReadPos(currentPage.getBegin()); mBook.update(mBook.getId()); //If you set a default value to a field, the corresponding // * column won't be updated. // mBook.save(); /*Novel nv = LitePal.find(Novel.class,mBook.getId()); Log.d(TAG,String.format("prepare book saved lastchapt %s,lastpos %s, db lastchapt %s last pos %s", currentChapter,currentPage.getBegin(),nv.getLastReadChapt(),nv.getLastReadPos())); */ } /* values.put("lastReadPos",currentPage.getBegin()); values.put("lastReadChapt",currentChapter); Log.d(TAG,String.format("begin to update book %s chapter%s bigin %s ",mBook.getName(),currentChapter, currentPage.getBegin() ) ); int rows = LitePal.update(Novel.class,values,mBook.getId()); Log.d(TAG,String.format("update book %s chapter%s bigin %s, result %s",mBook.getName(),currentChapter, currentPage.getBegin(),rows) ); */ } }.start(); } Canvas c = new Canvas(bitmap); c.drawBitmap(getBgBitmap(), 0, 0, null); // word.setLength(0); mPaint.setTextSize(getFontSize()); mPaint.setColor(getTextColor()); mBatterryPaint.setColor(getTextColor()); if (m_lines.size() == 0) { return; } float space =m_fontSize + lineSpace; paragraphSpace = prate * lineSpace; if (m_lines.size() > 0) { float y = marginHeight; String lastLine =""; for (String strLine : m_lines) { // if(strLine.endsWith("\n")) { // if(strLine.charAt(strLine.length()-1) == ('\n' )) { // Log.d(TAG, strLine); // Log.d(TAG,"最后字符 。。。" +strLine.charAt(strLine.length()-1) + ""); lastLine =strLine; if(( strLine.charAt(strLine.length()-1) + "" ).equals("\n")){ strLine =strLine.replace("\n",""); y += space; space =m_fontSize + paragraphSpace; // Log.d( TAG ,String.format("prepare book 开始新段落 %s, y plus is %s" ,strLine, m_fontSize + paragraphSpace)); }else{ y += space; space =m_fontSize + lineSpace; // Log.d(TAG,String.format("prepare book %s,y plus is %s" ,strLine, m_fontSize + lineSpace)); } c.drawText(strLine, measureMarginWidth, y, mPaint); // word.append(strLine); } // Log.d(TAG,String.format("getNavigationBarSize mHeight is %s ,last line height %s, power %s, %s", // mHeight,y,mHeight - CommonUtil.convertDpToPixel(mContext,10) + mBorderWidth - statusMarginBottom, lastLine)); float adHeight = mHeight -y - space -marginHeight-statusMarginBottom; float adY =y +space; showAd((int)adHeight,(int)adY); // Log.d(TAG,String.format("ad + statusMarginBottom %s ",200+ statusMarginBottom)); // Log.d(TAG,String.format("adHeight %s, adY %s",adHeight,adY)); } //画进度及时间 int dateWith = (int) (mBatterryPaint.measureText(date)+mBorderWidth);//时间宽度 // float fPercent = (float) (currentPage.getBegin() * 1.0 / mBookUtil.getBookLen());//进度 float fPercent = (float) (currentPage.getPageNo() * 1.0 /currentChaptPages.size());//进度 currentProgress = fPercent; if (mPageEvent != null){ mPageEvent.changeProgress(fPercent); } // String strPercent = df.format(fPercent * 100) + "%";//进度文字 String strPercent = String.format("%s/%s",currentPage.getPageNo(),currentChaptPages.size()) + "页";//进度文字 int nPercentWidth = (int) mBatterryPaint.measureText("10/25页") + 50; //Paint.measureText直接返回參數字串所佔用的寬度 float botoomY =mHeight - statusMarginBottom;// +screenHeihtDiff; c.drawText(strPercent, mWidth - nPercentWidth, botoomY, mBatterryPaint);//x y为坐标值 c.drawText(date, marginWidth ,botoomY, mBatterryPaint); // 画电池 level = batteryInfoIntent.getIntExtra( "level" , 0 ); int scale = batteryInfoIntent.getIntExtra("scale", 100); mBatteryPercentage = (float) level / scale; float rect1Left = marginWidth + dateWith + statusMarginBottom;//电池外框left位置 //画电池外框 float width = CommonUtil.convertDpToPixel(mContext,20) - mBorderWidth; float height = CommonUtil.convertDpToPixel(mContext,10); rect1.set(rect1Left, botoomY - height ,rect1Left + width, botoomY); rect2.set(rect1Left + mBorderWidth, botoomY - height + mBorderWidth , rect1Left + width - mBorderWidth, botoomY - mBorderWidth ); // c.save(Canvas.CLIP_SAVE_FLAG); c.save(); c.clipRect(rect2, Region.Op.DIFFERENCE); c.drawRect(rect1, mBatterryPaint); c.restore(); //画电量部分 rect2.left += mBorderWidth; rect2.right -= mBorderWidth; rect2.right = rect2.left + rect2.width() * mBatteryPercentage; rect2.top += mBorderWidth; rect2.bottom -= mBorderWidth; c.drawRect(rect2, mBatterryPaint); //画电池头 int poleHeight = (int) CommonUtil.convertDpToPixel(mContext,10) / 2; rect2.left = rect1.right; rect2.top = rect2.top + poleHeight / 4; rect2.right = rect1.right + mBorderWidth; rect2.bottom = rect2.bottom - poleHeight/4; c.drawRect(rect2, mBatterryPaint); //画书名 c.drawText(CommonUtil.subString(bookName,12), marginWidth ,statusMarginBottom + mBatterryFontSize, mBatterryPaint); //画章 /* String chapterName =""; if(mCurrentChapter!=null){ chapterName = mCurrentChapter.getChapterName(); }else*/ if (getChapters().size() > 0) { String chapterName = CommonUtil.subString(getChapterName(),16); int nChaterWidth = (int) mBatterryPaint.measureText(chapterName) + 1; c.drawText(chapterName, mWidth - marginWidth - nChaterWidth, statusMarginBottom + mBatterryFontSize, mBatterryPaint); } mBookPageWidget.postInvalidate(); } private void showAd(int adHeight,int adY) { boolean showAd = getCurrentPage().getPageNo() > 2 &&NetWorkUtil.isNetworkConnected(mContext); if (mAd != null) { mAd.showAd(showAd,adHeight, adY); } } //向前翻页 public void prePage(){ if(null == currentPage){ return; } if(mBookUtil.isBusy()){ return; } m_isfirstPage = false; if (currentPage.getBegin() <= 1) { Log.d(TAG,"当前是本章第一页"); m_isfirstPage =currentChapter ==1; if ( m_isfirstPage){ Toast.makeText(mContext, "当前是第一页", Toast.LENGTH_SHORT).show(); return; } } Log.d(TAG, "prepare book prePage: to open prepage: "); cancelPage = currentPage; onDraw(mBookPageWidget.getCurPage(),currentPage.getLines(),true); currentPage = getPrePage(); onDraw(mBookPageWidget.getNextPage(),currentPage.getLines(),true); } //向后翻页 public void nextPage(){ m_islastPage = false; if(null == currentPage){ return; } if(mBookUtil.isBusy()){ return; } if (currentPage.getEnd() >= mBookUtil.getBookLen()) { Log.d(TAG,"已经是本章最后一页了"); m_islastPage =currentChapter == mBookUtil.getChapters().size(); if ( m_islastPage){ Toast.makeText(mContext, "已经是最后一页了", Toast.LENGTH_SHORT).show(); return; } else { } } // Log.d(TAG, "prepare book nextPage: to open next page: "); cancelPage = currentPage; onDraw(mBookPageWidget.getCurPage(),currentPage.getLines(),true); prePage = currentPage; currentPage = getNextPage(); // currentPage = currentChaptPages.get(currentPage.getPageNo()-1); onDraw(mBookPageWidget.getNextPage(),currentPage.getLines(),true); Log.d("nextPage","nextPagenext"); } //取消翻页 public void cancelPage(){ if(cancelPage !=null && (cancelPage.isLastPage() || cancelPage.isFirstPage())){ //TODO:待测试 mBookUtil.setChapterNo(cancelPage.getChapterNo()); // openBookPosition = cancelPage.getBegin(); Log.d(TAG, "cancelPage: cancelPage is LastPage? " +cancelPage.isLastPage() ); Log.d(TAG, String.format("cancelPage:cancelPage.getBegin() %s, cancelPage.getPageno() %s, preChaptPages is null? %s, nextChaptPages is null %s", cancelPage.getBegin() ,cancelPage.getPageNo(),preChaptPages ==null,nextChaptPages==null )); if(cancelPage.isLastPage()){ currentChaptPages = nextChaptPages; }else{ currentChaptPages = preChaptPages; } // currentChaptPages = loadCurrentChapt(cancelPage.getChapterNo()); currentPage = getPageForBegin(cancelPage.getBegin()) ;// currentChaptPages.get(0); // currentPage = getPageForBegin(begin); if (mBookPageWidget != null) { // currentPage(true); } } currentPage = cancelPage; } public void prepareBook(Novel book){ Log.d(TAG, "prepare book: start prepare book " + book.getName()); if(mBook!=null &&mBook.getNovelId() !=book.getNovelId()){ //取消未上本书完成的web请求,待验证效果 try { NetUtil.cancelRequest(mBook.getNovelId() ); }catch (Exception e) { Log.e(TAG, "prepare book: error on canceling request "+e.getMessage()); e.printStackTrace(); } } this.mBook = book ; mBookUtil = new BookUtil(); //this.mBookUtil.setContext(context); this.mBookUtil.setNovel(book); this.mBookUtil.getTargetSites(); } /** * 打开书本 * @throws IOException */ public void openBook(Novel book ,Context context) throws IOException { if(book.isLocalBook() || mBookUtil==null){ //离线书籍重新初始化加载mBookUtil mBookUtil = new BookUtil(); } mBookUtil.setContext(context); mContext =context; mBookUtil.pagefactory=this; //清空数据 currentChapter = 0; // m_mbBufLen = 0; initBg(config.getDayOrNight()); if(mBook!=null &&mBook.getNovelId() !=book.getNovelId()){ //取消未上本书完成的web请求 NetUtil.cancelRequest(mBook.getNovelId() ); } this.mBook = book ; bookPath = mBook.getNovelPath(); bookName =mBook.getName();// FileUtils.getFileName(bookPath); openBookPosition = mBook.getLastReadPos(); // this.mCurrentChapter = chapter; mStatus = Status.OPENING; drawStatus(mBookPageWidget.getCurPage()); drawStatus(mBookPageWidget.getNextPage()); if (bookTask != null && bookTask.getStatus() != AsyncTask.Status.FINISHED){ bookTask.cancel(true); } bookTask = new BookTask(); Log.d(TAG, String.format("prepare book 1 to open chapter %s ",book.getLastReadChapt() ) ); bookTask.execute((long)book.getLastReadChapt(),book .getLastReadPos()); } private class BookTask extends AsyncTask{ private long chapter=0; // private long begin = 0; @Override protected void onPostExecute(Boolean result) { super.onPostExecute(result); Log.d("onPostExecute",isCancelled() + ""); if (isCancelled()){ return; } if (result) { Log.d(TAG, String.format("prepare book ready, to open chapter %s ",chapter ) ); // m_mbBufLen = mBookUtil.getBookLen(); mBookUtil.setChapterNo((int)chapter); Log.d(TAG, String.format("prepare book ready, to open chapter, loadCurrentChapt %s ",chapter ) ); loadCurrentChapt((int)chapter); /* currentChaptPages = loadCurrentChapt((int)chapter); currentPage = getPageForBegin(begin) ;// currentChaptPages.get(0); if (mBookPageWidget != null) { currentPage(true); }*/ // Log.d(TAG, String.format("prepare book set PageFactory.mStatus %s .",PageFactory.Status.FINISH ) ); // PageFactory.mStatus = PageFactory.Status.FINISH; }else{ PageFactory.mStatus = PageFactory.Status.FAIL; drawStatus(mBookPageWidget.getCurPage()); drawStatus(mBookPageWidget.getNextPage()); Toast.makeText(mContext,"打开书本失败!",Toast.LENGTH_SHORT).show(); } } @Override protected void onPreExecute() { super.onPreExecute(); } @Override protected void onProgressUpdate(Void... values) { super.onProgressUpdate(values); } @Override protected Boolean doInBackground(Long... params) { chapter = params[0]; //begin = params[1]; currentChapter = (int) chapter; try { mBookUtil.openBook(mBook,chapter); } catch (Exception e) { e.printStackTrace(); return false; } return true; } } public TRPage getNextPage(){ int nextPageNo =currentPage.getPageNo(); Log.e(TAG,String.format("prepare book getNextPage() currentChapter %s, currentChaptPages .size() is %s,currentpage pageno is %s" ,currentChapter, currentChaptPages.size() ,currentChapter, nextPageNo)); if(nextPageNo >= currentChaptPages.size()){ preChaptPages =currentChaptPages; currentChapter++; mBookUtil.setChapterNo(currentChapter); isShowPrePage = false; currentChaptPages = loadCurrentChapt(currentChapter ) ; nextPageNo =0; } return currentChaptPages.get(nextPageNo); } public TRPage getPrePage(){ int prePageNo =currentPage.getPageNo()-1; Log.d(TAG,String.format("currentPageno %s,total pagno %s",currentPage.getPageNo(),currentChaptPages.size())); if(prePageNo <=0){ nextChaptPages =currentChaptPages; currentChapter--; if(currentChapter ==0) { return new TRPage("没有内容了"); } mBookUtil.setChapterNo(currentChapter); isShowPrePage = true; currentChaptPages = loadCurrentChapt(currentChapter ) ; prePageNo = currentChaptPages.size(); } return currentChaptPages.get(prePageNo-1); } public TRPage getPageForBegin(long begin){ /* TRPage trPage = new TRPage(); trPage.setBegin(begin); mBookUtil.setPostition(begin - 1); trPage.setLines(getNextLines()); trPage.setEnd(mBookUtil.getPosition()); return trPage; */ Log.d(TAG, String.format("prepare book getPageForBegin: chaptid %s, begin %s ",currentChapter,begin)); for(TRPage page : currentChaptPages) { if(page.getEnd() >begin){ return page; } } //return new TRPage();// currentChaptPages.get(currentChaptPages.size()-1); return currentChaptPages.get(currentChaptPages.size()-1); } boolean showChapTitleOnTopWhenNextPage =false; public List getNextLines(){ List lines = new ArrayList<>(); float width = 0; float height = 0; String line = ""; if(mBookUtil.getPosition()==0) { lines.add("\n");lines.add("\n"); } calculateLineCount(); while (mBookUtil.next(true) != -1){ char word = (char) mBookUtil.next(false); //判断是否换行 if ((word + "" ).equals("\n") ){// if ((word + "" ).equals("\r") && (((char) mBookUtil.next(true)) + "").equals("\n")){ // mBookUtil.next(false); if ( !line.isEmpty()){ if (showChapTitleOnTopWhenNextPage && lines.size() >0 && mBookUtil.isChapterTitle(line)) { Log.d(TAG,String.format("title is %s\n,size is %s ,position is %s" ,line,line.length(),mBookUtil.getPosition() )); break; } lines.add(line+word); // lines.add("\n"); line = ""; width = 0; height += paragraphSpace - lineSpace; calculateLineCount(height); if (lines.size()>= mLineCount){ // Log.d(TAG,String.format("lines count limit a %s,lines size %s",mLineCount,lines.size())); line =""; break; } } }else { float widthChar = mPaint.measureText(word + ""); width += widthChar; if (width > mVisibleWidth) { width = widthChar; lines.add(line); /* if (lines.size() == mLineCount){ Log.d(TAG,String.format("lines count limit b %s,lines size %s",mLineCount,lines.size())); line =""; break; } */ line = word + ""; } else { line += word; } } if (lines.size() == mLineCount){ // Log.d(TAG,String.format("lines count limit c %s,lines size %s",mLineCount,lines.size())); if (!line.isEmpty()){ // mBookUtil.setPostition(mBookUtil.getPosition() - line.length()-2);// mBookUtil.setPostition(mBookUtil.getPosition() - 1); mBookUtil.setPostition(mBookUtil.getPosition() - 1); } break; } } /* if (lines.size() == mLineCount) { Log.d(TAG, String.format("lines count limit d %s,lines size %s", mLineCount, lines.size())); Log.d(TAG, String.format("lines count limit d %s,line is \n %s", mLineCount, line)); if (!line.isEmpty()) { mBookUtil.setPostition(mBookUtil.getPosition() - line.length() - 2);// mBookUtil.setPostition(mBookUtil.getPosition() - 1); } }*/ if (!line.isEmpty() && lines.size() < mLineCount){ if (!(showChapTitleOnTopWhenNextPage && mBookUtil.isChapterTitle(line) ) ) { lines.add(line); }else { // mBookUtil.setPostition(mBookUtil.getPosition() - line.length()-2); } // lines.add(line); } /*for (String str : lines){ Log.d(TAG,str + " "); }*/ return lines; } public List getPreLines(){ List lines = new ArrayList<>(); float width = 0; String line = ""; char[] par = mBookUtil.preLine(); while (par != null){ List preLines = new ArrayList<>(); for (int i = 0 ; i < par.length ; i++){ char word = par[i]; float widthChar = mPaint.measureText(word + ""); width += widthChar; if (width > mVisibleWidth) { width = widthChar; preLines.add(line); line = word + ""; } else { line += word; } // Log.d(TAG,"preLine is \n" + line); } /* if ( mBookUtil.isChapterTitle(line)) { mBookUtil.setPostition(mBookUtil.getPosition() - line.length()-2); break; }*/ // lines.add(line); // Log.d(TAG,"preLine is \n" + line); if (!line.isEmpty()){ preLines.add(line); } lines.addAll(0,preLines); if (lines.size() >= mLineCount){ break; } width = 0; line = ""; par = mBookUtil.preLine(); } List reLines = new ArrayList<>(); int num = 0; for (int i = lines.size() -1;i >= 0;i --){ if (reLines.size() < mLineCount) { reLines.add(0,lines.get(i)); }else{ num = num + lines.get(i).length(); } Log.d(TAG,lines.get(i) + " "); } if (num > 0){ if ( mBookUtil.getPosition() > 0) { mBookUtil.setPostition(mBookUtil.getPosition() + num + 1);//mBookUtil.setPostition(mBookUtil.getPosition() + num + 2); // /r/n -> /n,只需要回退1个字符 }else{ mBookUtil.setPostition(mBookUtil.getPosition() + num ); } } return reLines; } //上一章 public void preChapter(){ fileRetryCnt.clear(); if(currentChapter==1){ Toast.makeText(mContext,"到头了",Toast.LENGTH_SHORT).show(); } // if (mBookUtil.getChapters().size() > 0 ){ int num = currentChapter; if (num ==1){ num = getCurrentChapter(); } num --; if (num >= 1){ nextChaptPages =currentChaptPages; currentChapter = num; mBookUtil.setChapterNo(currentChapter); currentChaptPages = loadCurrentChapt(currentChapter ) ; // currentPage = getPageForBegin(0); // currentPage(true); } } //} //下一章 public void nextChapter(){ fileRetryCnt.clear(); int num = currentChapter; if (num == 0){ num = getCurrentChapter(); } if(num==getChapters().size()){ Toast.makeText(mContext,"没有了",Toast.LENGTH_SHORT).show(); } num ++; if (num <= getChapters().size() || mBookUtil.chaptCached(num)){ preChaptPages =currentChaptPages; currentChapter = num; mBookUtil.setChapterNo(currentChapter); currentChaptPages = loadCurrentChapt(currentChapter ) ; // currentPage = getPageForBegin(0); // currentPage(true); } } //获取现在的章 public int getCurrentChapter(){ /*int num = 0; for (int i = 0;getDirectoryList().size() > i;i++){ Chapter bookCatalogue = getDirectoryList().get(i); if (currentPage.getEnd() >= bookCatalogue.getBookChapterStartPos()){ num = i; }else{ break; } } return num; */ currentChapter = mBookUtil.getChapterNo(); // Log.d(TAG, String.format(" prepare book onDraw chapter after mBookUtil.getChapterNo(),currentChapter %s ",currentChapter ) ); return currentChapter ; } //绘制当前页面 public void currentPage(Boolean updateChapter){ // Log.d(TAG, "prepare book currentPage: to open current Page : "); onDraw(mBookPageWidget.getCurPage(),currentPage.getLines(),updateChapter); onDraw(mBookPageWidget.getNextPage(),currentPage.getLines(),updateChapter); } //更新电量 public void updateBattery(int mLevel){ mAd.hideSystemUI(); if (currentPage != null && mBookPageWidget != null && !mBookPageWidget.isRunning()) { if (level != mLevel) { level = mLevel; currentPage(false); } } } public void updateTime(){ mAd.hideSystemUI(); if (currentPage != null && mBookPageWidget != null && !mBookPageWidget.isRunning()) { String mDate = sdf.format(new java.util.Date()); if (date != mDate) { date = mDate; currentPage(false); } } } //改变进度 public void changeProgress(float progress){ long begin = (long) (mBookUtil.getBookLen() * progress); currentPage = getPageForBegin(begin); currentPage(true); } private void changeChapter(int chapNum, List chaptPages){ if (mBook == null) { return; } //preChaptPages =currentChaptPages; currentChapter = chapNum; mBookUtil.setChapterNo(currentChapter); currentChaptPages = chaptPages ; if(isShowPrePage) { currentPage = currentChaptPages.get(currentChaptPages.size()-1); }else { currentPage = getPageForBegin(openBookPosition); } openBookPosition =0;//初次打开书本定位到上次读书位置,以后章节切换就定位到章节首页 currentPage(true); } //改变章节 public void changeChapter(int chapNum){ if (mBook == null) { return; } // preChaptPages =currentChaptPages; currentChapter = chapNum; mBookUtil.setChapterNo(currentChapter); currentChaptPages = loadCurrentChapt(currentChapter ) ; // currentPage = getPageForBegin(0); // currentPage(true); } public void openBookmark(int chapNum,long position){ //preChaptPages =currentChaptPages; currentChapter = chapNum; mBookUtil.setChapterNo(currentChapter); currentChaptPages = loadCurrentChapt(currentChapter ) ; openBookPosition = position; // currentPage = getPageForBegin(position); // currentPage(true); } //改变行间距 public void changeLineHight(int lineSpace) { this.lineSpace = lineSpace; mPaint.setTextSize(m_fontSize); calculateLineCount(); measureMarginWidth(); currentChaptPages = loadCurrentChapt(currentChapter ); openBookPosition = currentPage.getBegin(); // currentPage = getPageForBegin(currentPage.getBegin()); // currentPage(true); } //改变字体大小 public void changeFontSize(int fontSize){ this.m_fontSize = fontSize; mPaint.setTextSize(m_fontSize); calculateLineCount(); measureMarginWidth(); currentChaptPages = loadCurrentChapt(currentChapter ); openBookPosition = currentPage.getBegin(); // currentPage = getPageForBegin(currentPage.getBegin()); // currentPage(true); } //改变字体 public void changeTypeface(Typeface typeface){ this.typeface = typeface; mPaint.setTypeface(typeface); mBatterryPaint.setTypeface(typeface); calculateLineCount(); measureMarginWidth(); //openBookPosition = currentPage.getBegin(); currentPage = getPageForBegin(currentPage.getBegin()); currentPage(true); } //改变背景 public void changeBookBg(int type){ setBookBg(type); currentPage(false); } //设置页面的背景 public void setBookBg(int type){ Bitmap bitmap = Bitmap.createBitmap(mWidth,mHeight, Bitmap.Config.RGB_565); Canvas canvas = new Canvas(bitmap); int color = 0; switch (type){ case Config.BOOK_BG_DEFAULT: canvas = null; bitmap.recycle(); if (getBgBitmap() != null) { getBgBitmap().recycle(); } bitmap = BitmapUtil.decodeSampledBitmapFromResource( mContext.getResources(), R.drawable.paper, mWidth, mHeight); color = mContext.getResources().getColor(R.color.read_font_default); setBookPageBg(mContext.getResources().getColor(R.color.read_bg_default)); break; case Config.BOOK_BG_1: canvas.drawColor(mContext.getResources().getColor(R.color.read_bg_1)); color = mContext.getResources().getColor(R.color.read_font_1); setBookPageBg(mContext.getResources().getColor(R.color.read_bg_1)); break; case Config.BOOK_BG_2: canvas.drawColor(mContext.getResources().getColor(R.color.read_bg_2)); color = mContext.getResources().getColor(R.color.read_font_2); setBookPageBg(mContext.getResources().getColor(R.color.read_bg_2)); break; case Config.BOOK_BG_3: canvas.drawColor(mContext.getResources().getColor(R.color.read_bg_3)); color = mContext.getResources().getColor(R.color.read_font_3); if (mBookPageWidget != null) { mBookPageWidget.setBgColor(mContext.getResources().getColor(R.color.read_bg_3)); } break; case Config.BOOK_BG_4: canvas.drawColor(mContext.getResources().getColor(R.color.read_bg_4)); color = mContext.getResources().getColor(R.color.read_font_4); setBookPageBg(mContext.getResources().getColor(R.color.read_bg_4)); break; } setBgBitmap(bitmap); //设置字体颜色 setM_textColor(color); } public void setBookPageBg(int color){ if (mBookPageWidget != null) { mBookPageWidget.setBgColor(color); } } //设置日间或者夜间模式 public void setDayOrNight(Boolean isNgiht){ initBg(isNgiht); currentPage(false); } public void clear(){ Log.d(TAG, String .format("prepare Book: clearing book info %s" , getNovle().getName())); fileRetryCnt.clear(); //mBookUtil=null; currentChapter = 0; bookPath = ""; bookName = ""; mBook = null; mBookPageWidget = null; mPageEvent = null; cancelPage = null; prePage = null; currentPage = null; currentChaptPages =null; // preChaptPages=null; // nextChaptPages=null; } public static Status getStatus(){ return mStatus; } public long getBookLen(){ return mBookUtil.getBookLen(); } public TRPage getCurrentPage(){ return currentPage; } //获取书本的章 public List getChapters(){ return mBookUtil.getChapters(); } public boolean isReadingCatalogs(){ return mBookUtil.isReadingCatalogs(); } public String getBookPath(){ return bookPath; } public String getBookName(){ return getNovle().getName(); } public Novel getNovle(){ return mBookUtil.getNovel(); } public boolean isWorking(){ return mBookUtil !=null; } //是否是第一页 public boolean isfirstPage() { return m_isfirstPage; } //询问是否可以退出阅读 public boolean canExitSilent(){ return m_islastPage || mStatus==Status.FAIL ||mStatus==Status.NETWORKFAILE || mStatus==Status.SERVERERROR; } //是否是最后一页 public boolean islastPage() { return m_islastPage; } //是否可以翻页 public boolean isReady() { return mStatus==Status.FINISH; } //设置页面背景 public void setBgBitmap(Bitmap BG) { m_book_bg = BG; } //设置页面背景 public Bitmap getBgBitmap() { return m_book_bg; } //设置文字颜色 public void setM_textColor(int m_textColor) { this.m_textColor = m_textColor; } //获取文字颜色 public int getTextColor() { return this.m_textColor; } //获取文字大小 public float getFontSize() { return this.m_fontSize; } public void setPageWidget(PageWidget mBookPageWidget){ this.mBookPageWidget = mBookPageWidget; } public PageWidget getPageWidget( ){ return mBookPageWidget; } public void setPageEvent(PageEvent pageEvent){ this.mPageEvent = pageEvent; } public interface PageEvent{ void changeProgress(float progress); } }