diff --git a/app/src/main/assets/updatelog.fy b/app/src/main/assets/updatelog.fy
index 4a2ceaa..814173f 100644
--- a/app/src/main/assets/updatelog.fy
+++ b/app/src/main/assets/updatelog.fy
@@ -1,3 +1,8 @@
+2021.06.14
+风月读书v2.1.3
+更新内容:
+1、优化阅读文字选择
+
2021.06.13
风月读书v2.1.2
更新内容:
diff --git a/app/src/main/java/xyz/fycz/myreader/common/APPCONST.java b/app/src/main/java/xyz/fycz/myreader/common/APPCONST.java
index 1df4798..6401ab7 100644
--- a/app/src/main/java/xyz/fycz/myreader/common/APPCONST.java
+++ b/app/src/main/java/xyz/fycz/myreader/common/APPCONST.java
@@ -22,18 +22,17 @@ import javax.script.ScriptEngineManager;
public class APPCONST {
public static String publicKey = "";//服务端公钥
- public static String privateKey;//app私钥
public static final String KEY = "";
public static final String[] STORAGE_PERMISSIONS = new String[]{Permission.WRITE_EXTERNAL_STORAGE,
Permission.READ_EXTERNAL_STORAGE};
- public static final String FILE_DIR = Environment.getExternalStorageDirectory() + "/FYReader/";
- public static final String SHARE_FILE_DIR = Environment.getExternalStorageDirectory() + "/FYReader/share/";
- public static String LOG_DIR = FileUtils.getCachePath() + "/log/";
- public static String COVER_DIR = FileUtils.getCachePath() + "/covers/";
- public static final String BG_FILE_DIR = Environment.getExternalStorageDirectory() + "/FYReader/bg/";
- public static String TEM_FILE_DIR = FileUtils.getCachePath() + "/tem/";
+ public static final String FILE_DIR = Environment.getExternalStorageDirectory() + "/FYReader/";
+ public static final String SHARE_FILE_DIR = Environment.getExternalStorageDirectory() + "/FYReader/share/";
+ public static String LOG_DIR = FileUtils.getCachePath() + "/log/";
+ public static String COVER_DIR = FileUtils.getCachePath() + "/covers/";
+ public static final String BG_FILE_DIR = Environment.getExternalStorageDirectory() + "/FYReader/bg/";
+ public static String TEM_FILE_DIR = FileUtils.getCachePath() + "/tem/";
public static final String BACKUP_FILE_DIR = Environment.getExternalStorageDirectory() + "/FYReader/backup/";
public static final String TXT_BOOK_DIR = Environment.getExternalStorageDirectory() + "/FYReader/noveltxt/";
public static final String FONT_BOOK_DIR = Environment.getExternalStorageDirectory() + "/FYReader/font/";
@@ -41,9 +40,9 @@ public class APPCONST {
public static final String QQ_DATA_DIR = Environment.getExternalStorageDirectory() + "/tencent/MobileQQ/data/";
//BookCachePath (因为getCachePath引用了Context,所以必须是静态变量,不能够是静态常量)
public static String BOOK_CACHE_PATH = FileUtils.getCachePath() + File.separator
- + "book_cache"+ File.separator ;
+ + "book_cache" + File.separator;
public static String HTML_CACHE_PATH = FileUtils.getCachePath() + File.separator
- + "html_cache"+ File.separator ;
+ + "html_cache" + File.separator;
public static long exitTime;
public static final int exitConfirmTime = 2000;
@@ -120,6 +119,7 @@ public class APPCONST {
public static final Pattern JS_PATTERN = Pattern.compile("([\\w\\W]*?|@js:[\\w\\W]*$)", Pattern.CASE_INSENSITIVE);
public static final Pattern EXP_PATTERN = Pattern.compile("\\{\\{([\\w\\W]*?)\\}\\}");
+// public static final Pattern IMG_PATTERN = Pattern.compile("", Pattern.CASE_INSENSITIVE);
public static final ScriptEngine SCRIPT_ENGINE = new ScriptEngineManager().getEngineByName("rhino");
diff --git a/app/src/main/java/xyz/fycz/myreader/ui/activity/ReadActivity.java b/app/src/main/java/xyz/fycz/myreader/ui/activity/ReadActivity.java
index 2b362e4..e46e2a5 100644
--- a/app/src/main/java/xyz/fycz/myreader/ui/activity/ReadActivity.java
+++ b/app/src/main/java/xyz/fycz/myreader/ui/activity/ReadActivity.java
@@ -28,6 +28,7 @@ import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.FrameLayout;
+import android.widget.ImageView;
import android.widget.SeekBar;
import androidx.annotation.NonNull;
@@ -111,6 +112,7 @@ import xyz.fycz.myreader.widget.BubblePopupView;
import xyz.fycz.myreader.widget.page.PageLoader;
import xyz.fycz.myreader.widget.page.PageMode;
import xyz.fycz.myreader.widget.page.PageView;
+import xyz.fycz.myreader.widget.page.TxtChar;
import static android.view.View.GONE;
import static android.view.View.VISIBLE;
@@ -1741,6 +1743,9 @@ public class ReadActivity extends BaseActivity implements ColorPickerDialogListe
longPressMenu.hidePopupListWindow();
break;
case MotionEvent.ACTION_MOVE:
+ ImageView left = binding.getRoot().findViewWithTag("left");
+ ImageView right = binding.getRoot().findViewWithTag("right");
+
int dx = (int) event.getRawX() - lastX;
int dy = (int) event.getRawY() - lastY;
int l = v.getLeft() + dx;
@@ -1759,17 +1764,52 @@ public class ReadActivity extends BaseActivity implements ColorPickerDialogListe
int hh = binding.cursorLeft.getHeight();
int ww = binding.cursorLeft.getWidth();
- if (v.getId() == R.id.cursor_left) {
- binding.readPvContent.setFirstSelectTxtChar(binding.readPvContent.getCurrentTxtChar(lastX + ww, lastY - hh));
- if (binding.readPvContent.getFirstSelectTxtChar() != null) {
- binding.cursorLeft.setX(binding.readPvContent.getFirstSelectTxtChar().getTopLeftPosition().x - ww);
- binding.cursorLeft.setY(binding.readPvContent.getFirstSelectTxtChar().getBottomLeftPosition().y);
+ if (v.getId() == left.getId()) {
+ TxtChar first = binding.readPvContent.getCurrentTxtChar(lastX + ww, lastY - hh, true);
+ if (first != null) {
+ binding.readPvContent.setFirstSelectTxtChar(first);
}
+ left.setX(binding.readPvContent.getFirstSelectTxtChar().getBottomLeftPosition().x - ww);
+ left.setY(binding.readPvContent.getFirstSelectTxtChar().getBottomLeftPosition().y);
} else {
- binding.readPvContent.setLastSelectTxtChar(binding.readPvContent.getCurrentTxtChar(lastX - ww, lastY - hh));
- if (binding.readPvContent.getLastSelectTxtChar() != null) {
- binding.cursorRight.setX(binding.readPvContent.getLastSelectTxtChar().getBottomRightPosition().x);
- binding.cursorRight.setY(binding.readPvContent.getLastSelectTxtChar().getBottomRightPosition().y);
+ TxtChar last = binding.readPvContent.getCurrentTxtChar(lastX - ww, lastY - hh, false);
+ if (last != null) {
+ binding.readPvContent.setLastSelectTxtChar(last);
+ }
+ right.setX(binding.readPvContent.getLastSelectTxtChar().getBottomRightPosition().x);
+ right.setY(binding.readPvContent.getLastSelectTxtChar().getBottomRightPosition().y);
+ }
+
+
+ float leftX = left.getX();
+ float leftY = left.getY();
+ float rightX = right.getX();
+ float rightY = right.getY();
+
+ if ((leftY == rightY && leftX > rightX) || leftY > rightY) {
+ left.setTag("right");
+ left.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.ic_cursor_right));
+ right.setTag("left");
+ right.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.ic_cursor_left));
+
+ if (v.getId() == left.getId()) {
+ TxtChar last = binding.readPvContent.getLastSelectTxtChar();
+ last = binding.readPvContent.getNextTxtChar(last);
+ binding.readPvContent.setFirstSelectTxtChar(last);
+ if (last != null) {
+ right.setX(last.getBottomLeftPosition().x - ww);
+ right.setY(last.getBottomLeftPosition().y);
+ } else {
+ return true;
+ }
+ } else {
+ TxtChar first = binding.readPvContent.getFirstSelectTxtChar();
+ first = binding.readPvContent.getLastTxtChar(first);
+ binding.readPvContent.setLastSelectTxtChar(first);
+ if (first != null) {
+ left.setX(first.getBottomRightPosition().x);
+ left.setY(first.getBottomRightPosition().y);
+ }
}
}
@@ -1826,15 +1866,17 @@ public class ReadActivity extends BaseActivity implements ColorPickerDialogListe
* 显示选择
*/
private void cursorShow() {
- binding.cursorLeft.setVisibility(View.VISIBLE);
- binding.cursorRight.setVisibility(View.VISIBLE);
+ ImageView left = binding.getRoot().findViewWithTag("left");
+ ImageView right = binding.getRoot().findViewWithTag("right");
+ left.setVisibility(View.VISIBLE);
+ right.setVisibility(View.VISIBLE);
int hh = binding.cursorLeft.getHeight();
int ww = binding.cursorLeft.getWidth();
if (binding.readPvContent.getFirstSelectTxtChar() != null) {
- binding.cursorLeft.setX(binding.readPvContent.getFirstSelectTxtChar().getTopLeftPosition().x - ww);
- binding.cursorLeft.setY(binding.readPvContent.getFirstSelectTxtChar().getBottomLeftPosition().y);
- binding.cursorRight.setX(binding.readPvContent.getFirstSelectTxtChar().getBottomRightPosition().x);
- binding.cursorRight.setY(binding.readPvContent.getFirstSelectTxtChar().getBottomRightPosition().y);
+ left.setX(binding.readPvContent.getFirstSelectTxtChar().getTopLeftPosition().x - ww);
+ left.setY(binding.readPvContent.getFirstSelectTxtChar().getBottomLeftPosition().y);
+ right.setX(binding.readPvContent.getFirstSelectTxtChar().getBottomRightPosition().x);
+ right.setY(binding.readPvContent.getFirstSelectTxtChar().getBottomRightPosition().y);
}
}
diff --git a/app/src/main/java/xyz/fycz/myreader/widget/page/EpubPageLoader.java b/app/src/main/java/xyz/fycz/myreader/widget/page/EpubPageLoader.java
index de01364..e191663 100644
--- a/app/src/main/java/xyz/fycz/myreader/widget/page/EpubPageLoader.java
+++ b/app/src/main/java/xyz/fycz/myreader/widget/page/EpubPageLoader.java
@@ -53,6 +53,7 @@ public class EpubPageLoader extends PageLoader {
EpubPageLoader(PageView pageView, xyz.fycz.myreader.greendao.entity.Book bookShelfBean, Setting setting) {
super(pageView, bookShelfBean, setting);
+ mStatus = STATUS_PARING;
}
@Override
@@ -91,13 +92,17 @@ public class EpubPageLoader extends PageLoader {
@Override
public void onNext(xyz.fycz.myreader.greendao.entity.Book bookShelfBean) {
isChapterListPrepare = true;
+ //提示目录加载完成
+ if (mPageChangeListener != null) {
+ mPageChangeListener.onCategoryFinish(mChapterList);
+ }
// 加载并显示当前章节
openChapter();
}
@Override
public void onError(Throwable e) {
- error(STATUS_CATEGORY_ERROR, e.getMessage());
+ error(STATUS_PARSE_ERROR, e.getMessage());
}
});
}
@@ -249,9 +254,8 @@ public class EpubPageLoader extends PageLoader {
}
private Observable checkChapterList(xyz.fycz.myreader.greendao.entity.Book collBook) {
- if (mCollBook.getChapterTotalNum() != 0) {
- mChapterList = ChapterService.getInstance().findBookAllChapterByBookId(mCollBook.getId());
- mPageChangeListener.onCategoryFinish(mChapterList);
+ mChapterList = ChapterService.getInstance().findBookAllChapterByBookId(mCollBook.getId());
+ if (!mChapterList.isEmpty()) {
return Observable.just(collBook);
} else {
return Observable.create((ObservableOnSubscribe>) e -> {
diff --git a/app/src/main/java/xyz/fycz/myreader/widget/page/LocalPageLoader.java b/app/src/main/java/xyz/fycz/myreader/widget/page/LocalPageLoader.java
index b95b2e2..2279cf4 100644
--- a/app/src/main/java/xyz/fycz/myreader/widget/page/LocalPageLoader.java
+++ b/app/src/main/java/xyz/fycz/myreader/widget/page/LocalPageLoader.java
@@ -69,15 +69,15 @@ public class LocalPageLoader extends PageLoader {
// 对于文件是否存在,或者为空的判断,不作处理。 ==> 在文件打开前处理过了。
mBookFile = new File(mCollBook.getChapterUrl());
if (!mBookFile.exists()) {
- error(STATUS_CATEGORY_ERROR, "书籍源文件不存在\n" + mCollBook.getChapterUrl());
+ error(STATUS_PARSE_ERROR, "书籍源文件不存在\n" + mCollBook.getChapterUrl());
return;
}
mCharset = mCollBook.getInfoUrl();
// 判断文件是否已经加载过,并具有缓存
- if (mCollBook.getChapterTotalNum() != 0) {
+ mChapterList = mChapterService.findBookAllChapterByBookId(mCollBook.getId());
+ if (!mChapterList.isEmpty()) {
- mChapterList = mChapterService.findBookAllChapterByBookId(mCollBook.getId());
isChapterListPrepare = true;
//提示目录加载完成
diff --git a/app/src/main/java/xyz/fycz/myreader/widget/page/PageLoader.java b/app/src/main/java/xyz/fycz/myreader/widget/page/PageLoader.java
index 5611a0d..377cdf9 100644
--- a/app/src/main/java/xyz/fycz/myreader/widget/page/PageLoader.java
+++ b/app/src/main/java/xyz/fycz/myreader/widget/page/PageLoader.java
@@ -32,13 +32,11 @@ import xyz.fycz.myreader.model.audio.ReadAloudService;
import xyz.fycz.myreader.util.IOUtils;
import xyz.fycz.myreader.util.ToastUtils;
import xyz.fycz.myreader.util.help.ChapterContentHelp;
-import xyz.fycz.myreader.util.help.StringHelper;
import xyz.fycz.myreader.util.utils.BitmapUtil;
import xyz.fycz.myreader.util.utils.MeUtils;
import xyz.fycz.myreader.util.utils.RxUtils;
import xyz.fycz.myreader.util.utils.ScreenUtils;
import xyz.fycz.myreader.util.utils.StringUtils;
-import xyz.fycz.myreader.widget.page2.TxtLine;
import java.io.BufferedReader;
import java.io.File;
@@ -46,6 +44,7 @@ import java.io.IOException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
/**
* Created by fengyue on 20-11-21
@@ -785,7 +784,7 @@ public abstract class PageLoader {
error(STATUS_ERROR, msg);
}
- public void error(int status, String msg){
+ public void error(int status, String msg) {
//加载错误
mStatus = status;
errorMsg = msg;
@@ -1044,10 +1043,10 @@ public abstract class PageLoader {
tip = "章节内容为空";
break;
case STATUS_PARING:
- tip = "正在拆分章节请等待...";
+ tip = "正在解析文件请等待...";
break;
case STATUS_PARSE_ERROR:
- tip = "文件解析错误";
+ tip = "文件解析错误\n" + errorMsg;
break;
case STATUS_CATEGORY_EMPTY:
tip = "目录列表为空";
@@ -1056,7 +1055,8 @@ public abstract class PageLoader {
tip = "目录加载失败\n" + errorMsg;
break;
}
- if (mStatus == STATUS_ERROR || mStatus == STATUS_CATEGORY_ERROR) {
+ if (mStatus == STATUS_ERROR || mStatus == STATUS_CATEGORY_ERROR
+ || mStatus == STATUS_PARSE_ERROR) {
drawErrorMsg(canvas, tip, 0);
} else {
//将提示语句放到正中间
@@ -2061,6 +2061,10 @@ public abstract class PageLoader {
}
}
+ enum Detect {
+ None, Left, Right
+ }
+
/**
* --------------------
* 检测获取按压坐标所在位置的字符,没有的话返回null
@@ -2068,7 +2072,7 @@ public abstract class PageLoader {
* author: huangwei
* 2017年7月4日上午10:23:19
*/
- TxtChar detectPressTxtChar(float down_X2, float down_Y2) {
+ TxtChar detectPressTxtChar(float down_X2, float down_Y2, Detect detect) {
TxtPage txtPage = mCurPage;
if (txtPage == null) return null;
List txtLines = txtPage.txtLists;
@@ -2076,14 +2080,24 @@ public abstract class PageLoader {
for (TxtLine l : txtLines) {
List txtChars = l.getCharsData();
if (txtChars != null) {
- for (TxtChar c : txtChars) {
+ for (int i = 0; i < txtChars.size(); i++) {
+ TxtChar c = txtChars.get(i);
Point leftPoint = c.getBottomLeftPosition();
Point rightPoint = c.getBottomRightPosition();
if (leftPoint != null && down_Y2 > leftPoint.y) {
break;// 说明是在下一行
}
- if (leftPoint != null && rightPoint != null && down_X2 >= leftPoint.x && down_X2 <= rightPoint.x) {
- return c;
+ if (leftPoint != null && rightPoint != null) {
+ boolean flag = down_X2 >= leftPoint.x && down_X2 <= rightPoint.x;
+ switch (detect) {
+ case Left:
+ flag = flag || (i == 0 && down_X2 < leftPoint.x);
+ break;
+ case Right:
+ flag = flag || (i == txtChars.size() - 1 && down_X2 > rightPoint.x);
+ break;
+ }
+ if (flag) return c;
}
}
@@ -2092,6 +2106,42 @@ public abstract class PageLoader {
return null;
}
+ TxtChar detectLastTxtChar(TxtChar txtChar) {
+ TxtChar last = txtChar;
+ TxtPage txtPage = mCurPage;
+ if (txtPage == null) return txtChar;
+ List txtLines = txtPage.txtLists;
+ if (txtLines == null) return txtChar;
+ for (TxtLine l : txtLines) {
+ List txtChars = l.getCharsData();
+ if (txtChars != null) {
+ for (TxtChar c : txtChars) {
+ if (c != null && c.getIndex() == txtChar.getIndex()) return last;
+ last = c;
+ }
+ }
+ }
+ return txtChar;
+ }
+
+ TxtChar detectNextTxtChar(TxtChar txtChar) {
+ TxtPage txtPage = mCurPage;
+ boolean isNext = false;
+ if (txtPage == null) return txtChar;
+ List txtLines = txtPage.txtLists;
+ if (txtLines == null) return txtChar;
+ for (TxtLine l : txtLines) {
+ List txtChars = l.getCharsData();
+ if (txtChars != null) {
+ for (TxtChar c : txtChars) {
+ if (isNext) return c;
+ if (c != null && c.getIndex() == txtChar.getIndex()) isNext = true;
+ }
+ }
+ }
+ return txtChar;
+ }
+
public boolean isPrev() {
return isPrev;
}
diff --git a/app/src/main/java/xyz/fycz/myreader/widget/page/PageView.java b/app/src/main/java/xyz/fycz/myreader/widget/page/PageView.java
index 4e70e1a..48a0bbb 100644
--- a/app/src/main/java/xyz/fycz/myreader/widget/page/PageView.java
+++ b/app/src/main/java/xyz/fycz/myreader/widget/page/PageView.java
@@ -26,7 +26,6 @@ import xyz.fycz.myreader.util.utils.FileUtils;
import xyz.fycz.myreader.util.utils.SnackbarUtils;
import xyz.fycz.myreader.webapi.crawler.base.ReadCrawler;
import xyz.fycz.myreader.widget.animation.*;
-import xyz.fycz.myreader.widget.page2.TxtLine;
/**
* Created by Administrator on 2016/8/29 0029.
@@ -125,7 +124,7 @@ public class PageView extends View {
performLongClick();
if (mStartX > 0 && mStartY > 0) {// 说明还没释放,是长按事件
isLongPress = true;//长按
- TxtChar p = mPageLoader.detectPressTxtChar(mStartX, mStartY);//找到长按的点
+ TxtChar p = mPageLoader.detectPressTxtChar(mStartX, mStartY, PageLoader.Detect.None);//找到长按的点
firstSelectTxtChar = p;//设置开始位置字符
lastSelectTxtChar = p;//设置结束位置字符
selectMode = SelectMode.PressSelectText;//设置模式为长按选择
@@ -628,8 +627,16 @@ public class PageView extends View {
}
//根据当前坐标返回文字
- public TxtChar getCurrentTxtChar(float x, float y) {
- return mPageLoader.detectPressTxtChar(x, y);
+ public TxtChar getCurrentTxtChar(float x, float y, boolean left) {
+ return mPageLoader.detectPressTxtChar(x, y, left ? PageLoader.Detect.Left : PageLoader.Detect.Right);
+ }
+
+ public TxtChar getLastTxtChar(TxtChar txtChar){
+ return mPageLoader.detectLastTxtChar(txtChar);
+ }
+
+ public TxtChar getNextTxtChar(TxtChar txtChar){
+ return mPageLoader.detectNextTxtChar(txtChar);
}
private void drawOaleSeletLinesBg(Canvas canvas) {// 绘制选中背景
diff --git a/app/src/main/java/xyz/fycz/myreader/widget/page/TxtLine.kt b/app/src/main/java/xyz/fycz/myreader/widget/page/TxtLine.kt
index 9667781..d7694c0 100644
--- a/app/src/main/java/xyz/fycz/myreader/widget/page/TxtLine.kt
+++ b/app/src/main/java/xyz/fycz/myreader/widget/page/TxtLine.kt
@@ -1,6 +1,4 @@
-package xyz.fycz.myreader.widget.page2
-
-import xyz.fycz.myreader.widget.page.TxtChar
+package xyz.fycz.myreader.widget.page
class TxtLine {
diff --git a/app/src/main/java/xyz/fycz/myreader/widget/page/TxtPage.java b/app/src/main/java/xyz/fycz/myreader/widget/page/TxtPage.java
index 630a418..02e9b7f 100644
--- a/app/src/main/java/xyz/fycz/myreader/widget/page/TxtPage.java
+++ b/app/src/main/java/xyz/fycz/myreader/widget/page/TxtPage.java
@@ -2,8 +2,6 @@ package xyz.fycz.myreader.widget.page;
import java.util.List;
-import xyz.fycz.myreader.widget.page2.TxtLine;
-
public class TxtPage {
int position;
String title;
diff --git a/app/src/main/res/layout/activity_read.xml b/app/src/main/res/layout/activity_read.xml
index ed184f7..8982090 100644
--- a/app/src/main/res/layout/activity_read.xml
+++ b/app/src/main/res/layout/activity_read.xml
@@ -82,6 +82,7 @@
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@color/colorBackground"
+ android:orientation="vertical">
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ layout="@layout/toolbar" />
+
+ android:id="@+id/iv_refresh_search"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentEnd="true"
+ android:layout_centerInParent="true"
+ android:padding="8dp"
+ android:background="?android:attr/selectableItemBackground"
+ app:srcCompat="@drawable/ic_refresh" />
+
+ android:id="@+id/iv_stop_search"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerInParent="true"
+ android:background="?android:attr/selectableItemBackground"
+ android:layout_toStartOf="@+id/iv_refresh_search"
+ android:padding="8dp"
+ app:srcCompat="@drawable/ic_stop_black_24dp" />
+ android:id="@+id/rpb"
+ android:layout_width="match_parent"
+ android:layout_height="3dp"
+ android:visibility="visible" />