test

TXT阅读器

一. 实验内容

1.项目简介

实现一个轻量级文本播放控件,同时内置默认的播放页面

2.目前实现了的功能:

1.欢迎页面
2.书架页面
(1)增加图书
(2)图书重命名
(3)移出单本图书
(4)移出所有图书
(5)书架图书查询
3.阅读页面
(1)目录功能
(2)字体设置与调节。包括大小、是否加粗。
(3)页面风格设置,夜间模式等。
(4)进度跳转与当前进度获取。
(5)章节获取与章节跳转。
(6)可以滑盖翻页与平移翻页切换,支持轻击翻页。
(7)可以进行长按滑动选择复制文字。
(8)自动跳转到上次阅读进度。
4.关于我们

二. 关键代码

1.欢迎页面

(1)activity_welcome.xml

<?xml version="1.0" encoding="utf-8"?>
<com.monke.immerselayout.ImmerseFrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#30000000"
    app:need_immerse="true">

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="fitXY" />

    <com.monke.immerselayout.ImmerseFrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        app:need_immerse="false">

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginBottom="60dp"
            android:orientation="vertical">

            <FrameLayout
                android:layout_width="180dp"
                android:layout_height="31dp"
                android:layout_gravity="center_horizontal">

                <ImageView
                    android:id="@+id/logo"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:scaleType="fitXY"
                    android:src="@drawable/logo"
                    android:transitionName="logo" />
            </FrameLayout>
        </LinearLayout>
    </com.monke.immerselayout.ImmerseFrameLayout>

</com.monke.immerselayout.ImmerseFrameLayout>

(2)WelcomeActivity.java

package hw.txtreader.activity;

import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Handler;
import android.os.Message;
import android.preference.PreferenceManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ImageView;
import com.bumptech.glide.Glide;
import java.io.IOException;
import hw.txtreader.R;
import hw.txtreader.util.HttpUtil;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Response;

public class WelcomeActivity extends AppCompatActivity{

    private ImageView imageView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //隐藏标题栏以及状态栏
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
        setContentView(R.layout.activity_welcome);
        imageView=findViewById(R.id.imageView);
        SharedPreferences preferences= PreferenceManager.getDefaultSharedPreferences(this);
        String bingPic=preferences.getString("bing_Pic",null);
        if(bingPic!=null){
            Glide.with(this).load(bingPic).into(imageView);
        }else {
            loadBingPic();
        }
        handler.sendEmptyMessageDelayed(0,3000);//延迟三秒进入主界面
    }

    private void loadBingPic(){//加载Bing每日一图
        String requestBingPic="http://guolin.tech/api/bing_pic";
        HttpUtil.sendOkHttpRequest(requestBingPic, new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                e.printStackTrace();
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                final String bingPic=response.body().string();
                SharedPreferences.Editor editor=PreferenceManager.getDefaultSharedPreferences(WelcomeActivity.this).edit();
                editor.putString("bing_pic",bingPic);
                editor.apply();
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Glide.with(WelcomeActivity.this).load(bingPic).into(imageView);
                    }
                });
            }
        });
    }
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            getHome();
            super.handleMessage(msg);
        }
    };

    public void getHome(){//跳转页面
        Intent intent = new Intent(WelcomeActivity.this, BookShelfActivity.class);
        startActivity(intent);
        finish();
    }
}
2.书架页面

(1)BookShelfActivity.java(在WelcomeActivity中跳转页面到BookShelfActivity)

package hw.txtreader.activity;

import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.provider.MediaStore;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.SearchView;
import android.view.ContextMenu;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.Toast;

import com.bifan.txtreaderlib.main.TxtConfig;
import com.bifan.txtreaderlib.ui.HwTxtPlayActivity;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import hw.txtreader.R;
import hw.txtreader.bean.BookBean;
import hw.txtreader.dao.BookBeanDao;
import hw.txtreader.dao.DbHelper;

/**
 * 书架页面
 */

/**
 * 从文件中读取文件并将他的url存到数据库
 * 然后在列表就通过url加载这个文件
 */
public class BookShelfActivity extends AppCompatActivity {

    private ListView shelf;//书架
    private SimpleAdapter adapter;//列表适配器
    private List<Map<String, String>> bookBeanList = new ArrayList<>();//书籍列表
    private FloatingActionButton addBook;//从本地导入书籍
    private Boolean Permit = false;
    private final BookBeanDao bookBeanDao = DbHelper.getInstance().getmDaoSession().getBookBeanDao();
    private SearchView search;
    private ImageButton setting;//关于我们

    private static final int MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE = 0x01;

    String[] target = {
            "name",
            "introduce",
            "author"
    };//参数名

    int[] xmlpath = {
            R.id.title,
//      R.id.describe,
//      R.id.author
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_header);
        if (CheckPermission()) {//获取文件操作权限
            Permit = true;
        }

        shelf = findViewById(R.id.shelf);
//        registerForContextMenu(shelf);
        search = findViewById(R.id.search);
        search.setImeOptions(EditorInfo.IME_ACTION_SEARCH);
        search.setIconified(false);
        addBook = findViewById(R.id.ib_add);
        addBook.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                chooseFile(null);//添加书籍
            }
        });

        getdata();//获取列表信息
        shelf.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                String path = bookBeanList.get(position).get("url");
                TxtConfig.saveIsOnVerticalPageMode(BookShelfActivity.this, false);
                HwTxtPlayActivity.loadTxtFile(BookShelfActivity.this, path);
            }
        });
        setting = findViewById(R.id.setting);
        setting.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(BookShelfActivity.this, AboutActivity.class);
                startActivity(intent);
            }
        });
        LongClick();//长按item弹出菜单

        Search();//搜索

    }

    public void getdata() {
        List<BookBean> list = bookBeanDao.loadAll();//获取所有书籍

        bookBeanList.clear();//先清理掉
        if (list.size() > 0) {
            for (BookBean bookBean : list) {//添加数据库的所有书籍
                Map<String, String> map = new HashMap<>();
                map.put("name", bookBean.getName());
//                map.put("introduce", bookBean.getIntroduce());
//                map.put("author", bookBean.getAuthor());
                map.put("url", bookBean.getNoteUrl());
                bookBeanList.add(map);
            }
            adapter = new SimpleAdapter(BookShelfActivity.this, bookBeanList, R.layout.activity_book_shelf_item, target, xmlpath);
            shelf.setAdapter(adapter);
        } else {
            toast("当前没有书籍!");
        }
    }

    public void chooseFile(View view) {//从本机选择文件
        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        intent.setType("text/plain");//设置类型
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        startActivityForResult(intent, 3);
    }

    private Boolean CheckPermission() {
        if (ContextCompat.checkSelfPermission(this,
                Manifest.permission.WRITE_EXTERNAL_STORAGE)
                != PackageManager.PERMISSION_GRANTED) {

            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                    MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE);
            return false;
        }
        return true;
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == Activity.RESULT_OK) {//是否选择,没选择就不会继续
            Uri uri = data.getData();//得到uri,后面就是将uri转化成file的过程。
            String[] pros = {MediaStore.Files.FileColumns.DATA};
            try {
                Cursor cursor = managedQuery(uri, pros, null, null, null);
                int actual_txt_column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
                cursor.moveToFirst();
                String path = cursor.getString(actual_txt_column_index);
                //保存书籍的path
                //更新数据库
                BookBean bookBean = new BookBean();
                bookBean.setNoteUrl(path);
                bookBean.setName(path.trim().substring(path.lastIndexOf("/") + 1));
                bookBean.setChapterUrl(path);
//                bookBean.setAuthor("唐家三少");
//                bookBean.setIntroduce("这是一片斗气的世界,这里没有绚丽的魔法,有的只有强横的斗气...");
                long res = bookBeanDao.insertOrReplace(bookBean);//添加到数据库
                if (res > 0) {
                    getdata();
                    toast("添加成功!");
                } else
                    toast("添加失败!");
            } catch (Exception e) {
                toast("选择出错了!");
            }
        }
    }


    public void LongClick() {//长按菜单操作
        shelf.setOnCreateContextMenuListener(new View.OnCreateContextMenuListener() {
            @Override
            public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
                menu.add(0, 0, 0, "重命名");
                menu.add(0, 1, 0, "移出书架");
                menu.add(0, 2, 0, "移出所有");
            }
        });
    }

    @Override
    public boolean onContextItemSelected(MenuItem item) {
        //获取当前
        final AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item
                .getMenuInfo();
        String path = null;
        BookBean bookBean = null;
        AlertDialog.Builder alertDialog = null;
        switch (item.getItemId()) {
            case 0:
                //重命名
                alertDialog = new AlertDialog.Builder(BookShelfActivity.this);
                final View layout = LayoutInflater.from(this).inflate(R.layout.activity_alert, shelf, false);
                alertDialog.setView(layout);
                alertDialog.setTitle("请输入修改后的书名");
                alertDialog.setPositiveButton("确定", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        EditText text = (EditText) layout;
                        String name = text.getText().toString();
                        if (name != null && !"".equals(name)) {
                            String path = bookBeanList.get(info.position).get("url");
                            String author = bookBeanList.get(info.position).get("author");
                            String desc = bookBeanList.get(info.position).get("introduce");
                            BookBean bookBean = new BookBean();
                            bookBean.setNoteUrl(path);
                            bookBean.setName(name);
                            bookBean.setAuthor(author);
                            bookBean.setIntroduce(desc);
                            bookBeanDao.update(bookBean);
                            adapter.notifyDataSetChanged();
                            getdata();//刷新页面
                        } else {
                            toast("输入为空");
                        }
                    }
                }).setNegativeButton("取消", null);
                alertDialog.show();//显示alertDialog
                break;
            case 1:
                //移出书架
                path = bookBeanList.get(info.position).get("url");
                bookBean = new BookBean();
                bookBean.setNoteUrl(path);
                bookBeanDao.delete(bookBean);
                toast("删除成功!");
                shelf.removeAllViewsInLayout();//清空所有view
                getdata();//重新获取数据
                break;
            case 2:
                //移出全部
                bookBeanDao.deleteAll();
                toast("删除成功!");
                shelf.removeAllViewsInLayout();//清空所有view
                getdata();//刷新
                break;
        }
        return super.onContextItemSelected(item);
    }

    public void Search() {
        search.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String query) {
                return false;
            }

            @Override
            public boolean onQueryTextChange(String newText) {
                if (newText != "") {
                    String name = "%" + newText + "%";
                    List<BookBean> list = bookBeanDao.queryBuilder().where(BookBeanDao.Properties.Name.like(name)).list();
                    bookBeanList.clear();//先清理掉
                    if (list.size() > 0) {
                        for (BookBean bookBean : list) {//添加数据库的所有书籍
                            Map<String, String> map = new HashMap<>();
                            map.put("name", bookBean.getName());
//                            map.put("introduce", bookBean.getIntroduce());
//                            map.put("author", bookBean.getAuthor());
                            map.put("url", bookBean.getNoteUrl());
                            bookBeanList.add(map);
                        }
                        shelf.removeAllViewsInLayout();//清空所有view

                        adapter = new SimpleAdapter(BookShelfActivity.this, bookBeanList, R.layout.activity_book_shelf_item, target, xmlpath);
                        shelf.setAdapter(adapter);
                    } else {
                        toast("没有符合搜索条件的书籍");
                    }
                    return true;
                }
                return false;
            }
        });
    }

    private Toast t;

    private void toast(String msg) {
        if (t != null) {
            t.cancel();
        }
        t = Toast.makeText(this, msg, Toast.LENGTH_SHORT);
        t.show();
    }
}

(2)activity_header.xml

<?xml version="1.0" encoding="utf-8"?>
<com.monke.immerselayout.ImmerseFrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/shelfLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".activity.BookShelfActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/back3"
        android:orientation="vertical">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="48dp"
            android:orientation="horizontal">

            <ImageView
                android:id="@+id/iv_logo"
                android:layout_width="119dp"
                android:layout_height="40dp"
                android:layout_gravity="center_vertical"
                android:layout_marginLeft="15dp"
                android:src="@drawable/logo" />

            <View
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_weight="1" />

            <ImageButton
                android:id="@+id/setting"
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:layout_gravity="center_vertical"
                android:layout_marginRight="5dp"
                android:background="@drawable/bg_ib_pre"
                android:paddingTop="10dp"
                android:paddingBottom="10dp"
                android:scaleType="fitCenter"
                android:src="@drawable/about" />

        </LinearLayout>

        <android.support.v7.widget.SearchView
            android:id="@+id/search"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

        <ListView
            android:id="@+id/shelf"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

    </LinearLayout>

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/ib_add"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_marginRight="16dp"
        android:layout_marginBottom="50dp"
        android:clickable="true"
        android:src="@drawable/selector_iv_add"
        app:backgroundTint="#767676"
        app:fabSize="auto" />
</com.monke.immerselayout.ImmerseFrameLayout>

(3)activity_alert.xml

<?xml version="1.0" encoding="utf-8"?>
<EditText xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/name"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:hint="请输入新的书名" />

(4)activity_book_shelf_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#fff2ff"
    android:orientation="vertical"
    tools:context=".activity.BookShelfActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="87dp"
        android:layout_marginTop="10dp">

        <android.support.v7.widget.AppCompatImageView
            android:layout_width="87dp"
            android:layout_height="87dp"
            android:src="@drawable/reader" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="87dp"
            android:layout_marginLeft="20dp"
            android:orientation="vertical">

            <TextView
                android:id="@+id/title"
                android:layout_width="match_parent"
                android:layout_height="30dp"
                android:layout_marginTop="27dp"
                android:singleLine="true"
                android:textSize="20dp" />
        </LinearLayout>
    </LinearLayout>

    <View
        android:layout_width="match_parent"
        android:layout_height="5dp"
        android:layout_gravity="center" />
</LinearLayout>
3.阅读页面

(1)在BookShelfActivity.java设置单击事件

 shelf.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                String path = bookBeanList.get(position).get("url");
                TxtConfig.saveIsOnVerticalPageMode(BookShelfActivity.this, false);
                HwTxtPlayActivity.loadTxtFile(BookShelfActivity.this, path);
            }
        });

(2)HwTxtPlayActivity.java

package com.bifan.txtreaderlib.ui;

import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.provider.MediaStore;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;

import com.bifan.txtreaderlib.R;
import com.bifan.txtreaderlib.bean.TxtChar;
import com.bifan.txtreaderlib.bean.TxtMsg;
import com.bifan.txtreaderlib.interfaces.ICenterAreaClickListener;
import com.bifan.txtreaderlib.interfaces.IChapter;
import com.bifan.txtreaderlib.interfaces.ILoadListener;
import com.bifan.txtreaderlib.interfaces.IPageChangeListener;
import com.bifan.txtreaderlib.interfaces.ISliderListener;
import com.bifan.txtreaderlib.interfaces.ITextSelectListener;
import com.bifan.txtreaderlib.main.TxtConfig;
import com.bifan.txtreaderlib.main.TxtReaderView;
import com.bifan.txtreaderlib.utils.ELogger;

import java.io.File;

public class HwTxtPlayActivity extends AppCompatActivity {
    protected Handler mHandler;
    protected boolean FileExist = false;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(getContentViewLayout());
        FileExist = getIntentData();
        init();
        loadFile();
        registerListener();

    }

    protected int getContentViewLayout() {
        return R.layout.activity_hwtxtpaly;
    }

    protected boolean getIntentData() {
        // Get the intent that started this activity
        Uri uri = getIntent().getData();
        if (uri != null) {
            ELogger.log("getIntentData", "" + uri);
        } else {
            ELogger.log("getIntentData", "uri is null");
        }
        if (uri != null) {
            try {
                String path = getRealPathFromUri(uri);
                if (!TextUtils.isEmpty(path)) {
                    if (path.contains("/storage/")) {
                        path = path.substring(path.indexOf("/storage/"));
                    }
                    ELogger.log("getIntentData", "path:" + path);
                    File file = new File(path);
                    if (file.exists()) {
                        FilePath = path;
                        FileName = file.getName();
                        return true;
                    } else {
                        toast("文件不存在");
                        return false;
                    }
                }
                return false;
            } catch (Exception e) {
                toast("文件出错了");
            }
        }

        FilePath = getIntent().getStringExtra("FilePath");
        FileName = getIntent().getStringExtra("FileName");
        ContentStr = getIntent().getStringExtra("ContentStr");
        if (ContentStr == null) {
            return FilePath != null && new File(FilePath).exists();
        } else {
            return true;
        }

    }

    private String getRealPathFromUri(Uri contentUri) {
        Cursor cursor = null;
        try {
            String[] pro = {MediaStore.Files.FileColumns.DATA};
            cursor = getContentResolver().query(contentUri, pro, null, null, null);
            int column_index = cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.DATA);
            cursor.moveToFirst();
            return cursor.getString(column_index);
        } catch (Exception e) {
            return null;
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
    }

    /**
     * @param context  上下文
     * @param FilePath 文本文件路径
     */
    public static void loadTxtFile(Context context, String FilePath) {
        loadTxtFile(context, FilePath, null);
    }

    /**
     * @param context 上下文
     * @param str     文本文内容
     */
    public static void loadStr(Context context, String str) {
        loadTxtStr(context, str, null);
    }

    /**
     * @param context  上下文
     * @param str      文本显示内容
     * @param FileName 显示的书籍或者文件名称
     */
    public static void loadTxtStr(Context context, String str, String FileName) {
        Intent intent = new Intent();
        intent.putExtra("ContentStr", str);
        intent.putExtra("FileName", FileName);
        intent.setClass(context, HwTxtPlayActivity.class);
        context.startActivity(intent);
    }

    /**
     * @param context  上下文
     * @param FilePath 文本文件路径
     * @param FileName 显示的书籍或者文件名称
     */
    public static void loadTxtFile(Context context, String FilePath, String FileName) {
        Intent intent = new Intent();
        intent.putExtra("FilePath", FilePath);
        intent.putExtra("FileName", FileName);
        intent.setClass(context, HwTxtPlayActivity.class);
        context.startActivity(intent);
    }

    protected View mTopDecoration, mBottomDecoration;
    protected View mChapterMsgView;
    protected TextView mChapterMsgName;
    protected TextView mChapterMsgProgress;
    protected TextView mChapterNameText;
    protected TextView mChapterMenuText;
    protected TextView mProgressText;
    protected TextView mSettingText;
    protected TextView mSelectedText;
    protected TxtReaderView mTxtReaderView;
    protected View mTopMenu;
    protected View mBottomMenu;
    protected View mCoverView;
    protected View ClipboardView;
    protected String CurrentSelectedText;

    protected ChapterList mChapterListPop;
    protected MenuHolder mMenuHolder = new MenuHolder();

    protected void init() {
        mHandler = new Handler();
        mChapterMsgView = findViewById(R.id.activity_hwtxtplay_chapter_msg);
        mChapterMsgName = (TextView) findViewById(R.id.chapter_name);
        mChapterMsgProgress = (TextView) findViewById(R.id.charpter_progress);
        mTopDecoration = findViewById(R.id.activity_hwtxtplay_top);
        mBottomDecoration = findViewById(R.id.activity_hwtxtplay_bottom);
        mTxtReaderView = (TxtReaderView) findViewById(R.id.activity_hwtxtplay_readerView);
        mChapterNameText = (TextView) findViewById(R.id.activity_hwtxtplay_chaptername);
        mChapterMenuText = (TextView) findViewById(R.id.activity_hwtxtplay_chapter_menutext);
        mProgressText = (TextView) findViewById(R.id.activity_hwtxtplay_progress_text);
        mSettingText = (TextView) findViewById(R.id.activity_hwtxtplay_setting_text);
        mTopMenu = findViewById(R.id.activity_hwtxtplay_menu_top);
        mBottomMenu = findViewById(R.id.activity_hwtxtplay_menu_bottom);
        mCoverView = findViewById(R.id.activity_hwtxtplay_cover);
        ClipboardView = findViewById(R.id.activity_hwtxtplay_Clipboar);
        mSelectedText = (TextView) findViewById(R.id.activity_hwtxtplay_selected_text);

        mMenuHolder.mTitle = (TextView) findViewById(R.id.txtreadr_menu_title);
        mMenuHolder.mPreChapter = (TextView) findViewById(R.id.txtreadr_menu_chapter_pre);
        mMenuHolder.mNextChapter = (TextView) findViewById(R.id.txtreadr_menu_chapter_next);
        mMenuHolder.mSeekBar = (SeekBar) findViewById(R.id.txtreadr_menu_seekbar);
        mMenuHolder.mTextSizeDel = findViewById(R.id.txtreadr_menu_textsize_del);
        mMenuHolder.mTextSize = (TextView) findViewById(R.id.txtreadr_menu_textsize);
        mMenuHolder.mTextSizeAdd = findViewById(R.id.txtreadr_menu_textsize_add);
        mMenuHolder.mBoldSelectedLayout = findViewById(R.id.txtreadr_menu_textsetting1_bold);
        mMenuHolder.mNormalSelectedLayout = findViewById(R.id.txtreadr_menu_textsetting1_normal);
        mMenuHolder.mCoverSelectedLayout = findViewById(R.id.txtreadr_menu_textsetting2_cover);
        mMenuHolder.mTranslateSelectedLayout = findViewById(R.id.txtreadr_menu_textsetting2_translate);

        mMenuHolder.mStyle1 = findViewById(R.id.hwtxtreader_menu_style1);
        mMenuHolder.mStyle2 = findViewById(R.id.hwtxtreader_menu_style2);
        mMenuHolder.mStyle3 = findViewById(R.id.hwtxtreader_menu_style3);
        mMenuHolder.mStyle4 = findViewById(R.id.hwtxtreader_menu_style4);
        mMenuHolder.mStyle5 = findViewById(R.id.hwtxtreader_menu_style5);
    }

    private final int[] StyleTextColors = new int[]{
            Color.parseColor("#4a453a"),
            Color.parseColor("#505550"),
            Color.parseColor("#453e33"),
            Color.parseColor("#8f8e88"),
            Color.parseColor("#27576c")
    };

    protected String ContentStr = null;
    protected String FilePath = null;
    protected String FileName = null;

    protected void loadFile() {
        TxtConfig.savePageSwitchDuration(this, 400);
        if (ContentStr == null) {
            if (TextUtils.isEmpty(FilePath) || !(new File(FilePath).exists())) {
                toast("文件不存在");
                return;
            }

        }
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                //延迟加载避免闪一下的情况出现
                if (ContentStr == null) {
                    loadOurFile();
                } else {
                    loadStr();
                }
            }
        }, 300);


    }

    protected void loadOurFile() {
        mTxtReaderView.loadTxtFile(FilePath, new ILoadListener() {
            @Override
            public void onSuccess() {
                if (!hasExisted) {
                    onLoadDataSuccess();
                }
            }

            @Override
            public void onFail(final TxtMsg txtMsg) {
                if (!hasExisted) {
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            onLoadDataFail(txtMsg);
                        }
                    });
                }

            }

            @Override
            public void onMessage(String message) {
                //加载过程信息
            }
        });
    }

    /**
     * @param txtMsg txtMsg
     */
    protected void onLoadDataFail(TxtMsg txtMsg) {
        //加载失败信息
        toast(txtMsg + "");
    }

    /**
     *
     */
    protected void onLoadDataSuccess() {
        if (TextUtils.isEmpty(FileName)) {//没有显示的名称,获取文件名显示
            FileName = mTxtReaderView.getTxtReaderContext().getFileMsg().FileName;
        }
        setBookName(FileName);
        initWhenLoadDone();
    }

    private void loadStr() {
        String testText = ContentStr;
        mTxtReaderView.loadText(testText, new ILoadListener() {
            @Override
            public void onSuccess() {
                setBookName("test with str");
                initWhenLoadDone();
            }

            @Override
            public void onFail(TxtMsg txtMsg) {
                //加载失败信息
                toast(txtMsg + "");
            }

            @Override
            public void onMessage(String message) {
                //加载过程信息
            }
        });
    }

    protected void initWhenLoadDone() {
        if (mTxtReaderView.getTxtReaderContext().getFileMsg() != null) {
            FileName = mTxtReaderView.getTxtReaderContext().getFileMsg().FileName;
        }
        mMenuHolder.mTextSize.setText(mTxtReaderView.getTextSize() + "");
        mTopDecoration.setBackgroundColor(mTxtReaderView.getBackgroundColor());
        mBottomDecoration.setBackgroundColor(mTxtReaderView.getBackgroundColor());
        //mTxtReaderView.setLeftSlider(new MuiLeftSlider());//修改左滑动条
        //mTxtReaderView.setRightSlider(new MuiRightSlider());//修改右滑动条
        //字体初始化
        onTextSettingUi(mTxtReaderView.getTxtReaderContext().getTxtConfig().Bold);
        //翻页初始化
        onPageSwitchSettingUi(mTxtReaderView.getTxtReaderContext().getTxtConfig().SwitchByTranslate);
        //保存的翻页模式
        if (mTxtReaderView.getTxtReaderContext().getTxtConfig().SwitchByTranslate) {
            mTxtReaderView.setPageSwitchByTranslate();
        } else {
            mTxtReaderView.setPageSwitchByCover();
        }
        //章节初始化
        if (mTxtReaderView.getChapters() != null && mTxtReaderView.getChapters().size() > 0) {
            WindowManager m = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
            DisplayMetrics metrics = new DisplayMetrics();
            m.getDefaultDisplay().getMetrics(metrics);
            int ViewHeight = metrics.heightPixels - mTopDecoration.getHeight();
            mChapterListPop = new ChapterList(this, ViewHeight, mTxtReaderView.getChapters(), mTxtReaderView.getTxtReaderContext().getParagraphData().getCharNum());
            mChapterListPop.getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                    IChapter chapter = (IChapter) mChapterListPop.getAdapter().getItem(i);
                    mChapterListPop.dismiss();
                    mTxtReaderView.loadFromProgress(chapter.getStartParagraphIndex(), 0);
                }
            });
            mChapterListPop.setBackGroundColor(mTxtReaderView.getBackgroundColor());
        } else {
            Gone(mChapterMenuText);
        }
    }

    protected void registerListener() {
        mSettingText.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Show(mTopMenu, mBottomMenu, mCoverView);
            }
        });
        setMenuListener();
        setSeekBarListener();
        setCenterClickListener();
        setPageChangeListener();
        setOnTextSelectListener();
        setStyleChangeListener();
        setExtraListener();
    }

    private void setExtraListener() {
        mMenuHolder.mPreChapter.setOnClickListener(new ChapterChangeClickListener(true));
        mMenuHolder.mNextChapter.setOnClickListener(new ChapterChangeClickListener(false));
        mMenuHolder.mTextSizeAdd.setOnClickListener(new TextChangeClickListener(true));
        mMenuHolder.mTextSizeDel.setOnClickListener(new TextChangeClickListener(false));
        mMenuHolder.mBoldSelectedLayout.setOnClickListener(new TextSettingClickListener(true));
        mMenuHolder.mNormalSelectedLayout.setOnClickListener(new TextSettingClickListener(false));
        mMenuHolder.mTranslateSelectedLayout.setOnClickListener(new SwitchSettingClickListener(true));
        mMenuHolder.mCoverSelectedLayout.setOnClickListener(new SwitchSettingClickListener(false));
    }

    protected void setStyleChangeListener() {
        mMenuHolder.mStyle1.setOnClickListener(new StyleChangeClickListener(ContextCompat.getColor(this, R.color.hwtxtreader_styleclor1), StyleTextColors[0]));
        mMenuHolder.mStyle2.setOnClickListener(new StyleChangeClickListener(ContextCompat.getColor(this, R.color.hwtxtreader_styleclor2), StyleTextColors[1]));
        mMenuHolder.mStyle3.setOnClickListener(new StyleChangeClickListener(ContextCompat.getColor(this, R.color.hwtxtreader_styleclor3), StyleTextColors[2]));
        mMenuHolder.mStyle4.setOnClickListener(new StyleChangeClickListener(ContextCompat.getColor(this, R.color.hwtxtreader_styleclor4), StyleTextColors[3]));
        mMenuHolder.mStyle5.setOnClickListener(new StyleChangeClickListener(ContextCompat.getColor(this, R.color.hwtxtreader_styleclor5), StyleTextColors[4]));
    }

    protected void setOnTextSelectListener() {
        mTxtReaderView.setOnTextSelectListener(new ITextSelectListener() {
            @Override
            public void onTextChanging(TxtChar firstSelectedChar, TxtChar lastSelectedChar) {
                //firstSelectedChar.Top
                //  firstSelectedChar.Bottom
                // 这里可以根据 firstSelectedChar与lastSelectedChar的top与bottom的位置
                //计算显示你要显示的弹窗位置,如果需要的话
            }

            @Override
            public void onTextChanging(String selectText) {
                onCurrentSelectedText(selectText);
            }

            @Override
            public void onTextSelected(String selectText) {
                onCurrentSelectedText(selectText);
            }
        });

        mTxtReaderView.setOnSliderListener(new ISliderListener() {
            @Override
            public void onShowSlider(TxtChar txtChar) {
                //TxtChar 为当前长按选中的字符
                // 这里可以根据 txtChar的top与bottom的位置
                //计算显示你要显示的弹窗位置,如果需要的话
            }

            @Override
            public void onShowSlider(String currentSelectedText) {
                onCurrentSelectedText(currentSelectedText);
                Show(ClipboardView);
            }

            @Override
            public void onReleaseSlider() {
                Gone(ClipboardView);
            }
        });

    }

    protected void setPageChangeListener() {
        mTxtReaderView.setPageChangeListener(new IPageChangeListener() {
            @Override
            public void onCurrentPage(float progress) {
                int p = (int) (progress * 1000);
                mProgressText.setText(((float) p / 10) + "%");
                mMenuHolder.mSeekBar.setProgress((int) (progress * 100));
                IChapter currentChapter = mTxtReaderView.getCurrentChapter();
                if (currentChapter != null) {
                    mChapterNameText.setText((currentChapter.getTitle() + "").trim());
                } else {
                    mChapterNameText.setText("无章节");
                }
            }
        });
    }

    protected void setCenterClickListener() {
        mTxtReaderView.setOnCenterAreaClickListener(new ICenterAreaClickListener() {
            @Override
            public boolean onCenterClick(float widthPercentInView) {
                mSettingText.performClick();
                return true;
            }

            @Override
            public boolean onOutSideCenterClick(float widthPercentInView) {
                if (mBottomMenu.getVisibility() == View.VISIBLE) {
                    mSettingText.performClick();
                    return true;
                }
                return false;
            }
        });
    }

    protected void setMenuListener() {
        mTopMenu.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                return true;
            }
        });
        mBottomMenu.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                return true;
            }
        });
        mCoverView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                Gone(mTopMenu, mBottomMenu, mCoverView, mChapterMsgView);
                return true;
            }
        });
        mChapterMenuText.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (mChapterListPop != null) {
                    if (!mChapterListPop.isShowing()) {
                        mChapterListPop.showAsDropDown(mTopDecoration);
                        mHandler.postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                IChapter currentChapter = mTxtReaderView.getCurrentChapter();
                                if (currentChapter != null) {
                                    mChapterListPop.setCurrentIndex(currentChapter.getIndex());
                                    mChapterListPop.notifyDataSetChanged();
                                }
                            }
                        }, 300);
                    } else {
                        mChapterListPop.dismiss();
                    }
                }
            }
        });
        mTopMenu.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (mChapterListPop.isShowing()) {
                    mChapterListPop.dismiss();
                }
            }
        });
    }

    protected void setSeekBarListener() {

        mMenuHolder.mSeekBar.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                if (motionEvent.getAction() == MotionEvent.ACTION_UP) {
                    mTxtReaderView.loadFromProgress(mMenuHolder.mSeekBar.getProgress());
                    Gone(mChapterMsgView);
                }
                return false;
            }
        });
        mMenuHolder.mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, final int progress, boolean fromUser) {
                if (fromUser) {
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            onShowChapterMsg(progress);
                        }
                    });
                }
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                Gone(mChapterMsgView);
            }
        });

    }


    private void onShowChapterMsg(int progress) {
        if (mTxtReaderView != null && mChapterListPop != null) {
            IChapter chapter = mTxtReaderView.getChapterFromProgress(progress);
            if (chapter != null) {
                float p = (float) chapter.getStartIndex() / (float) mChapterListPop.getAllCharNum();
                if (p > 1) {
                    p = 1;
                }
                Show(mChapterMsgView);
                mChapterMsgName.setText(chapter.getTitle());
                mChapterMsgProgress.setText((int) (p * 100) + "%");
            }
        }
    }

    private void onCurrentSelectedText(String SelectedText) {
        mSelectedText.setText("选中" + (SelectedText + "").length() + "个文字");
        CurrentSelectedText = SelectedText;
    }

    private void onTextSettingUi(Boolean isBold) {
        if (isBold) {
            mMenuHolder.mBoldSelectedLayout.setBackgroundResource(R.drawable.shape_menu_textsetting_selected);
            mMenuHolder.mNormalSelectedLayout.setBackgroundResource(R.drawable.shape_menu_textsetting_unselected);
        } else {
            mMenuHolder.mBoldSelectedLayout.setBackgroundResource(R.drawable.shape_menu_textsetting_unselected);
            mMenuHolder.mNormalSelectedLayout.setBackgroundResource(R.drawable.shape_menu_textsetting_selected);
        }
    }

    private void onPageSwitchSettingUi(Boolean isTranslate) {
        if (isTranslate) {
            mMenuHolder.mTranslateSelectedLayout.setBackgroundResource(R.drawable.shape_menu_textsetting_selected);
            mMenuHolder.mCoverSelectedLayout.setBackgroundResource(R.drawable.shape_menu_textsetting_unselected);
        } else {
            mMenuHolder.mTranslateSelectedLayout.setBackgroundResource(R.drawable.shape_menu_textsetting_unselected);
            mMenuHolder.mCoverSelectedLayout.setBackgroundResource(R.drawable.shape_menu_textsetting_selected);
        }
    }

    private class TextSettingClickListener implements View.OnClickListener {
        private Boolean Bold;

        public TextSettingClickListener(Boolean bold) {
            Bold = bold;
        }

        @Override
        public void onClick(View view) {
            if (FileExist) {
                mTxtReaderView.setTextBold(Bold);
                onTextSettingUi(Bold);
            }
        }
    }

    private class SwitchSettingClickListener implements View.OnClickListener {
        private Boolean isSwitchTranslate;

        public SwitchSettingClickListener(Boolean pre) {
            isSwitchTranslate = pre;
        }

        @Override
        public void onClick(View view) {
            if (FileExist) {
                if (!isSwitchTranslate) {
                    mTxtReaderView.setPageSwitchByCover();
                } else {
                    mTxtReaderView.setPageSwitchByTranslate();
                }
                onPageSwitchSettingUi(isSwitchTranslate);
            }
        }
    }


    private class ChapterChangeClickListener implements View.OnClickListener {
        private Boolean Pre;

        public ChapterChangeClickListener(Boolean pre) {
            Pre = pre;
        }

        @Override
        public void onClick(View view) {
            if (Pre) {
                mTxtReaderView.jumpToPreChapter();
            } else {
                mTxtReaderView.jumpToNextChapter();
            }
        }
    }

    private class TextChangeClickListener implements View.OnClickListener {
        private Boolean Add;

        public TextChangeClickListener(Boolean pre) {
            Add = pre;
        }

        @Override
        public void onClick(View view) {
            if (FileExist) {
                int textSize = mTxtReaderView.getTextSize();
                if (Add) {
                    if (textSize + 2 <= TxtConfig.MAX_TEXT_SIZE) {
                        mTxtReaderView.setTextSize(textSize + 2);
                        mMenuHolder.mTextSize.setText(textSize + 2 + "");
                    }
                } else {
                    if (textSize - 2 >= TxtConfig.MIN_TEXT_SIZE) {
                        mTxtReaderView.setTextSize(textSize - 2);
                        mMenuHolder.mTextSize.setText(textSize - 2 + "");
                    }
                }
            }
        }
    }

    private class StyleChangeClickListener implements View.OnClickListener {
        private int BgColor;
        private int TextColor;

        public StyleChangeClickListener(int bgColor, int textColor) {
            BgColor = bgColor;
            TextColor = textColor;
        }

        @Override
        public void onClick(View view) {
            if (FileExist) {
                mTxtReaderView.setStyle(BgColor, TextColor);
                mTopDecoration.setBackgroundColor(BgColor);
                mBottomDecoration.setBackgroundColor(BgColor);
                if (mChapterListPop != null) {
                    mChapterListPop.setBackGroundColor(BgColor);
                }
            }
        }
    }

    protected void setBookName(String name) {
        mMenuHolder.mTitle.setText(name + "");
    }

    protected void Show(View... views) {
        for (View v : views) {
            v.setVisibility(View.VISIBLE);
        }
    }

    protected void Gone(View... views) {
        for (View v : views) {
            v.setVisibility(View.GONE);
        }
    }


    private Toast t;

    protected void toast(final String msg) {
        if (t != null) {
            t.cancel();
        }
        t = Toast.makeText(HwTxtPlayActivity.this, msg, Toast.LENGTH_SHORT);
        t.show();
    }

    protected class MenuHolder {
        public TextView mTitle;
        public TextView mPreChapter;
        public TextView mNextChapter;
        public SeekBar mSeekBar;
        public View mTextSizeDel;
        public View mTextSizeAdd;
        public TextView mTextSize;
        public View mBoldSelectedLayout;
        public View mNormalSelectedLayout;
        public View mCoverSelectedLayout;
        public View mTranslateSelectedLayout;
        public View mStyle1;
        public View mStyle2;
        public View mStyle3;
        public View mStyle4;
        public View mStyle5;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        exist();
    }

    public void BackClick(View view) {
        finish();
    }

    public void onCopyText(View view) {
        if (!TextUtils.isEmpty(CurrentSelectedText)) {
            toast("已经复制到粘贴板");
            ClipboardManager cm = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
            cm.setText(CurrentSelectedText + "");
        }
        onCurrentSelectedText("");
        mTxtReaderView.releaseSelectedState();
        Gone(ClipboardView);
    }

    @Override
    public void onBackPressed() {
        super.onBackPressed();
        finish();
    }

    @Override
    public void finish() {
        super.finish();
        exist();
    }

    protected boolean hasExisted = false;

    protected void exist() {
        if (!hasExisted) {
            ContentStr = null;
            hasExisted = true;
            if (mTxtReaderView != null) {
                mTxtReaderView.saveCurrentProgress();
            }
            mHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    if (mTxtReaderView != null) {
                        mTxtReaderView.getTxtReaderContext().Clear();
                        mTxtReaderView = null;
                    }
                    if (mHandler != null) {
                        mHandler.removeCallbacksAndMessages(null);
                        mHandler = null;
                    }
                    if (mChapterListPop != null) {
                        if (mChapterListPop.isShowing()) {
                            mChapterListPop.dismiss();
                        }
                        mChapterListPop.onDestroy();
                        mChapterListPop = null;
                    }
                    mMenuHolder = null;
                }
            }, 300);

        }
    }
}

(3)activity_hwtxtplay.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <RelativeLayout
        android:id="@+id/activity_hwtxtplay_top"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#ffffff"
        >

        <TextView
            android:id="@+id/activity_hwtxtplay_chaptername"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="5dp"
            android:layout_toLeftOf="@+id/activity_hwtxtplay_chpatermenu"
            android:ellipsize="end"
            android:maxLines="1"
            android:paddingBottom="10dp"
            android:paddingTop="10dp"
            android:text="第一章"
            android:textColor="#666666" />

        <LinearLayout
            android:id="@+id/activity_hwtxtplay_chpatermenu"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:clickable="true"
            android:orientation="horizontal">

            <View

                android:layout_width="7dp"
                android:layout_height="7dp"
                android:layout_gravity="center_vertical"
                android:layout_marginRight="5dp"
                android:layout_toLeftOf="@+id/activity_hwtxtplay_chapter_menutext"
                android:background="@drawable/shape_little_ball" />

            <TextView
                android:id="@+id/activity_hwtxtplay_chapter_menutext"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_vertical"
                android:paddingRight="10dp"
                android:paddingBottom="10dp"
                android:paddingTop="10dp"
                android:clickable="true"
                android:text="章节"
                android:textColor="#858582" />
        </LinearLayout>


    </RelativeLayout>

    <com.bifan.txtreaderlib.main.TxtReaderView
        android:id="@+id/activity_hwtxtplay_readerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@+id/activity_hwtxtplay_bottom"
        android:layout_below="@+id/activity_hwtxtplay_top"
        android:background="#ffffff" />

    <RelativeLayout
        android:id="@+id/activity_hwtxtplay_bottom"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:background="#ffffff"
        android:paddingTop="5dp">

        <TextView
            android:id="@+id/activity_hwtxtplay_progress_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:text="0%"
            android:textColor="#666666" />

        <TextView
            android:id="@+id/activity_hwtxtplay_setting_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_marginRight="5dp"
            android:clickable="true"
            android:paddingBottom="5dp"
            android:paddingTop="5dp"
            android:text="设置"
            android:textColor="#858582" />
    </RelativeLayout>


    <RelativeLayout
        android:id="@+id/activity_hwtxtplay_Clipboar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:background="#000000"
        android:visibility="gone">

        <View
            android:layout_width="match_parent"
            android:layout_height="1px"
            android:background="#666666" />

        <TextView
            android:id="@+id/activity_hwtxtplay_selected_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:paddingBottom="10dp"
            android:paddingTop="10dp"
            android:text="选中0个字"
            android:textColor="#aaffffff" />

        <TextView
            android:id="@+id/activity_hwtxtplay_Clipboar_click"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_marginRight="5dp"
            android:clickable="true"
            android:onClick="onCopyText"
            android:paddingBottom="10dp"
            android:paddingTop="10dp"
            android:text="复制"
            android:textColor="#ffffff" />
    </RelativeLayout>


    <View
        android:id="@+id/activity_hwtxtplay_cover"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@+id/activity_hwtxtplay_menu_bottom"
        android:layout_below="@+id/activity_hwtxtplay_menu_top"
        android:background="#00000000"
        android:clickable="true"
        android:focusable="true"
        android:visibility="gone" />

    <include
        android:id="@+id/activity_hwtxtplay_menu_top"
        layout="@layout/view_menu_top"
        android:clickable="true"
        android:focusable="true"
        android:visibility="gone" />

    <include
        android:id="@+id/activity_hwtxtplay_menu_bottom"
        layout="@layout/view_menu_bottom"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:clickable="true"
        android:focusable="true"
        android:visibility="gone" />
    <include
        android:id="@+id/activity_hwtxtplay_chapter_msg"
        layout="@layout/view_charpter_msg"
        android:layout_width="250dp"
        android:layout_height="80dp"
        android:layout_centerInParent="true"
        android:visibility="gone" />
</RelativeLayout>

(4)view_menu_buttom.xml(设置框,单击屏幕中央或设置按钮时显示)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:background="#000000"
    android:orientation="vertical"
    android:padding="10dp">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:id="@+id/txtreadr_menu_chapter_pre"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:text="上一章"
            android:textColor="@color/hwtxtreader_bottom_menu_textclor"
            android:textSize="@dimen/hwtxtreader_menu_textsize_normal" />

        <SeekBar
            android:id="@+id/txtreadr_menu_seekbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_gravity="center_vertical"
            android:layout_toLeftOf="@+id/txtreadr_menu_chapter_next"
            android:layout_toRightOf="@+id/txtreadr_menu_chapter_pre"
            android:layout_weight="1"
            android:maxHeight="3dip"
            android:minHeight="3dip"
            android:progress="30"
            android:progressDrawable="@drawable/txtview_po_seekbar"
            android:thumb="@drawable/shape_seekbar_thumb"
            android:thumbOffset="0dip" />

        <TextView
            android:id="@+id/txtreadr_menu_chapter_next"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:text="下一章"
            android:textColor="@color/hwtxtreader_bottom_menu_textclor"
            android:textSize="@dimen/hwtxtreader_menu_textsize_normal" />
    </RelativeLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="15dp"
        android:orientation="horizontal"
        android:weightSum="6">

        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:layout_marginLeft="50px"
            android:layout_weight="2"
            android:orientation="horizontal">

            <RelativeLayout
                android:id="@+id/txtreadr_menu_textsize_del"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:layout_weight="1">

                <ImageView
                    android:layout_width="20dp"
                    android:layout_height="20dp"
                    android:layout_centerInParent="true"
                    android:scaleType="centerInside"
                    android:src="@drawable/ic_key_del" />
            </RelativeLayout>

            <TextView
                android:id="@+id/txtreadr_menu_textsize"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:layout_weight="1"
                android:gravity="center"
                android:text="25"
                android:textColor="@color/hwtxtreader_bottom_menu_textclor"
                android:textSize="@dimen/hwtxtreader_menu_textsize_max" />

            <RelativeLayout
                android:id="@+id/txtreadr_menu_textsize_add"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:layout_weight="1">

                <ImageView
                    android:layout_width="20dp"
                    android:layout_height="20dp"
                    android:layout_centerInParent="true"
                    android:scaleType="centerInside"
                    android:src="@drawable/ic_key_add" />
            </RelativeLayout>
        </LinearLayout>

        <RelativeLayout
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="4">

            <LinearLayout
                android:id="@+id/txtreadr_menu_textsetting1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentRight="true"
                android:layout_marginRight="20dp"
                android:orientation="horizontal">

                <LinearLayout
                    android:id="@+id/txtreadr_menu_textsetting1_bold"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:orientation="horizontal"
                    android:paddingLeft="@dimen/hwtxtreader_menu_textsetting_padding_leftright"
                    android:paddingTop="@dimen/hwtxtreader_menu_textsetting_padding_topbottom"
                    android:paddingRight="@dimen/hwtxtreader_menu_textsetting_padding_leftright"
                    android:paddingBottom="@dimen/hwtxtreader_menu_textsetting_padding_topbottom">

                    <TextView
                        android:layout_width="0dp"
                        android:layout_height="wrap_content"
                        android:layout_gravity="center_vertical"
                        android:layout_weight="1"
                        android:gravity="center|top"
                        android:text="加粗"
                        android:textColor="@color/hwtxtreader_bottom_menu_textclor"
                        android:textSize="@dimen/hwtxtreader_menu_textsize_max" />

                </LinearLayout>

                <LinearLayout
                    android:id="@+id/txtreadr_menu_textsetting1_normal"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginLeft="30dp"
                    android:orientation="horizontal"
                    android:paddingLeft="@dimen/hwtxtreader_menu_textsetting_padding_leftright"
                    android:paddingTop="@dimen/hwtxtreader_menu_textsetting_padding_topbottom"
                    android:paddingRight="@dimen/hwtxtreader_menu_textsetting_padding_leftright"
                    android:paddingBottom="@dimen/hwtxtreader_menu_textsetting_padding_topbottom">

                    <TextView
                        android:layout_width="0dp"
                        android:layout_height="wrap_content"
                        android:layout_gravity="center_vertical"
                        android:layout_weight="1"
                        android:gravity="center|top"
                        android:text="普通"
                        android:textColor="@color/hwtxtreader_bottom_menu_textclor"
                        android:textSize="@dimen/hwtxtreader_menu_textsize_max" />

                </LinearLayout>

            </LinearLayout>

            <LinearLayout
                android:id="@+id/txtreadr_menu_textsetting2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@+id/txtreadr_menu_textsetting1"
                android:layout_alignParentRight="true"
                android:layout_marginTop="10dp"
                android:layout_marginRight="20dp"
                android:orientation="horizontal">

                <LinearLayout
                    android:id="@+id/txtreadr_menu_textsetting2_cover"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:orientation="horizontal"
                    android:paddingLeft="@dimen/hwtxtreader_menu_textsetting_padding_leftright"
                    android:paddingTop="@dimen/hwtxtreader_menu_textsetting_padding_topbottom"
                    android:paddingRight="@dimen/hwtxtreader_menu_textsetting_padding_leftright"
                    android:paddingBottom="@dimen/hwtxtreader_menu_textsetting_padding_topbottom">

                    <TextView
                        android:layout_width="0dp"
                        android:layout_height="wrap_content"
                        android:layout_gravity="center_vertical"
                        android:layout_weight="1"
                        android:gravity="center|top"
                        android:text="滑盖"
                        android:textColor="@color/hwtxtreader_bottom_menu_textclor"
                        android:textSize="@dimen/hwtxtreader_menu_textsize_max" />

                </LinearLayout>

                <LinearLayout
                    android:id="@+id/txtreadr_menu_textsetting2_translate"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginLeft="30dp"
                    android:orientation="horizontal"
                    android:paddingLeft="@dimen/hwtxtreader_menu_textsetting_padding_leftright"
                    android:paddingTop="@dimen/hwtxtreader_menu_textsetting_padding_topbottom"
                    android:paddingRight="@dimen/hwtxtreader_menu_textsetting_padding_leftright"
                    android:paddingBottom="@dimen/hwtxtreader_menu_textsetting_padding_topbottom">

                    <TextView
                        android:layout_width="0dp"
                        android:layout_height="wrap_content"
                        android:layout_gravity="center_vertical"
                        android:layout_weight="1"
                        android:gravity="center|top"
                        android:text="平移"
                        android:textColor="@color/hwtxtreader_bottom_menu_textclor"
                        android:textSize="@dimen/hwtxtreader_menu_textsize_max" />

                </LinearLayout>

            </LinearLayout>

        </RelativeLayout>
    </LinearLayout>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:id="@+id/tag_1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_centerVertical="true"
            android:text="上一"
            android:textSize="@dimen/hwtxtreader_menu_textsize_normal"
            android:visibility="invisible" />

        <TextView
            android:id="@+id/tag_2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:text="下一"
            android:textSize="@dimen/hwtxtreader_menu_textsize_normal"
            android:visibility="invisible" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:layout_marginBottom="0dp"
            android:layout_toLeftOf="@+id/tag_2"
            android:layout_toRightOf="@+id/tag_1"
            android:orientation="horizontal"
            android:weightSum="5">

            <RelativeLayout
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1">

                <View
                    android:id="@+id/hwtxtreader_menu_style1"
                    android:layout_width="25dp"
                    android:layout_height="25dp"
                    android:layout_centerInParent="true"
                    android:background="@color/hwtxtreader_styleclor1" />
            </RelativeLayout>

            <RelativeLayout
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1">

                <View
                    android:id="@+id/hwtxtreader_menu_style2"
                    android:layout_width="25dp"
                    android:layout_height="25dp"
                    android:layout_centerInParent="true"
                    android:background="@color/hwtxtreader_styleclor2" />
            </RelativeLayout>

            <RelativeLayout
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1">

                <View
                    android:id="@+id/hwtxtreader_menu_style3"
                    android:layout_width="25dp"
                    android:layout_height="25dp"
                    android:layout_centerInParent="true"
                    android:background="@color/hwtxtreader_styleclor3" />
            </RelativeLayout>

            <RelativeLayout
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1">

                <View
                    android:id="@+id/hwtxtreader_menu_style4"
                    android:layout_width="25dp"
                    android:layout_height="25dp"
                    android:layout_centerInParent="true"
                    android:background="@color/hwtxtreader_styleclor4" />
            </RelativeLayout>

            <RelativeLayout
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1">

                <View
                    android:id="@+id/hwtxtreader_menu_style5"
                    android:layout_width="25dp"
                    android:layout_height="25dp"
                    android:layout_centerInParent="true"
                    android:background="@color/hwtxtreader_styleclor5" />
            </RelativeLayout>
        </LinearLayout>
    </RelativeLayout>
</LinearLayout>

(5)view_menu_top.xml(返回框,单击屏幕中央或设置按钮时显示)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#000000"
    android:orientation="horizontal"
    android:paddingLeft="10dp"
    android:paddingTop="13dp"
    android:paddingBottom="13dp">

    <ImageView
        android:layout_width="30dp"
        android:layout_height="18dp"
        android:layout_gravity="center_vertical"
        android:onClick="BackClick"
        android:src="@drawable/ic_key_back" />

    <TextView
        android:id="@+id/txtreadr_menu_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:layout_marginLeft="25dp"
        android:ellipsize="end"
        android:maxLines="1"
        android:text=""
        android:textColor="#ffffff"
        android:textSize="17sp" />
</LinearLayout>
4.关于我们

(1)AboutActivity.java(在书架页面点击右上角图标可以进入该页面)

package hw.txtreader.activity;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import hw.txtreader.R;

public class AboutActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_about);
    }
}

(2)activity_about.xml

<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/background"
    tools:context=".activity.AboutActivity">

    <ImageView
        android:id="@+id/imageView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="100dp"
        android:src="@drawable/icon"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="36dp"
        android:text="@string/app_name"
        android:textSize="30dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/imageView2" />

    <TextView
        android:id="@+id/edition"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginTop="314dp"
        android:drawableStart="@drawable/banbe"
        android:gravity="center"
        android:text="版本: v1.0"
        android:textSize="20dp"
        app:layout_constraintBottom_toTopOf="@+id/team"
        app:layout_constraintEnd_toEndOf="@+id/team"
        app:layout_constraintHorizontal_bias="1.0"
        app:layout_constraintStart_toStartOf="@+id/team"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/team"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginBottom="263dp"
        android:drawableStart="@drawable/tuandui"
        android:gravity="center"
        android:text="开发团队:安卓小分队"
        android:textSize="20dp"
        app:layout_constraintBottom_toTopOf="@+id/code"
        app:layout_constraintEnd_toEndOf="@+id/call"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="@+id/call"
        app:layout_constraintTop_toBottomOf="@+id/edition" />

    <TextView
        android:id="@+id/call"
        android:layout_width="300dp"
        android:layout_height="50dp"
        android:drawableStart="@drawable/lianxi"
        android:gravity="center"
        android:text="有问题联系qq:1593457"
        android:textSize="20dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/team" />


    <TextView
        android:id="@+id/code"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="8dp"
        android:text="维护地址:https://github.com/Sugarcandy/ReaderApp"
        android:textAlignment="center"
        android:textSize="20dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/team" />

</android.support.constraint.ConstraintLayout>

三.其他关键代码

1.bean
(1)BookBean.java

package hw.txtreader.bean;

import com.bifan.txtreaderlib.bean.Chapter;

import org.greenrobot.greendao.annotation.Entity;
import org.greenrobot.greendao.annotation.Id;
import org.greenrobot.greendao.annotation.Transient;

import java.util.ArrayList;
import java.util.List;

import org.greenrobot.greendao.annotation.Generated;

/**
 * 读取进来的文本信息
 */
@Entity
public class BookBean {
    private String name; //小说名

    private String tag;

    @Id
    private String noteUrl; //小说本地MD5

    private String chapterUrl;  //章节目录地址

    @Transient
    private List<Chapter> chapterlist = new ArrayList<>();    //章节列表

    private long finalRefreshData;  //章节最后更新时间

    private String coverUrl; //小说封面

    private String author;//作者

    private String introduce; //简介

    private String origin; //来源

    @Generated(hash = 169255905)
    public BookBean(String name, String tag, String noteUrl, String chapterUrl,
                    long finalRefreshData, String coverUrl, String author, String introduce,
                    String origin) {
        this.name = name;
        this.tag = tag;
        this.noteUrl = noteUrl;
        this.chapterUrl = chapterUrl;
        this.finalRefreshData = finalRefreshData;
        this.coverUrl = coverUrl;
        this.author = author;
        this.introduce = introduce;
        this.origin = origin;
    }

    @Generated(hash = 269018259)
    public BookBean() {
    }

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getTag() {
        return this.tag;
    }

    public void setTag(String tag) {
        this.tag = tag;
    }

    public String getNoteUrl() {
        return this.noteUrl;
    }

    public void setNoteUrl(String noteUrl) {
        this.noteUrl = noteUrl;
    }

    public String getChapterUrl() {
        return this.chapterUrl;
    }

    public void setChapterUrl(String chapterUrl) {
        this.chapterUrl = chapterUrl;
    }

    public long getFinalRefreshData() {
        return this.finalRefreshData;
    }

    public void setFinalRefreshData(long finalRefreshData) {
        this.finalRefreshData = finalRefreshData;
    }

    public String getCoverUrl() {
        return this.coverUrl;
    }

    public void setCoverUrl(String coverUrl) {
        this.coverUrl = coverUrl;
    }

    public String getAuthor() {
        return this.author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public String getIntroduce() {
        return this.introduce;
    }

    public void setIntroduce(String introduce) {
        this.introduce = introduce;
    }

    public String getOrigin() {
        return this.origin;
    }

    public void setOrigin(String origin) {
        this.origin = origin;
    }

    @Override
    public String toString() {
        return "BookBean{" +
                "name='" + name + '\'' +
                ", tag='" + tag + '\'' +
                ", noteUrl='" + noteUrl + '\'' +
                ", chapterUrl='" + chapterUrl + '\'' +
                ", chapterlist=" + chapterlist +
                ", finalRefreshData=" + finalRefreshData +
                ", coverUrl='" + coverUrl + '\'' +
                ", author='" + author + '\'' +
                ", introduce='" + introduce + '\'' +
                ", origin='" + origin + '\'' +
                '}';
    }
}

(2)BookShelfBean.java

package hw.txtreader.bean;

import org.greenrobot.greendao.annotation.Entity;
import org.greenrobot.greendao.annotation.Id;
import org.greenrobot.greendao.annotation.Transient;
import org.greenrobot.greendao.annotation.Generated;

/**
 * 书架
 */
@Entity
public class BookShelfBean {
    @Id
    private String noteUrl; //对应BookInfoBean noteUrl;

    private int durChapter;   //当前章节 (包括番外)

    //private int durChapterPage = BookContentView.DURPAGEINDEXBEGIN;  // 当前章节位置   用页码

    private long finalDate;  //最后阅读时间

    private String tag;

    @Transient
    private BookBean bookBean = new BookBean();

    @Generated(hash = 1754467827)
    public BookShelfBean(String noteUrl, int durChapter, long finalDate, String tag) {
        this.noteUrl = noteUrl;
        this.durChapter = durChapter;
        this.finalDate = finalDate;
        this.tag = tag;
    }

    @Generated(hash = 1462228839)
    public BookShelfBean() {
    }

    public String getNoteUrl() {
        return this.noteUrl;
    }

    public void setNoteUrl(String noteUrl) {
        this.noteUrl = noteUrl;
    }

    public int getDurChapter() {
        return this.durChapter;
    }

    public void setDurChapter(int durChapter) {
        this.durChapter = durChapter;
    }

    public long getFinalDate() {
        return this.finalDate;
    }

    public void setFinalDate(long finalDate) {
        this.finalDate = finalDate;
    }

    public String getTag() {
        return this.tag;
    }

    public void setTag(String tag) {
        this.tag = tag;
    }

    @Override
    public String toString() {
        return "BookShelfBean{" +
                "noteUrl='" + noteUrl + '\'' +
                ", durChapter=" + durChapter +
                ", finalDate=" + finalDate +
                ", tag='" + tag + '\'' +
                ", bookBean=" + bookBean +
                '}';
    }
}

2.Dao

(1)BookBeanDao.java

package hw.txtreader.dao;

import android.database.Cursor;
import android.database.sqlite.SQLiteStatement;

import org.greenrobot.greendao.AbstractDao;
import org.greenrobot.greendao.Property;
import org.greenrobot.greendao.internal.DaoConfig;
import org.greenrobot.greendao.database.Database;
import org.greenrobot.greendao.database.DatabaseStatement;

import hw.txtreader.bean.BookBean;

// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT.

/**
 * DAO for table "BOOK_BEAN".
 */
public class BookBeanDao extends AbstractDao<BookBean, String> {

    public static final String TABLENAME = "BOOK_BEAN";

    /**
     * Properties of entity BookBean.<br/>
     * Can be used for QueryBuilder and for referencing column names.
     */
    public static class Properties {
        public final static Property Name = new Property(0, String.class, "name", false, "NAME");
        public final static Property Tag = new Property(1, String.class, "tag", false, "TAG");
        public final static Property NoteUrl = new Property(2, String.class, "noteUrl", true, "NOTE_URL");
        public final static Property ChapterUrl = new Property(3, String.class, "chapterUrl", false, "CHAPTER_URL");
        public final static Property FinalRefreshData = new Property(4, long.class, "finalRefreshData", false, "FINAL_REFRESH_DATA");
        public final static Property CoverUrl = new Property(5, String.class, "coverUrl", false, "COVER_URL");
        public final static Property Author = new Property(6, String.class, "author", false, "AUTHOR");
        public final static Property Introduce = new Property(7, String.class, "introduce", false, "INTRODUCE");
        public final static Property Origin = new Property(8, String.class, "origin", false, "ORIGIN");
    }


    public BookBeanDao(DaoConfig config) {
        super(config);
    }

    public BookBeanDao(DaoConfig config, DaoSession daoSession) {
        super(config, daoSession);
    }

    /**
     * Creates the underlying database table.
     */
    public static void createTable(Database db, boolean ifNotExists) {
        String constraint = ifNotExists ? "IF NOT EXISTS " : "";
        db.execSQL("CREATE TABLE " + constraint + "\"BOOK_BEAN\" (" + //
                "\"NAME\" TEXT," + // 0: name
                "\"TAG\" TEXT," + // 1: tag
                "\"NOTE_URL\" TEXT PRIMARY KEY NOT NULL ," + // 2: noteUrl
                "\"CHAPTER_URL\" TEXT," + // 3: chapterUrl
                "\"FINAL_REFRESH_DATA\" INTEGER NOT NULL ," + // 4: finalRefreshData
                "\"COVER_URL\" TEXT," + // 5: coverUrl
                "\"AUTHOR\" TEXT," + // 6: author
                "\"INTRODUCE\" TEXT," + // 7: introduce
                "\"ORIGIN\" TEXT);"); // 8: origin
    }

    /**
     * Drops the underlying database table.
     */
    public static void dropTable(Database db, boolean ifExists) {
        String sql = "DROP TABLE " + (ifExists ? "IF EXISTS " : "") + "\"BOOK_BEAN\"";
        db.execSQL(sql);
    }

    @Override
    protected final void bindValues(DatabaseStatement stmt, BookBean entity) {
        stmt.clearBindings();

        String name = entity.getName();
        if (name != null) {
            stmt.bindString(1, name);
        }

        String tag = entity.getTag();
        if (tag != null) {
            stmt.bindString(2, tag);
        }

        String noteUrl = entity.getNoteUrl();
        if (noteUrl != null) {
            stmt.bindString(3, noteUrl);
        }

        String chapterUrl = entity.getChapterUrl();
        if (chapterUrl != null) {
            stmt.bindString(4, chapterUrl);
        }
        stmt.bindLong(5, entity.getFinalRefreshData());

        String coverUrl = entity.getCoverUrl();
        if (coverUrl != null) {
            stmt.bindString(6, coverUrl);
        }

        String author = entity.getAuthor();
        if (author != null) {
            stmt.bindString(7, author);
        }

        String introduce = entity.getIntroduce();
        if (introduce != null) {
            stmt.bindString(8, introduce);
        }

        String origin = entity.getOrigin();
        if (origin != null) {
            stmt.bindString(9, origin);
        }
    }

    @Override
    protected final void bindValues(SQLiteStatement stmt, BookBean entity) {
        stmt.clearBindings();

        String name = entity.getName();
        if (name != null) {
            stmt.bindString(1, name);
        }

        String tag = entity.getTag();
        if (tag != null) {
            stmt.bindString(2, tag);
        }

        String noteUrl = entity.getNoteUrl();
        if (noteUrl != null) {
            stmt.bindString(3, noteUrl);
        }

        String chapterUrl = entity.getChapterUrl();
        if (chapterUrl != null) {
            stmt.bindString(4, chapterUrl);
        }
        stmt.bindLong(5, entity.getFinalRefreshData());

        String coverUrl = entity.getCoverUrl();
        if (coverUrl != null) {
            stmt.bindString(6, coverUrl);
        }

        String author = entity.getAuthor();
        if (author != null) {
            stmt.bindString(7, author);
        }

        String introduce = entity.getIntroduce();
        if (introduce != null) {
            stmt.bindString(8, introduce);
        }

        String origin = entity.getOrigin();
        if (origin != null) {
            stmt.bindString(9, origin);
        }
    }

    @Override
    public String readKey(Cursor cursor, int offset) {
        return cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2);
    }

    @Override
    public BookBean readEntity(Cursor cursor, int offset) {
        BookBean entity = new BookBean( //
                cursor.isNull(offset + 0) ? null : cursor.getString(offset + 0), // name
                cursor.isNull(offset + 1) ? null : cursor.getString(offset + 1), // tag
                cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2), // noteUrl
                cursor.isNull(offset + 3) ? null : cursor.getString(offset + 3), // chapterUrl
                cursor.getLong(offset + 4), // finalRefreshData
                cursor.isNull(offset + 5) ? null : cursor.getString(offset + 5), // coverUrl
                cursor.isNull(offset + 6) ? null : cursor.getString(offset + 6), // author
                cursor.isNull(offset + 7) ? null : cursor.getString(offset + 7), // introduce
                cursor.isNull(offset + 8) ? null : cursor.getString(offset + 8) // origin
        );
        return entity;
    }

    @Override
    public void readEntity(Cursor cursor, BookBean entity, int offset) {
        entity.setName(cursor.isNull(offset + 0) ? null : cursor.getString(offset + 0));
        entity.setTag(cursor.isNull(offset + 1) ? null : cursor.getString(offset + 1));
        entity.setNoteUrl(cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2));
        entity.setChapterUrl(cursor.isNull(offset + 3) ? null : cursor.getString(offset + 3));
        entity.setFinalRefreshData(cursor.getLong(offset + 4));
        entity.setCoverUrl(cursor.isNull(offset + 5) ? null : cursor.getString(offset + 5));
        entity.setAuthor(cursor.isNull(offset + 6) ? null : cursor.getString(offset + 6));
        entity.setIntroduce(cursor.isNull(offset + 7) ? null : cursor.getString(offset + 7));
        entity.setOrigin(cursor.isNull(offset + 8) ? null : cursor.getString(offset + 8));
    }

    @Override
    protected final String updateKeyAfterInsert(BookBean entity, long rowId) {
        return entity.getNoteUrl();
    }

    @Override
    public String getKey(BookBean entity) {
        if (entity != null) {
            return entity.getNoteUrl();
        } else {
            return null;
        }
    }

    @Override
    public boolean hasKey(BookBean entity) {
        return entity.getNoteUrl() != null;
    }

    @Override
    protected final boolean isEntityUpdateable() {
        return true;
    }

}

(2)BookShelfBeanDao.java

package hw.txtreader.dao;

import android.database.Cursor;
import android.database.sqlite.SQLiteStatement;

import org.greenrobot.greendao.AbstractDao;
import org.greenrobot.greendao.Property;
import org.greenrobot.greendao.internal.DaoConfig;
import org.greenrobot.greendao.database.Database;
import org.greenrobot.greendao.database.DatabaseStatement;

import hw.txtreader.bean.BookShelfBean;

// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT.
/** 
 * DAO for table "BOOK_SHELF_BEAN".
*/
public class BookShelfBeanDao extends AbstractDao<BookShelfBean, String> {

    public static final String TABLENAME = "BOOK_SHELF_BEAN";

    /**
     * Properties of entity BookShelfBean.<br/>
     * Can be used for QueryBuilder and for referencing column names.
     */
    public static class Properties {
        public final static Property NoteUrl = new Property(0, String.class, "noteUrl", true, "NOTE_URL");
        public final static Property DurChapter = new Property(1, int.class, "durChapter", false, "DUR_CHAPTER");
        public final static Property FinalDate = new Property(2, long.class, "finalDate", false, "FINAL_DATE");
        public final static Property Tag = new Property(3, String.class, "tag", false, "TAG");
    }


    public BookShelfBeanDao(DaoConfig config) {
        super(config);
    }
    
    public BookShelfBeanDao(DaoConfig config, DaoSession daoSession) {
        super(config, daoSession);
    }

    /** Creates the underlying database table. */
    public static void createTable(Database db, boolean ifNotExists) {
        String constraint = ifNotExists? "IF NOT EXISTS ": "";
        db.execSQL("CREATE TABLE " + constraint + "\"BOOK_SHELF_BEAN\" (" + //
                "\"NOTE_URL\" TEXT PRIMARY KEY NOT NULL ," + // 0: noteUrl
                "\"DUR_CHAPTER\" INTEGER NOT NULL ," + // 1: durChapter
                "\"FINAL_DATE\" INTEGER NOT NULL ," + // 2: finalDate
                "\"TAG\" TEXT);"); // 3: tag
    }

    /** Drops the underlying database table. */
    public static void dropTable(Database db, boolean ifExists) {
        String sql = "DROP TABLE " + (ifExists ? "IF EXISTS " : "") + "\"BOOK_SHELF_BEAN\"";
        db.execSQL(sql);
    }

    @Override
    protected final void bindValues(DatabaseStatement stmt, BookShelfBean entity) {
        stmt.clearBindings();
 
        String noteUrl = entity.getNoteUrl();
        if (noteUrl != null) {
            stmt.bindString(1, noteUrl);
        }
        stmt.bindLong(2, entity.getDurChapter());
        stmt.bindLong(3, entity.getFinalDate());
 
        String tag = entity.getTag();
        if (tag != null) {
            stmt.bindString(4, tag);
        }
    }

    @Override
    protected final void bindValues(SQLiteStatement stmt, BookShelfBean entity) {
        stmt.clearBindings();
 
        String noteUrl = entity.getNoteUrl();
        if (noteUrl != null) {
            stmt.bindString(1, noteUrl);
        }
        stmt.bindLong(2, entity.getDurChapter());
        stmt.bindLong(3, entity.getFinalDate());
 
        String tag = entity.getTag();
        if (tag != null) {
            stmt.bindString(4, tag);
        }
    }

    @Override
    public String readKey(Cursor cursor, int offset) {
        return cursor.isNull(offset + 0) ? null : cursor.getString(offset + 0);
    }    

    @Override
    public BookShelfBean readEntity(Cursor cursor, int offset) {
        BookShelfBean entity = new BookShelfBean( //
            cursor.isNull(offset + 0) ? null : cursor.getString(offset + 0), // noteUrl
            cursor.getInt(offset + 1), // durChapter
            cursor.getLong(offset + 2), // finalDate
            cursor.isNull(offset + 3) ? null : cursor.getString(offset + 3) // tag
        );
        return entity;
    }
     
    @Override
    public void readEntity(Cursor cursor, BookShelfBean entity, int offset) {
        entity.setNoteUrl(cursor.isNull(offset + 0) ? null : cursor.getString(offset + 0));
        entity.setDurChapter(cursor.getInt(offset + 1));
        entity.setFinalDate(cursor.getLong(offset + 2));
        entity.setTag(cursor.isNull(offset + 3) ? null : cursor.getString(offset + 3));
     }
    
    @Override
    protected final String updateKeyAfterInsert(BookShelfBean entity, long rowId) {
        return entity.getNoteUrl();
    }
    
    @Override
    public String getKey(BookShelfBean entity) {
        if(entity != null) {
            return entity.getNoteUrl();
        } else {
            return null;
        }
    }

    @Override
    public boolean hasKey(BookShelfBean entity) {
        return entity.getNoteUrl() != null;
    }

    @Override
    protected final boolean isEntityUpdateable() {
        return true;
    }
    
}

(3)DaoMaster.java

package hw.txtreader.dao;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.util.Log;

import org.greenrobot.greendao.AbstractDaoMaster;
import org.greenrobot.greendao.database.StandardDatabase;
import org.greenrobot.greendao.database.Database;
import org.greenrobot.greendao.database.DatabaseOpenHelper;
import org.greenrobot.greendao.identityscope.IdentityScopeType;


// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT.

/**
 * Master of DAO (schema version 1): knows all DAOs.
 */
public class DaoMaster extends AbstractDaoMaster {
    public static final int SCHEMA_VERSION = 1;

    /**
     * Creates underlying database table using DAOs.
     */
    public static void createAllTables(Database db, boolean ifNotExists) {
        BookBeanDao.createTable(db, ifNotExists);
        BookShelfBeanDao.createTable(db, ifNotExists);
    }

    /**
     * Drops underlying database table using DAOs.
     */
    public static void dropAllTables(Database db, boolean ifExists) {
        BookBeanDao.dropTable(db, ifExists);
        BookShelfBeanDao.dropTable(db, ifExists);
    }

    /**
     * WARNING: Drops all table on Upgrade! Use only during development.
     * Convenience method using a {@link DevOpenHelper}.
     */
    public static DaoSession newDevSession(Context context, String name) {
        Database db = new DevOpenHelper(context, name).getWritableDb();
        DaoMaster daoMaster = new DaoMaster(db);
        return daoMaster.newSession();
    }

    public DaoMaster(SQLiteDatabase db) {
        this(new StandardDatabase(db));
    }

    public DaoMaster(Database db) {
        super(db, SCHEMA_VERSION);
        registerDaoClass(BookBeanDao.class);
        registerDaoClass(BookShelfBeanDao.class);
    }

    public DaoSession newSession() {
        return new DaoSession(db, IdentityScopeType.Session, daoConfigMap);
    }

    public DaoSession newSession(IdentityScopeType type) {
        return new DaoSession(db, type, daoConfigMap);
    }

    /**
     * Calls {@link #createAllTables(Database, boolean)} in {@link #onCreate(Database)} -
     */
    public static abstract class OpenHelper extends DatabaseOpenHelper {
        public OpenHelper(Context context, String name) {
            super(context, name, SCHEMA_VERSION);
        }

        public OpenHelper(Context context, String name, CursorFactory factory) {
            super(context, name, factory, SCHEMA_VERSION);
        }

        @Override
        public void onCreate(Database db) {
            Log.i("greenDAO", "Creating tables for schema version " + SCHEMA_VERSION);
            createAllTables(db, false);
        }
    }

    /**
     * WARNING: Drops all table on Upgrade! Use only during development.
     */
    public static class DevOpenHelper extends OpenHelper {
        public DevOpenHelper(Context context, String name) {
            super(context, name);
        }

        public DevOpenHelper(Context context, String name, CursorFactory factory) {
            super(context, name, factory);
        }

        @Override
        public void onUpgrade(Database db, int oldVersion, int newVersion) {
            Log.i("greenDAO", "Upgrading schema from version " + oldVersion + " to " + newVersion + " by dropping all tables");
            dropAllTables(db, true);
            onCreate(db);
        }
    }

}

(4)DaoSession.java

package hw.txtreader.dao;

import java.util.Map;

import org.greenrobot.greendao.AbstractDao;
import org.greenrobot.greendao.AbstractDaoSession;
import org.greenrobot.greendao.database.Database;
import org.greenrobot.greendao.identityscope.IdentityScopeType;
import org.greenrobot.greendao.internal.DaoConfig;

import hw.txtreader.bean.BookBean;
import hw.txtreader.bean.BookShelfBean;

import hw.txtreader.dao.BookBeanDao;
import hw.txtreader.dao.BookShelfBeanDao;

// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT.

/**
 * {@inheritDoc}
 *
 * @see org.greenrobot.greendao.AbstractDaoSession
 */
public class DaoSession extends AbstractDaoSession {

    private final DaoConfig bookBeanDaoConfig;
    private final DaoConfig bookShelfBeanDaoConfig;

    private final BookBeanDao bookBeanDao;
    private final BookShelfBeanDao bookShelfBeanDao;

    public DaoSession(Database db, IdentityScopeType type, Map<Class<? extends AbstractDao<?, ?>>, DaoConfig>
            daoConfigMap) {
        super(db);

        bookBeanDaoConfig = daoConfigMap.get(BookBeanDao.class).clone();
        bookBeanDaoConfig.initIdentityScope(type);

        bookShelfBeanDaoConfig = daoConfigMap.get(BookShelfBeanDao.class).clone();
        bookShelfBeanDaoConfig.initIdentityScope(type);

        bookBeanDao = new BookBeanDao(bookBeanDaoConfig, this);
        bookShelfBeanDao = new BookShelfBeanDao(bookShelfBeanDaoConfig, this);

        registerDao(BookBean.class, bookBeanDao);
        registerDao(BookShelfBean.class, bookShelfBeanDao);
    }

    public void clear() {
        bookBeanDaoConfig.clearIdentityScope();
        bookShelfBeanDaoConfig.clearIdentityScope();
    }

    public BookBeanDao getBookBeanDao() {
        return bookBeanDao;
    }

    public BookShelfBeanDao getBookShelfBeanDao() {
        return bookShelfBeanDao;
    }

}

(5)DbHelper.java

package hw.txtreader.dao;

import org.greenrobot.greendao.database.Database;

import hw.txtreader.MApplication;

public class DbHelper {
    private DaoMaster.DevOpenHelper mHelper;
    private Database db;
    private DaoMaster mDaoMaster;
    private DaoSession mDaoSession;

    private DbHelper() {
        mHelper = new DaoMaster.DevOpenHelper(MApplication.getInstance(), "reader.db", null);
        db = mHelper.getWritableDb();
        // 注意:该数据库连接属于 DaoMaster,所以多个 Session 指的是相同的数据库连接。
        mDaoMaster = new DaoMaster(db);
        mDaoSession = mDaoMaster.newSession();
    }

    private static DbHelper instance;

    public static DbHelper getInstance() {
        if (null == instance) {
            synchronized (DbHelper.class) {
                if (null == instance) instance = new DbHelper();
            }
        }
        return instance;
    }

    public DaoSession getmDaoSession() {
        return mDaoSession;
    }

    public Database getDb() {
        return db;
    }
}

3.util
HttpUtil.java

package hw.txtreader.util;

import okhttp3.OkHttpClient;
import okhttp3.Request;

public class HttpUtil {
    public static void sendOkHttpRequest(String address, okhttp3.Callback callback) {
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder().url(address).build();
        client.newCall(request).enqueue(callback);
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值