码迷,mamicode.com
首页 > 移动开发 > 详细

安卓小项目【小说阅读器】

时间:2016-05-06 12:37:26      阅读:219      评论:0      收藏:0      [点我收藏+]

标签:

1,布局设置,LiearLayout 上中下三部分,其中小说主题内容部分为自定义view,比例是1:8:1

2,创建数据库表  两张表txt表和page表,两张表进行主外键关联

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(context, 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) {
    }
}
文本表
<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()) {//如果不存在数据则插入数据
            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 HashMap<>();
        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>
分页表
<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,content) 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,定义一个全局可以使用的类Globals ,在里面设置页面内容,每行显示的字数,字间距,行间距,页边距,获得安卓设备的屏幕宽度和高度

public class Globals {
    public static int  SCREEN_WIDTH;
    public static int  SCREEN_HEIGHT;
    public static  int LINE_CHAR_COUNT=20;//每行显示20个字
    public static  int CHAR_SEP=2;//字间距
    public static  int PAGE_SEP=5;//页边距
    public static int LINE_SEP=2;//行间距
    public static  int CHAR_SIZE;//字符大小,需计算,保证能根据屏幕大小自适应
    public static int LINE_COUNT;//每页显示的行数,需计算。

 public static  void init(Activity a){

        SCREEN_WIDTH=a.getWindowManager().getDefaultDisplay().getWidth();//获得屏幕宽度
        SCREEN_HEIGHT=a.getWindowManager().getDefaultDisplay().getHeight();//获得屏幕高度

        CHAR_SIZE=(SCREEN_WIDTH-PAGE_SEP*2-(LINE_CHAR_COUNT-1)*CHAR_SEP)/LINE_CHAR_COUNT;//计算出字符大小
        LINE_COUNT=SCREEN_HEIGHT*4/5/(CHAR_SIZE+LINE_SEP);//计算每页显示的行数,并跟布局相适应,占屏幕的五分之四

    }

}
4,自定义MyView,滑动翻页
<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;//准备上一页和下一页的内容
    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();//重新调用onDraw方法
                } else if (event.getAction() == MotionEvent.ACTION_UP) {
                    if (Math.abs(nowX - startX) >= 50) {//nowX和startX的绝对值大于50 的话才执行翻页
                        if (nowX > startX) {//上一页
                            if (a.getNowPageNum() > 1) {
                                a.setNowPageNum(a.getNowPageNum() - 1);//翻到上一页
                                changeData();
                            }
                        }
                        if (nowX < startX) {//下一页
                            if (a.getNowPageNum() < a.getPageNum()) {
                                a.setNowPageNum(a.getNowPageNum() + 1);//翻到下一页
                                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) {//当前页不是第一页的时候
            preContent = PageDB.findContent((int) a.getTxtMap().get("txtId"), a.getNowPageNum() - 1);
        } else {
            preContent = null;
        }
        if (a.getNowPageNum() < a.getPageNum()) {//当前页不是最后一页
            nextContent = PageDB.findContent((int) a.getTxtMap().get("txtId"),a.getNowPageNum()+ 1);
        } else {
            nextContent = null;
        }
        a.getHandler().sendEmptyMessage(1);
        super.postInvalidate();//调用OnDraw方法;

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        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.char_size + Globals.char_sep) +(nowX-startX) -Globals.screen_width,
                                i * (Globals.char_size + Globals.line_sep), paint);
                    }
                }

            }
        }
        if (nowX < startX && nextContent != null) {
            String[] 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.char_size + Globals.char_sep) +(nowX-startX) +Globals.screen_width,
                                i * (Globals.char_size + Globals.line_sep), paint);
                    }
                }

            }
        }


    }
}


 


5,将文本存放在sdcard的根目录,以西游记作为示范,获得文本的绝对路径,用字符流进行按行读取

<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;//每页的行数
    static int pageNum = 1;//总页数
    static int nowPageNum = 1;//当前页数

    private String fullPath;


    static Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (msg.what == 0) {
                pageView.setText("正在分页,已经分解:" + pageNum);
            } else if (msg.what == 1) {
                pageView.setText("分页已经完成" + 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";//获取文件路径
        TxtDB.insertIntoTxt(fullPath);
        txtMap = TxtDB.loadTxtByFullpath(fullPath);

        if ((int) txtMap.get("overFlag") == 0) {
            //还未进行分页
            new Thread() {
                @Override
                public void run() {
                    try {
                        BufferedReader br = new BufferedReader(new InputStreamReader(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);//行余下的不足以凑成一行的字数添加成一行
                        }
                        br.close();
                        handler.sendEmptyMessage(1);
                        TxtDB.updateOverFlag(fullPath);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }.start();

        } else {
            //已经分页完成
            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();
    }

    public void addLine(String str) {//行凑成页之后存放到数据库中
        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 == 10) {
                contentView.changeData();
            }

            handler.sendEmptyMessage(0);
            sb = new StringBuffer();
            lineCount = 0;//再次初始化供下次循环使用

        }

    }


    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;
    }
}







安卓小项目【小说阅读器】

标签:

原文地址:http://blog.csdn.net/zhm0303/article/details/51328586

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!