| @ -1,204 +1,26 @@ | ||||
| # FYReader-master | ||||
| 风月读书,一款开源、无广告的小说阅读软件。 | ||||
| 
 | ||||
| demo下载:https://fycz.lanzoui.com/iaVu6i6ywlg | ||||
| 
 | ||||
| #### 一、关于书源 | ||||
| 
 | ||||
| * 软件内置了15个书源如下: | ||||
|   * 11个网络小说书源:天籁小说、笔趣阁44、品书网、笔趣阁、 | ||||
|     11个网络小说书源:天籁小说、笔趣阁44、品书网、笔趣阁、 | ||||
|                     全本小说、米趣小说、九桃小说、云中书库、 | ||||
|                     搜小说网、全小说网、奇奇小说 | ||||
|   * 4个实体书书源:超星图书·实体、作品集·实体、99藏书·实体、100本·实体 | ||||
| 
 | ||||
| * 如何自行制作并添加书源. | ||||
| 
 | ||||
|   * 基于面向接口开发的思想,对于书源我设计了如下接口: | ||||
| 
 | ||||
|     * ```java | ||||
|       // 这个接口位于xyz.fycz.myreader.webapi.crawler.base包下 | ||||
|       public interface ReadCrawler { | ||||
|           String getSearchLink();  // 书源的搜索url | ||||
|           String getCharset(); // 书源的字符编码 | ||||
|           String getSearchCharset(); // 书源搜索关键字的字符编码,和书源的字符编码就行 | ||||
|           String getNameSpace(); // 书源主页地址 | ||||
|           Boolean isPost(); // 是否以post请求搜索 | ||||
|           String getContentFormHtml(String html); // 获取书籍内容规则 | ||||
|           ArrayList<Chapter> getChaptersFromHtml(String html); // 获取书籍章节列表规则 | ||||
|           ConcurrentMultiValueMap<SearchBookBean, Book> getBooksFromSearchHtml(String html); // 搜索书籍规则 | ||||
|       } | ||||
|       ``` | ||||
| 
 | ||||
|   * 了解上述接口的方法,我们就可以开始创建书源了 | ||||
| 
 | ||||
|     * 第一步:创建一个书源类实现上述接口,下面以笔趣阁44为例进行说明 | ||||
| 
 | ||||
|       * ```java | ||||
|         // 注意:如果搜索书籍页没有图片、最新章节、书籍简介等信息,可以通过实现BookInfoCrawler接口,从书籍详情页获取 | ||||
|         public class BiQuGe44ReadCrawler implements ReadCrawler, BookInfoCrawler { | ||||
|             //网站主页地址 | ||||
|             public static final String NAME_SPACE = "https://www.wqge.cc"; | ||||
|             /* | ||||
|             	搜索url,搜索关键词以{key}进行占位 | ||||
|             	如果是post请求,以“,”分隔url,“,”前是搜索地址,“,”后是请求体,搜索关键词同样以{key}占位 | ||||
|             		例如:"https://www.9txs.com/search.html,searchkey={key}" | ||||
|             */ | ||||
|             public static final String NOVEL_SEARCH = "https://www.wqge.cc/modules/article/search.php?searchkey={key}";  | ||||
|             // 书源字符编码 | ||||
|             public static final String CHARSET = "GBK"; | ||||
|             // 书源搜索关键词编码 | ||||
|             public static final String SEARCH_CHARSET = "utf-8"; | ||||
|             @Override | ||||
|             public String getSearchLink() { | ||||
|                 return NOVEL_SEARCH; | ||||
|             } | ||||
|          | ||||
|             @Override | ||||
|             public String getCharset() { | ||||
|                 return CHARSET; | ||||
|             } | ||||
|          | ||||
|             @Override | ||||
|             public String getNameSpace() { | ||||
|                 return NAME_SPACE; | ||||
|             } | ||||
|             @Override | ||||
|             public Boolean isPost() { | ||||
|                 return false; | ||||
|             } | ||||
|             @Override | ||||
|             public String getSearchCharset() { | ||||
|                 return SEARCH_CHARSET; | ||||
|             } | ||||
|          | ||||
|             /** | ||||
|              * 从html中获取章节正文 | ||||
|              * @param html | ||||
|              * @return | ||||
|              */ | ||||
|             public String getContentFormHtml(String html) { | ||||
|                 Document doc = Jsoup.parse(html); | ||||
|                 Element divContent = doc.getElementById("content"); | ||||
|                 if (divContent != null) { | ||||
|                     String content = Html.fromHtml(divContent.html()).toString(); | ||||
|                     char c = 160; | ||||
|                     String spaec = "" + c; | ||||
|                     content = content.replace(spaec, "  "); | ||||
|                     return content; | ||||
|                 } else { | ||||
|                     return ""; | ||||
|                 } | ||||
|             } | ||||
|          | ||||
|             /** | ||||
|              * 从html中获取章节列表 | ||||
|              * | ||||
|              * @param html | ||||
|              * @return | ||||
|              */ | ||||
|             public ArrayList<Chapter> getChaptersFromHtml(String html) { | ||||
|                 ArrayList<Chapter> chapters = new ArrayList<>(); | ||||
|                 Document doc = Jsoup.parse(html); | ||||
|                 String readUrl = doc.select("meta[property=og:novel:read_url]").attr("content"); | ||||
|                 Element divList = doc.getElementById("list"); | ||||
|                 String lastTile = null; | ||||
|                 int i = 0; | ||||
|                 Elements elementsByTag = divList.getElementsByTag("dd"); | ||||
|                 for (int j = 9; j < elementsByTag.size(); j++) { | ||||
|                     Element dd = elementsByTag.get(j); | ||||
|                     Elements as = dd.getElementsByTag("a"); | ||||
|                     if (as.size() > 0) { | ||||
|                         Element a = as.get(0); | ||||
|                         String title = a.text() ; | ||||
|                         if (!StringHelper.isEmpty(lastTile) && title.equals(lastTile)) { | ||||
|                             continue; | ||||
|                         } | ||||
|                         Chapter chapter = new Chapter(); | ||||
|                         chapter.setNumber(i++); | ||||
|                         chapter.setTitle(title); | ||||
|                         String url = readUrl + a.attr("href"); | ||||
|                         chapter.setUrl(url); | ||||
|                         chapters.add(chapter); | ||||
|                         lastTile = title; | ||||
|                     } | ||||
|                 } | ||||
|                 return chapters; | ||||
|             } | ||||
|          | ||||
|             /** | ||||
|              * 从搜索html中得到书列表 | ||||
|              * @param html | ||||
|              * @return | ||||
|              */ | ||||
|             public ConcurrentMultiValueMap<SearchBookBean, Book> getBooksFromSearchHtml(String html) { | ||||
|                 ConcurrentMultiValueMap<SearchBookBean, Book> books = new ConcurrentMultiValueMap<>(); | ||||
|                 Document doc = Jsoup.parse(html); | ||||
|                 Elements divs = doc.getElementsByTag("table"); | ||||
|                 Element div = divs.get(0); | ||||
|                 Elements elementsByTag = div.getElementsByTag("tr"); | ||||
|                 for (int i = 1; i < elementsByTag.size(); i++) { | ||||
|                     Element element = elementsByTag.get(i); | ||||
|                     Book book = new Book(); | ||||
|                     Elements info = element.getElementsByTag("td"); | ||||
|                     book.setName(info.get(0).text()); | ||||
|                     book.setChapterUrl(NAME_SPACE + info.get(0).getElementsByTag("a").attr("href")); | ||||
|                     book.setAuthor(info.get(2).text()); | ||||
|                     book.setNewestChapterTitle(info.get(1).text()); | ||||
|                     book.setSource(BookSource.biquge44.toString()); | ||||
|                     // SearchBookBean用于合并相同书籍 | ||||
|                     SearchBookBean sbb = new SearchBookBean(book.getName(), book.getAuthor()); | ||||
|                     books.add(sbb, book); | ||||
|                 } | ||||
|                 return books; | ||||
|             } | ||||
|          | ||||
|             /** | ||||
|              * 获取书籍详细信息 | ||||
|              * @param book | ||||
|              */ | ||||
|             public Book getBookInfo(String html, Book book){ | ||||
|                 Document doc = Jsoup.parse(html); | ||||
|                 Element img = doc.getElementById("fmimg"); | ||||
|                 book.setImgUrl(img.getElementsByTag("img").get(0).attr("src")); | ||||
|                 Element desc = doc.getElementById("intro"); | ||||
|                 book.setDesc(desc.getElementsByTag("p").get(0).text()); | ||||
|                 Element type = doc.getElementsByClass("con_top").get(0); | ||||
|                 book.setType(type.getElementsByTag("a").get(2).text()); | ||||
|                 return book; | ||||
|             } | ||||
|          | ||||
|         } | ||||
|         ``` | ||||
| 
 | ||||
|     * 第二步:注册书源信息。有两个地方需要注册: | ||||
| 
 | ||||
|       * 1)在xyz.fycz.myreader.enums.BookSource类(这是个枚举类型)中添加你的书源的命名以及书源名称,例如: | ||||
| 
 | ||||
|         * ```java | ||||
|           biquge44("笔趣阁44") // biquge44是书源的命名,笔趣阁44是书源名称 | ||||
|           ``` | ||||
| 
 | ||||
|       * 2)在app/src/main/resources/crawler.properties配置文件中添加书源类信息,例如: | ||||
| 
 | ||||
|         * ```java | ||||
|           // biquge44书源的命名,与BookSource中的命名一致,xyz.fycz.myreader.webapi.crawler.read.BiQuGe44ReadCrawler是书源类的完整路径 | ||||
|           biquge44=xyz.fycz.myreader.webapi.crawler.read.BiQuGe44ReadCrawler  | ||||
|           ``` | ||||
| 
 | ||||
|     * 第三步:启用书源(新增的书源默认禁用)。只需在软件内-我的-设置-禁用书源中取消该书源的禁用即可。 | ||||
| 
 | ||||
| #### 二、关于发现界面 | ||||
| 
 | ||||
| * 软件内置的两个发现源: | ||||
|   * 某点的排行榜、分类,全本小说网 | ||||
|   * 制作发现源方法与书源类似,在此不再赘述 | ||||
| 
 | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|     4个实体书书源:超星图书·实体、作品集·实体、99藏书·实体、100本·实体 | ||||
|      | ||||
|     发现界面:排行榜、分类、书城 | ||||
|      | ||||
|     详细功能可查看图片或下载自行体验或自行编译 | ||||
|      | ||||
| demo下载:https://fycz.lanzoui.com/iBofFh42pxg | ||||
| 
 | ||||
| 如有问题请加QQ群:1085028304 | ||||
| 
 | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| @ -1,30 +0,0 @@ | ||||
| package xyz.fycz.myreader.util; | ||||
| 
 | ||||
| import android.content.Context; | ||||
| import android.provider.Settings; | ||||
| import android.util.DisplayMetrics; | ||||
| 
 | ||||
| import androidx.appcompat.app.AppCompatActivity; | ||||
| 
 | ||||
| /** | ||||
|  */ | ||||
| 
 | ||||
| public class ScreenHelper { | ||||
| 
 | ||||
|     public static double getScreenPhysicalSize(AppCompatActivity ctx) { | ||||
|         DisplayMetrics dm = new DisplayMetrics(); | ||||
|         ctx.getWindowManager().getDefaultDisplay().getMetrics(dm); | ||||
|         double diagonalPixels = Math.sqrt(Math.pow(dm.widthPixels, 2) + Math.pow(dm.heightPixels, 2)); | ||||
|         return diagonalPixels / (160 * dm.density); | ||||
|     } | ||||
|     public static int getScreenOffTime(Context context) { | ||||
|         int screenOffTime = 0; | ||||
|         try { | ||||
|             screenOffTime = Settings.System.getInt(context.getContentResolver(), | ||||
|                     Settings.System.SCREEN_OFF_TIMEOUT); | ||||
|         } catch (Exception e) { | ||||
|             e.printStackTrace(); | ||||
|         } | ||||
|         return screenOffTime; | ||||
|     } | ||||
| } | ||||
| @ -1,59 +1,99 @@ | ||||
| package xyz.fycz.myreader.widget.page; | ||||
| 
 | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
| 
 | ||||
| /** | ||||
|  * Created by newbiechen on 17-7-1. | ||||
|  * Created by zhouas666 on 18-1-23. | ||||
|  * 书籍chapter | ||||
|  */ | ||||
| 
 | ||||
| public class TxtChapter { | ||||
| public class TxtChapter{ | ||||
| 
 | ||||
|     //章节所属的小说(网络)
 | ||||
|     String bookId; | ||||
|     //章节名
 | ||||
|     String title; | ||||
|     private int position; | ||||
|     private List<TxtPage> txtPageList = new ArrayList<>(); | ||||
|     private List<Integer> txtPageLengthList = new ArrayList<>(); | ||||
|     private List<Integer> paragraphLengthList = new ArrayList<>(); | ||||
|     private Status status = Status.LOADING; | ||||
|     private String msg; | ||||
| 
 | ||||
|     //章节内容在文章中的起始位置(本地)
 | ||||
|     long start; | ||||
|     //章节内容在文章中的终止位置(本地)
 | ||||
|     long end; | ||||
|     TxtChapter(int position) { | ||||
|         this.position = position; | ||||
|     } | ||||
| 
 | ||||
|     public String getBookId() { | ||||
|         return bookId; | ||||
|     public int getPosition() { | ||||
|         return position; | ||||
|     } | ||||
| 
 | ||||
|     public void setBookId(String id) { | ||||
|         this.bookId = id; | ||||
|     List<TxtPage> getTxtPageList() { | ||||
|         return txtPageList; | ||||
|     } | ||||
| 
 | ||||
|     public String getTitle() { | ||||
|         return title; | ||||
|     void addPage(TxtPage txtPage) { | ||||
|         txtPageList.add(txtPage); | ||||
|     } | ||||
| 
 | ||||
|     public void setTitle(String title) { | ||||
|         this.title = title; | ||||
|     int getPageSize() { | ||||
|         return txtPageList.size(); | ||||
|     } | ||||
| 
 | ||||
|     public long getStart() { | ||||
|         return start; | ||||
|     TxtPage getPage(int page) { | ||||
|         if (!txtPageList.isEmpty()) { | ||||
|             return txtPageList.get(Math.max(0, Math.min(page, txtPageList.size() - 1))); | ||||
|         } | ||||
|         return null; | ||||
|     } | ||||
| 
 | ||||
|     public void setStart(long start) { | ||||
|         this.start = start; | ||||
|     Status getStatus() { | ||||
|         return status; | ||||
|     } | ||||
| 
 | ||||
|     public long getEnd() { | ||||
|         return end; | ||||
|     void setStatus(Status mStatus) { | ||||
|         this.status = mStatus; | ||||
|     } | ||||
| 
 | ||||
|     public void setEnd(long end) { | ||||
|         this.end = end; | ||||
|     public String getMsg() { | ||||
|         return msg; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public String toString() { | ||||
|         return "TxtChapter{" + | ||||
|                 "title='" + title + '\'' + | ||||
|                 ", start=" + start + | ||||
|                 ", end=" + end + | ||||
|                 '}'; | ||||
|     public void setMsg(String msg) { | ||||
|         this.msg = msg; | ||||
|     } | ||||
| 
 | ||||
|     int getPageLength(int position) { | ||||
|         if (txtPageLengthList != null && position >= 0 && position < txtPageLengthList.size()) { | ||||
|             return txtPageLengthList.get(position); | ||||
|         } | ||||
|         return -1; | ||||
|     } | ||||
| 
 | ||||
|     void addTxtPageLength(int length) { | ||||
|         txtPageLengthList.add(length); | ||||
|     } | ||||
| 
 | ||||
|     List<Integer> getTxtPageLengthList() { | ||||
|         return txtPageLengthList; | ||||
|     } | ||||
| 
 | ||||
|     List<Integer> getParagraphLengthList() { | ||||
|         return paragraphLengthList; | ||||
|     } | ||||
| 
 | ||||
|     void addParagraphLength(int length) { | ||||
|         paragraphLengthList.add(length); | ||||
|     } | ||||
| 
 | ||||
|     int getParagraphIndex(int length) { | ||||
|         for (int i = 0; i < paragraphLengthList.size(); i++) { | ||||
|             if ((i == 0 || paragraphLengthList.get(i - 1) < length) && length <= paragraphLengthList.get(i)) { | ||||
|                 return i; | ||||
|             } | ||||
|         } | ||||
|         return -1; | ||||
|     } | ||||
| 
 | ||||
|     public enum Status { | ||||
|         LOADING, FINISH, ERROR, EMPTY, CATEGORY_EMPTY, CHANGE_SOURCE, | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | ||||
| @ -1,199 +1,239 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|                 xmlns:tools="http://schemas.android.com/tools" | ||||
|                 android:layout_width="match_parent" | ||||
|                 android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto"> | ||||
|     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"> | ||||
| 
 | ||||
|     <com.google.android.material.appbar.AppBarLayout | ||||
|             android:id="@+id/read_abl_top_menu" | ||||
|         android:id="@+id/read_abl_top_menu" | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:background="@color/read_menu_bg" | ||||
|         android:visibility="gone" | ||||
|         tools:visibility="visible"> | ||||
| 
 | ||||
|         <LinearLayout | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:background="@color/read_menu_bg" | ||||
|             android:visibility="gone" | ||||
|             tools:visibility="visible"> | ||||
|             android:orientation="vertical"> | ||||
| 
 | ||||
|         <LinearLayout | ||||
|             <androidx.appcompat.widget.Toolbar | ||||
|                 android:id="@+id/toolbar" | ||||
|                 style="@style/NoPaddingToolbar" | ||||
|                 android:layout_width="match_parent" | ||||
|                 android:layout_height="wrap_content" | ||||
|                 android:orientation="vertical"> | ||||
|                 android:layout_height="45dp" | ||||
|                 android:gravity="center_vertical" | ||||
|                 android:minHeight="?attr/actionBarSize" | ||||
|                 android:theme="?attr/actionBarStyle" | ||||
|                 android:transitionName="sharedView" | ||||
|                 app:layout_scrollFlags="scroll|enterAlways" | ||||
|                 app:popupTheme="@style/AppTheme.PopupOverlay" | ||||
|                 app:title="大主宰" /> | ||||
| 
 | ||||
|             <androidx.appcompat.widget.Toolbar | ||||
|                     android:id="@+id/toolbar" | ||||
|                     style="@style/NoPaddingToolbar" | ||||
|                     android:layout_width="match_parent" | ||||
|                     android:layout_height="45dp" | ||||
|                     android:minHeight="?attr/actionBarSize" | ||||
|                     android:gravity="center_vertical" | ||||
|                     android:theme="?attr/actionBarStyle" | ||||
|                     android:transitionName="sharedView" | ||||
|                     app:title="大主宰" | ||||
|                     app:layout_scrollFlags="scroll|enterAlways" | ||||
|                     app:popupTheme="@style/AppTheme.PopupOverlay"> | ||||
|             </androidx.appcompat.widget.Toolbar> | ||||
|             <View | ||||
|                     android:layout_width="fill_parent" | ||||
|                     android:layout_height="0.5dp" | ||||
|                     android:background="@color/sys_dialog_setting_line" /> | ||||
|                 android:layout_width="fill_parent" | ||||
|                 android:layout_height="0.5dp" | ||||
|                 android:background="@color/sys_dialog_setting_line" /> | ||||
| 
 | ||||
|             <LinearLayout | ||||
|                     android:id="@+id/ll_chapter_view" | ||||
|                 android:id="@+id/ll_chapter_view" | ||||
|                 android:layout_width="match_parent" | ||||
|                 android:layout_height="40dp" | ||||
|                 android:orientation="vertical"> | ||||
| 
 | ||||
|                 <TextView | ||||
|                     android:id="@+id/tv_chapter_title_top" | ||||
|                     android:layout_width="match_parent" | ||||
|                     android:layout_height="40dp" | ||||
|                     android:orientation="vertical"> | ||||
|                 <TextView android:id="@+id/tv_chapter_title_top" | ||||
|                           android:layout_width="match_parent" | ||||
|                           android:layout_height="wrap_content" | ||||
|                           android:layout_marginStart="14dp" | ||||
|                           android:layout_marginEnd="14dp" | ||||
|                           android:textSize="15sp" | ||||
|                           android:text="章节名称" | ||||
|                           android:ellipsize="end" | ||||
|                           android:maxLines="1" | ||||
|                           android:textColor="@color/read_menu_text"> | ||||
|                 </TextView> | ||||
|                 <TextView android:id="@+id/tv_chapter_url" | ||||
|                           android:layout_width="match_parent" | ||||
|                           android:layout_height="wrap_content" | ||||
|                           android:layout_marginStart="14dp" | ||||
|                           android:layout_marginEnd="14dp" | ||||
|                           android:ellipsize="end" | ||||
|                           android:textSize="13sp" | ||||
|                           android:text="章节链接" | ||||
|                           android:maxLines="1" | ||||
|                           android:textColor="@color/read_menu_text"> | ||||
|                 </TextView> | ||||
|                     android:layout_height="wrap_content" | ||||
|                     android:layout_marginStart="14dp" | ||||
|                     android:layout_marginEnd="14dp" | ||||
|                     android:ellipsize="end" | ||||
|                     android:maxLines="1" | ||||
|                     android:text="章节名称" | ||||
|                     android:textColor="@color/read_menu_text" | ||||
|                     android:textSize="15sp" /> | ||||
| 
 | ||||
|                 <TextView | ||||
|                     android:id="@+id/tv_chapter_url" | ||||
|                     android:layout_width="match_parent" | ||||
|                     android:layout_height="wrap_content" | ||||
|                     android:layout_marginStart="14dp" | ||||
|                     android:layout_marginEnd="14dp" | ||||
|                     android:ellipsize="end" | ||||
|                     android:maxLines="1" | ||||
|                     android:text="章节链接" | ||||
|                     android:textColor="@color/read_menu_text" | ||||
|                     android:textSize="13sp" /> | ||||
|             </LinearLayout> | ||||
|         </LinearLayout> | ||||
|     </com.google.android.material.appbar.AppBarLayout> | ||||
| 
 | ||||
|     <!--阅读页面--> | ||||
|     <xyz.fycz.myreader.widget.page.PageView | ||||
|             android:id="@+id/read_pv_content" | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="match_parent" | ||||
|             android:clickable="true" | ||||
|             tools:visibility="gone"/> | ||||
|         android:id="@+id/read_pv_content" | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="match_parent" | ||||
|         android:clickable="true" | ||||
|         tools:visibility="gone" /> | ||||
| 
 | ||||
|     <com.h6ah4i.android.widget.verticalseekbar.VerticalSeekBarWrapper | ||||
|         android:layout_width="wrap_content" | ||||
|         android:layout_height="match_parent" | ||||
|         android:layout_marginTop="20dp" | ||||
|         android:layout_marginBottom="20dp"> | ||||
| 
 | ||||
|         <com.h6ah4i.android.widget.verticalseekbar.VerticalSeekBar | ||||
|             android:id="@+id/pb_nextPage" | ||||
|             android:layout_width="wrap_content" | ||||
|             android:layout_height="match_parent" | ||||
|             android:layout_marginTop="20dp" | ||||
|             android:layout_marginBottom="20dp"> | ||||
|         <com.h6ah4i.android.widget.verticalseekbar.VerticalSeekBar | ||||
|                 android:id="@+id/pb_nextPage" | ||||
|                 android:layout_width="wrap_content" | ||||
|                 android:layout_height="match_parent" | ||||
|                 android:splitTrack="false" | ||||
|                 app:seekBarRotation="CW270" | ||||
|                 android:visibility="invisible" | ||||
|                 tools:visibility="visible"/> | ||||
|             android:splitTrack="false" | ||||
|             android:visibility="invisible" | ||||
|             app:seekBarRotation="CW270" | ||||
|             tools:visibility="visible" /> | ||||
|     </com.h6ah4i.android.widget.verticalseekbar.VerticalSeekBarWrapper> | ||||
| 
 | ||||
|     <ProgressBar | ||||
|             android:id="@+id/pb_loading" | ||||
|             android:layout_width="wrap_content" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:layout_centerInParent="true" | ||||
|             android:visibility="gone" | ||||
|             tools:visibility="visible"/> | ||||
|         android:id="@+id/pb_loading" | ||||
|         android:layout_width="wrap_content" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_centerInParent="true" | ||||
|         android:visibility="gone" | ||||
|         tools:visibility="visible" /> | ||||
| 
 | ||||
| 
 | ||||
|     <!--切换页面提示--> | ||||
|     <TextView | ||||
|             android:id="@+id/read_tv_page_tip" | ||||
|             android:layout_width="wrap_content" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:layout_above="@+id/read_ll_bottom_menu" | ||||
|             android:layout_centerHorizontal="true" | ||||
|             android:layout_marginBottom="10dp" | ||||
|             android:background="@color/read_menu_bg" | ||||
|             android:gravity="center" | ||||
|             android:paddingLeft="12dp" | ||||
|             android:paddingTop="8dp" | ||||
|             android:paddingRight="12dp" | ||||
|             android:paddingBottom="8dp" | ||||
|             android:text="1/12" | ||||
|             android:textColor="@color/md_white_1000" | ||||
|             android:visibility="gone"/> | ||||
| 
 | ||||
|     <!--底部页面--> | ||||
|     <LinearLayout | ||||
|             android:id="@+id/read_ll_bottom_menu" | ||||
|         android:id="@+id/read_ll_bottom_menu" | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_alignParentBottom="true" | ||||
|         android:clickable="true" | ||||
|         android:orientation="vertical" | ||||
|         android:visibility="gone" | ||||
|         tools:visibility="visible"> | ||||
|         <RelativeLayout | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:layout_alignParentBottom="true" | ||||
|             android:background="@color/read_menu_bg" | ||||
|             android:clickable="true" | ||||
|             android:orientation="vertical" | ||||
|             android:visibility="gone" | ||||
|             tools:visibility="visible"> | ||||
|             android:layout_height="wrap_content"> | ||||
|             <!--切换页面提示--> | ||||
|             <TextView | ||||
|                 android:id="@+id/read_tv_page_tip" | ||||
|                 android:layout_width="wrap_content" | ||||
|                 android:layout_height="wrap_content" | ||||
|                 android:layout_centerHorizontal="true" | ||||
|                 android:layout_marginBottom="10dp" | ||||
|                 android:background="@color/read_menu_bg" | ||||
|                 android:gravity="center" | ||||
|                 android:layout_marginTop="4dp" | ||||
|                 android:paddingLeft="12dp" | ||||
|                 android:paddingTop="8dp" | ||||
|                 android:paddingRight="12dp" | ||||
|                 android:paddingBottom="8dp" | ||||
|                 android:text="1/12" | ||||
|                 android:textColor="@color/md_white_1000" /> | ||||
| 
 | ||||
|             <com.google.android.material.floatingactionbutton.FloatingActionButton | ||||
|                 android:id="@+id/iv_listen_book" | ||||
|                 app:backgroundTint="@color/read_menu_bg" | ||||
|                 android:layout_marginEnd="15dp" | ||||
|                 android:layout_marginBottom="12dp" | ||||
|                 android:layout_width="40dp" | ||||
|                 android:layout_height="40dp" | ||||
|                 android:layout_alignParentEnd="true" | ||||
|                 android:tint="@color/read_menu_text" | ||||
|                 android:src="@drawable/ic_listen_book" | ||||
|                 app:elevation="2dp" | ||||
|                 app:fabCustomSize="40dp" | ||||
|                 app:pressedTranslationZ="2dp" | ||||
|                 /> | ||||
|         </RelativeLayout> | ||||
| 
 | ||||
|         <!--页面进度栏--> | ||||
|         <LinearLayout | ||||
|                 android:layout_width="match_parent" | ||||
|                 android:layout_height="60dp" | ||||
|                 android:gravity="center_vertical" | ||||
|                 android:orientation="horizontal"> | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="60dp" | ||||
|             android:background="@color/read_menu_bg" | ||||
|             android:gravity="center_vertical" | ||||
|             android:orientation="horizontal"> | ||||
| 
 | ||||
|             <TextView | ||||
|                     android:id="@+id/read_tv_pre_chapter" | ||||
|                     style="@style/MAppTheme.TextAppearance.Read.BottomMenu" | ||||
|                     android:layout_width="80dp" | ||||
|                     android:layout_height="match_parent" | ||||
|                     android:gravity="center" | ||||
|                     android:text="上一章"/> | ||||
|                 android:id="@+id/read_tv_pre_chapter" | ||||
|                 style="@style/MAppTheme.TextAppearance.Read.BottomMenu" | ||||
|                 android:layout_width="80dp" | ||||
|                 android:layout_height="match_parent" | ||||
|                 android:gravity="center" | ||||
|                 android:clickable="true" | ||||
|                 android:focusable="true" | ||||
|                 android:text="上一章" /> | ||||
| 
 | ||||
|             <SeekBar | ||||
|                     android:id="@+id/read_sb_chapter_progress" | ||||
|                     android:layout_width="0dp" | ||||
|                     android:layout_height="wrap_content" | ||||
|                     android:layout_weight="1" | ||||
|                     android:max="100" | ||||
|                     android:maxHeight="3dp" | ||||
|                     android:minHeight="3dp" | ||||
|                     android:progressDrawable="@drawable/seekbar_bg" | ||||
|                     android:thumb="@mipmap/thumb" | ||||
|                     android:thumbOffset="10dp"/> | ||||
|                 android:id="@+id/read_sb_chapter_progress" | ||||
|                 android:layout_width="0dp" | ||||
|                 android:layout_height="wrap_content" | ||||
|                 android:layout_weight="1" | ||||
|                 android:max="100" | ||||
|                 android:maxHeight="3dp" | ||||
|                 android:minHeight="3dp" | ||||
|                 android:progressDrawable="@drawable/seekbar_bg" | ||||
|                 android:thumb="@mipmap/thumb" | ||||
|                 android:thumbOffset="10dp" /> | ||||
| 
 | ||||
|             <TextView | ||||
|                     android:id="@+id/read_tv_next_chapter" | ||||
|                     style="@style/MAppTheme.TextAppearance.Read.BottomMenu" | ||||
|                     android:layout_width="80dp" | ||||
|                     android:layout_height="match_parent" | ||||
|                     android:gravity="center" | ||||
|                     android:text="下一章"/> | ||||
|                 android:id="@+id/read_tv_next_chapter" | ||||
|                 style="@style/MAppTheme.TextAppearance.Read.BottomMenu" | ||||
|                 android:layout_width="80dp" | ||||
|                 android:layout_height="match_parent" | ||||
|                 android:gravity="center" | ||||
|                 android:clickable="true" | ||||
|                 android:focusable="true" | ||||
|                 android:text="下一章" /> | ||||
|         </LinearLayout> | ||||
| 
 | ||||
|         <View | ||||
|                 android:layout_width="fill_parent" | ||||
|                 android:layout_height="0.5dp" | ||||
|                 android:background="@color/sys_dialog_setting_line" /> | ||||
|             android:layout_width="fill_parent" | ||||
|             android:layout_height="0.5dp" | ||||
|             android:background="@color/sys_dialog_setting_line" /> | ||||
|         <!--菜单栏--> | ||||
|         <LinearLayout | ||||
|                 android:layout_width="match_parent" | ||||
|                 android:layout_height="72dp" | ||||
|                 android:orientation="horizontal" | ||||
|                 android:paddingTop="12dp" | ||||
|                 android:paddingBottom="12dp"> | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="72dp" | ||||
|             android:background="@color/read_menu_bg" | ||||
|             android:orientation="horizontal" | ||||
|             android:paddingTop="12dp" | ||||
|             android:paddingBottom="12dp"> | ||||
| 
 | ||||
|             <TextView | ||||
|                     android:id="@+id/read_tv_category" | ||||
|                     style="@style/AppTheme.TextAppearance.Read.BottomMenu.Button" | ||||
|                     android:drawableTop="@mipmap/t3" | ||||
|                     android:text="目录"/> | ||||
|                 android:id="@+id/read_tv_category" | ||||
|                 style="@style/AppTheme.TextAppearance.Read.BottomMenu.Button" | ||||
|                 android:text="目录" | ||||
|                 android:clickable="true" | ||||
|                 android:focusable="true" | ||||
|                 app:drawableTopCompat="@mipmap/t3" /> | ||||
| 
 | ||||
|             <TextView | ||||
|                     android:id="@+id/read_tv_download" | ||||
|                     style="@style/AppTheme.TextAppearance.Read.BottomMenu.Button" | ||||
|                     android:drawableTop="@mipmap/download" | ||||
|                     android:text="下载"/> | ||||
|                 android:id="@+id/read_tv_download" | ||||
|                 style="@style/AppTheme.TextAppearance.Read.BottomMenu.Button" | ||||
|                 android:text="下载" | ||||
|                 android:clickable="true" | ||||
|                 android:focusable="true" | ||||
|                 app:drawableTopCompat="@mipmap/download" /> | ||||
| 
 | ||||
|             <TextView | ||||
|                     android:id="@+id/read_tv_night_mode" | ||||
|                     style="@style/AppTheme.TextAppearance.Read.BottomMenu.Button" | ||||
|                     android:drawableTop="@mipmap/ao" | ||||
|                     android:text="夜间"/> | ||||
|                 android:id="@+id/read_tv_night_mode" | ||||
|                 style="@style/AppTheme.TextAppearance.Read.BottomMenu.Button" | ||||
|                 android:text="夜间" | ||||
|                 android:clickable="true" | ||||
|                 android:focusable="true" | ||||
|                 app:drawableTopCompat="@mipmap/ao" /> | ||||
| 
 | ||||
|             <TextView | ||||
|                     android:id="@+id/read_tv_setting" | ||||
|                     style="@style/AppTheme.TextAppearance.Read.BottomMenu.Button" | ||||
|                     android:drawableTop="@mipmap/t6" | ||||
|                     android:text="设置"/> | ||||
|                 android:id="@+id/read_tv_setting" | ||||
|                 style="@style/AppTheme.TextAppearance.Read.BottomMenu.Button" | ||||
|                 android:text="设置" | ||||
|                 android:clickable="true" | ||||
|                 android:focusable="true" | ||||
|                 app:drawableTopCompat="@mipmap/t6" /> | ||||
|         </LinearLayout> | ||||
|     </LinearLayout> | ||||
| </RelativeLayout> | ||||
|  | ||||
| @ -1,6 +1,9 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <androidx.constraintlayout.widget.ConstraintLayout | ||||
|         xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="match_parent" | ||||
|         android:background="@drawable/start"/> | ||||
| <androidx.appcompat.widget.AppCompatImageView | ||||
|     xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     xmlns:app="http://schemas.android.com/apk/res-auto" | ||||
|     android:id="@+id/iv_splash" | ||||
|     android:layout_width="match_parent" | ||||
|     android:layout_height="match_parent" | ||||
|     android:scaleType="fitXY" | ||||
|     app:srcCompat="@drawable/start"/> | ||||
| @ -1,2 +1,2 @@ | ||||
| #Mon Nov 09 21:09:26 CST 2020 | ||||
| VERSION_CODE=155 | ||||
| #Wed Nov 11 20:37:05 CST 2020 | ||||
| VERSION_CODE=154 | ||||
|  | ||||
| Before Width: | Height: | Size: 153 KiB After Width: | Height: | Size: 103 KiB | 
| Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 21 KiB | 
| Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 188 KiB | 
| Before Width: | Height: | Size: 125 KiB After Width: | Height: | Size: 30 KiB | 
| Before Width: | Height: | Size: 163 KiB After Width: | Height: | Size: 196 KiB | 
| Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 97 KiB | 
| Before Width: | Height: | Size: 174 KiB After Width: | Height: | Size: 51 KiB | 
| Before Width: | Height: | Size: 85 KiB After Width: | Height: | Size: 122 KiB |