1, layout settings, liearlayout the next three parts, including the novel theme content is a custom view, the proportion is 1:8:1
2, CREATE database table two tables TXT table and page table, two tables for primary foreign key Association
Public class DBHelper extends Sqliteopenhelper {public DBHelper (context context) {Super (context, "read.db" , NULL, 1); } public DBHelper (context context, String name, Sqlitedatabase.cursorfactory factory, int version) {Super (conte XT, name, Factory, version); } @Override public void OnCreate (Sqlitedatabase db) {db.execsql ("CREATE TABLE txt (ID Integer primry key,full _path text,now_page integer,over_flag integer) "); Db.execsql ("CREATE table page (ID integer primary key,txt_id integer,page_num integer,content text)"); } @Override public void Onupgrade (sqlitedatabase db, int oldversion, int newversion) {}} text table<span style= "FONT-SIZE:12PX;" >public class Txtdb {public static void InsertData (String fullPath) {String sql = ' Select id from txt where Full_path=? "; Cursor C = Globals.helper.getReadableDatabase (). Rawquery (SQL, new String[]{fullpath}); if (!c.movetofirst ()) {//If no data exists then insert data sql = "INSERT INTO TXT (id,full_path,now_page,over_flag) VALUES (?,?,?,?)" ; Globals.helper.getWritableDatabase (). Execsql (SQL, new object[]{1,fullpath,1,0}); } c.close (); } public static map<string, object> LoadData (String fullPath) {map<string, object> Map = new Hashma P<> (); String sql = "Select Id,now_page,over_flag from txt where full_path=?"; Cursor C = Globals.helper.getReadableDatabase (). Rawquery (SQL, new String[]{fullpath}); while (C.movetonext ()) {map.put ("txtID", C.getint (0)); Map.put ("Nowpage", C.getint (1)); Map.put ("Overflag", C.getint (2)); } C.close (); return map; } public static void Updateoverflag (String fullPath) {String sql = "Update txt set over_flag=1 where full_path= ?"; Globals.helper.getWritableDatabase (). Execsql (SQL, new Object[]{fullpath}); }}</span>
Table of pages
<span style= "FONT-SIZE:12PX;" >public class Pagedb {private static int pagenum; public static void Insertdate (Map<string, object> Map) {String sql = ' INSERT INTO page (txt_id,page_num,conte NT) VALUES (?,?,?) "; Globals.helper.getWritableDatabase (). Execsql (SQL, New Object[]{map.get ("txtID"), Map.get ("Pagenum"), Map.get (" Content ")}); public static string findcontent (int txtid, int pagenum) {string content = null; String sql = "Select content from page where txt_id=?" and page_num=? "; Cursor C = Globals.helper.getReadableDatabase (). Rawquery (SQL, new String[]{txtid + "", Pagenum + "}); while (C.movetonext ()) {content = c.getstring (0); } c.close (); return content; } public static int findpagenum (int txtid) {String sql= ' select COUNT (*) from page where txt_id=? "; Cursor c= Globals.helper.getReadableDatabase (). Rawquery (Sql,new string[]{txtid+ ""}); while (C.movetonext ()){pagenum=c.getint (0); } c.close (); return pagenum; }}</span>
3, define a globally available class globals , set the contents of the page, the number of words per line, word spacing, line spacing, margins, the screen width and height of the Android device.
public class Globals {public static int screen_width; public static int screen_height; public static int line_char_count=20;//each line displays 20 characters public static int char_sep=2;//word spacing public static int page_sep=5;/ /margins public static int line_sep=2;//line spacing public static int char_size;//character size, to be computed, to ensure that the public static int LI can be adapted to the screen size ne_count;//the number of rows to be displayed per page, calculated. public static void Init (Activity a) {Screen_width=a.getwindowmanager (). Getdefaultdisplay (). getwidth ();//Get screen Width Screen_height=a.getwindowmanager (). Getdefaultdisplay (). GetHeight ();//Get screen height char_size= (screen_width-page_ sep*2-(line_char_count-1) *char_sep)/line_char_count;//calculates the character size line_count=screen_height*4/5/(CHAR_SIZE+LINE_SEP) ;//Calculate the number of rows displayed per page and match the layout, accounting for four-fifths}}4 of the screen, custom MyView, sliding page <pre name= "code" class= "Java" >public class MyView extends View { Private String content; Private Mainactivity A; private float StartX; private float nowx; Private String precontent;//The contents of the previous and next pages pRivate String nextcontent; Public MyView (Context context) {super (context); } public MyView (context context, AttributeSet Attrs) {Super (context, attrs); A = (mainactivity) context; This.setonclicklistener (New Onclicklistener () {@Override public void OnClick (View v) {} }); This.setontouchlistener (New Ontouchlistener () {@Override public boolean onTouch (View V, motionevent Event) {if (event.getaction () = = Motionevent.action_down) {StartX = Event.getx (); } else if (event.getaction () = = Motionevent.action_move) {nowx = Event.getx (); Postinvalidate ();//re-call the OnDraw method} else if (event.getaction () = = motionevent.action_up) { if (Math.Abs (NOWX-STARTX) >=) {//NOWX and StartX have an absolute value greater than 50, the page turn if (nowx > Start X) {//Previous page if (A.getnowpagenum () > 1) {a.setnowpagenum (A.getnowpagenum ()-1);//Turn to previous page Changedata (); }} if (Nowx < StartX) {//Next page if (a.getnowpage Num () < A.getpagenum ()) {A.setnowpagenum (A.getnowpagenum () + 1);//Turn to next page Changedata (); }}} StartX = 0; nowx = 0; } return false; } }); } public MyView (context context, AttributeSet attrs, int defstyleattr) {Super (context, attrs, defstyleattr); public void Changedata () {content = pagedb.findcontent ((int) a.gettxtmap (). Get ("txtID"), A.getnowpagenum ()); if (A.getnowpagenum () > 1) {//The current page is not the first page precontent = Pagedb.findContent ((int) a.gettxtmap (). Get ("txtID"), A.getnowpagenum ()-1); } else {precontent = null; } if (A.getnowpagenum () < A.getpagenum ()) {//The current page is not the last page nextcontent = pagedb.findcontent (int) A.gettx TMap (). Get ("txtID"), A.getnowpagenum () + 1); } else {nextcontent = null; } a.gethandler (). Sendemptymessage (1); Super.postinvalidate ();//Call OnDraw method;} @Override protected void OnDraw (canvas canvas) {Super.ondraw (Canva s); if (content! = null) {string[] allvalues = Content.split (Globals.end_flag); for (int i = 0; i < allvalues.length; i++.) {for (int j = 0; J < Allvalues[i].length (), j + +) { if (j + i * Globals.char_line_conut < Content.length ()) {Paint paint = new Paint () ; Paint.setcolor (Color.Black); Paint.settextsize (globals.char_size); Canvas.drawtext (String.valueof (Allvalues[i].charat (j)), Globals.page_sep + J * (Globals . char_size + globals.char_sep) + (NOWX-STARTX), I * (Globals.char_size + globals.line_sep), Paint); }}}} if (Nowx > StartX && precontent! = null) {string[] Allvalues = Precontent.split (Globals.end_flag); for (int i = 0; i < allvalues.length; i++.) {for (int j = 0; J < Allvalues[i].length (), j + +) { if (j + i * Globals.char_line_conut < Content.length ()) {Paint paint = new Paint () ; Paint.setcolor (Color.Black); Paint.settextsize (globals.char_size); Canvas.drawtext (String.valueof (Allvalues[i].charat (j)), Globals.page_sep + J * (Globals.cha R_size + globals.char_sep) + (NOWX-STARTX)-Globals.screen_width, I * (Globals.char_size + globals.line_sep), paint); }}}} if (Nowx < StartX && nextcontent! = null) {Strin g[] allvalues = Nextcontent.split (Globals.end_flag); for (int i = 0; i < allvalues.length; i++.) {for (int j = 0; J < Allvalues[i].length (), j + +) { if (j + i * Globals.char_line_conut < Content.length ()) {Paint paint = new Paint () ; Paint.setcolor (Color.Black); Paint.settextsize (globals.char_size); Canvas.drawtext (String.valueof (Allvalues[i].charat (j)), Globals.page_sep + J * (Globals.cha R_size + globals.char_sep) + (NOWX-STARTX) +globals.screen_width, I * (Globals.char_size + G LOBALS.LINE_SEP), paint); } } } } }}
5, the text is stored in the root directory of the SDcard, to the journey to the monkey as a demonstration, get the absolute path of the text, with a character stream to read by line
<pre name= "code" class= "Java" >public class Mainactivity extends appcompatactivity {static MyView contentview; Static TextView PageView; Private map<string, object> Txtmap; Private map<string, object> pagemap = new hashmap<> (); Private StringBuffer sb = new StringBuffer (); private int linecount = 0;//number of rows per page static int pagenum = 1;//total pages static int nowpagenum = 1;//Current page private String Fu Llpath; static Handler Handler = new Handler () {@Override public void Handlemessage (Message msg) {if (M Sg.what = = 0) {pageview.settext ("paging, already decomposed:" + pagenum); } else if (msg.what = = 1) {Pageview.settext ("pagination completed" + Nowpagenum + "/" + pagenum); } } }; @Override protected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate); Globals.init (this); Setcontentview (R.layout.activity_main); Contentview = (MyView) FIndviewbyid (R.id.content_view); PageView = (TextView) Findviewbyid (R.id.page_view); FullPath = Environment.getexternalstoragedirectory (). GetAbsolutePath () + "/xiyouji.txt";//Get File path Txtdb.insertintotx T (FullPath); Txtmap = Txtdb.loadtxtbyfullpath (FullPath); if ((int) txtmap.get ("overflag") = = 0) {//Not yet paged new Thread () {@Override public void Run () {try {bufferedreader br = new BufferedReader (New InputS Treamreader (New FileInputStream (FullPath), "GBK")); String line = null; while (line = Br.readline ())! = null) {while (Line.length () > Globals.char_line_conut) { String str = line.substring (0, Globals.char_line_conut); line = line.substring (globals.char_line_conut); AddLine (str); } addline (line);//lines The remaining insufficient to make a line of words added to a line} Br.close (); Handler.sendemptymessage (1); Txtdb.updateoverflag (FullPath); } catch (Exception e) {e.printstacktrace (); }}}.start (); } else {//has paginated completed pagenum = pagedb.getpagecount ((int) txtmap.get ("txtID")); Nowpagenum = (int) txtmap.get ("Nowpage"); Contentview.changedata (); }} @Override protected void OnDestroy () {Txtdb.updatenowpaga ((int) txtmap.get ("Nowpage"), FullPath); Super.ondestroy (); The public void AddLine (String str) {//rows are formed after the page is placed into the database sb.append (str); Sb.append (Globals.end_flag); linecount++; if (LineCount = = Globals.line_count) {pagemap.put ("txtID", Txtmap.get ("txtID")); Pagemap.put ("pAgenum ", pagenum++); Pagemap.put ("Content", sb.tostring ()); Pagedb.insertintopagedb (PAGEMAP); if (Pagenum = = ten) {contentview.changedata (); } handler.sendemptymessage (0); SB = new StringBuffer (); LineCount = 0;//is initialized again for next cycle} public map<string, Object> Gettxtmap () {return txtmap; } public void Settxtmap (map<string, object> txtmap) {this.txtmap = Txtmap; } public int Getpagenum () {return pagenum; } public void Setpagenum (int pagenum) {this.pagenum = Pagenum; } public int Getnowpagenum () {return nowpagenum; } public void Setnowpagenum (int nowpagenum) {this.nowpagenum = Nowpagenum; } public Handler GetHandler () {return Handler; } public void SetHandler (Handler Handler) {this.handler = Handler; } public map<string, Object> Getpagemap () {return PagEMap; }}
Android Small Project "Fiction reader"