diff --git a/app/src/androidTest/java/xyz/fycz/myreader/ExampleInstrumentedTest.java b/app/src/androidTest/java/xyz/fycz/myreader/ExampleInstrumentedTest.java index db8d9cc..0b87f68 100644 --- a/app/src/androidTest/java/xyz/fycz/myreader/ExampleInstrumentedTest.java +++ b/app/src/androidTest/java/xyz/fycz/myreader/ExampleInstrumentedTest.java @@ -30,8 +30,8 @@ public class ExampleInstrumentedTest { @Test public void test() { ReadService readService = new ReadService(); - readService.initSynthesizer(); - readService.startSynthesizer("科幻电影是我们从小就爱看的电影题材,我们也都梦想过生活在那样的科幻世界里。科幻片,顾名思义即“科学幻想片”,是“以科学幻想为内容的故事片,其基本特点是从今天已知的科学原理和科学成就出发,对未来的世界或遥远的过去的情景作幻想式的描述。”"); + //readService.initSynthesizer(); + //readService.startSynthesizer("科幻电影是我们从小就爱看的电影题材,我们也都梦想过生活在那样的科幻世界里。科幻片,顾名思义即“科学幻想片”,是“以科学幻想为内容的故事片,其基本特点是从今天已知的科学原理和科学成就出发,对未来的世界或遥远的过去的情景作幻想式的描述。”"); } } \ No newline at end of file diff --git a/app/src/androidTest/java/xyz/fycz/myreader/TestAudioPlay.java b/app/src/androidTest/java/xyz/fycz/myreader/TestAudioPlay.java index f5a5e55..fff9e7b 100644 --- a/app/src/androidTest/java/xyz/fycz/myreader/TestAudioPlay.java +++ b/app/src/androidTest/java/xyz/fycz/myreader/TestAudioPlay.java @@ -11,8 +11,8 @@ public class TestAudioPlay { public void test() { ReadService readService = new ReadService(); - readService.initSynthesizer(); - readService.startSynthesizer("科幻电影是我们从小就爱看的电影题材,我们也都梦想过生活在那样的科幻世界里。科幻片,顾名思义即“科学幻想片”,是“以科学幻想为内容的故事片,其基本特点是从今天已知的科学原理和科学成就出发,对未来的世界或遥远的过去的情景作幻想式的描述。”"); + //readService.initSynthesizer(); + //readService.startSynthesizer("科幻电影是我们从小就爱看的电影题材,我们也都梦想过生活在那样的科幻世界里。科幻片,顾名思义即“科学幻想片”,是“以科学幻想为内容的故事片,其基本特点是从今天已知的科学原理和科学成就出发,对未来的世界或遥远的过去的情景作幻想式的描述。”"); } } 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 7b95886..db52a95 100644 --- a/app/src/main/java/xyz/fycz/myreader/common/APPCONST.java +++ b/app/src/main/java/xyz/fycz/myreader/common/APPCONST.java @@ -10,10 +10,10 @@ import java.io.File; public class APPCONST { - public static String publicKey = "";//服务端公钥 + public static String publicKey = "fyds1.0";//服务端公钥 public static String privateKey;//app私钥 public final static String s = "11940364935628058505"; - public static final String KEY = ""; + public static final String KEY = "readerByFengyue"; public static final String ALARM_SCHEDULE_MSG = "alarm_schedule_msg"; diff --git a/app/src/main/java/xyz/fycz/myreader/entity/ReadBookControl.java b/app/src/main/java/xyz/fycz/myreader/entity/ReadBookControl.java deleted file mode 100644 index 32a1d00..0000000 --- a/app/src/main/java/xyz/fycz/myreader/entity/ReadBookControl.java +++ /dev/null @@ -1,813 +0,0 @@ -//Copyright (c) 2017. 章钦豪. All rights reserved. -package xyz.fycz.myreader.entity; - -import android.content.ContentResolver; -import android.content.Context; -import android.content.SharedPreferences; -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.Color; -import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.ColorDrawable; -import android.graphics.drawable.Drawable; -import android.provider.Settings; -import android.util.DisplayMetrics; - - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import xyz.fycz.myreader.application.MyApplication; -import xyz.fycz.myreader.util.SharedPreUtils; -import xyz.fycz.myreader.util.utils.BitmapUtil; -import xyz.fycz.myreader.util.utils.MeUtils; - -import static xyz.fycz.myreader.widget.page2.PageLoader.DEFAULT_MARGIN_WIDTH; - - -public class ReadBookControl { - private static final int DEFAULT_BG = 1; - private int textDrawableIndex = DEFAULT_BG; - private List> textDrawable; - private Bitmap bgBitmap; - private int screenDirection; - private int speechRate; - private boolean speechRateFollowSys; - private int textSize; - private int textColor; - private boolean bgIsColor; - private int bgColor; - private float lineMultiplier; - private float paragraphSize; - private int pageMode; - private Boolean hideStatusBar; - private Boolean hideNavigationBar; - private String fontPath; - private int textConvert; - private int navBarColor; - private Boolean textBold; - private Boolean canClickTurn; - private Boolean canKeyTurn; - private Boolean readAloudCanKeyTurn; - private int CPM; - private Boolean clickAllNext; - private Boolean showTitle; - private Boolean showTimeBattery; - private Boolean showLine; - private Boolean darkStatusIcon; - private int indent; - private int screenTimeOut; - private int paddingLeft; - private int paddingTop; - private int paddingRight; - private int paddingBottom; - private int tipPaddingLeft; - private int tipPaddingTop; - private int tipPaddingRight; - private int tipPaddingBottom; - private float textLetterSpacing; - private boolean canSelectText; - public int minCPM = 200; - public int maxCPM = 2000; - private int defaultCPM = 500; - - private SharedPreferences preferences; - - private static ReadBookControl readBookControl; - - public static ReadBookControl getInstance() { - if (readBookControl == null) { - synchronized (ReadBookControl.class) { - if (readBookControl == null) { - readBookControl = new ReadBookControl(); - } - } - } - return readBookControl; - } - - private ReadBookControl() { - preferences = SharedPreUtils.getInstance().getSharedReadable(); - initTextDrawable(); - updateReaderSettings(); - } - - public void updateReaderSettings() { - this.hideStatusBar = preferences.getBoolean("hide_status_bar", false); - this.hideNavigationBar = preferences.getBoolean("hide_navigation_bar", false); - this.indent = preferences.getInt("indent", 2); - this.textSize = preferences.getInt("textSize", 20); - this.canClickTurn = preferences.getBoolean("canClickTurn", true); - this.canKeyTurn = preferences.getBoolean("canKeyTurn", true); - this.readAloudCanKeyTurn = preferences.getBoolean("readAloudCanKeyTurn", false); - this.lineMultiplier = preferences.getFloat("lineMultiplier", 1); - this.paragraphSize = preferences.getFloat("paragraphSize", 1); - this.CPM = preferences.getInt("CPM", defaultCPM) > maxCPM - ? minCPM : preferences.getInt("CPM", defaultCPM); - this.clickAllNext = preferences.getBoolean("clickAllNext", false); - this.fontPath = preferences.getString("fontPath", null); - this.textConvert = preferences.getInt("textConvertInt", 0); - this.textBold = preferences.getBoolean("textBold", false); - this.speechRate = preferences.getInt("speechRate", 10); - this.speechRateFollowSys = preferences.getBoolean("speechRateFollowSys", true); - this.showTitle = preferences.getBoolean("showTitle", true); - this.showTimeBattery = preferences.getBoolean("showTimeBattery", true); - this.showLine = preferences.getBoolean("showLine", true); - this.screenTimeOut = preferences.getInt("screenTimeOut", 0); - this.paddingLeft = preferences.getInt("paddingLeft", DEFAULT_MARGIN_WIDTH); - this.paddingTop = preferences.getInt("paddingTop", 0); - this.paddingRight = preferences.getInt("paddingRight", DEFAULT_MARGIN_WIDTH); - this.paddingBottom = preferences.getInt("paddingBottom", 0); - this.tipPaddingLeft = preferences.getInt("tipPaddingLeft", DEFAULT_MARGIN_WIDTH); - this.tipPaddingTop = preferences.getInt("tipPaddingTop", 0); - this.tipPaddingRight = preferences.getInt("tipPaddingRight", DEFAULT_MARGIN_WIDTH); - this.tipPaddingBottom = preferences.getInt("tipPaddingBottom", 0); - this.pageMode = preferences.getInt("pageMode", 0); - this.screenDirection = preferences.getInt("screenDirection", 0); - this.navBarColor = preferences.getInt("navBarColorInt", 0); - this.textLetterSpacing = preferences.getFloat("textLetterSpacing", 0); - this.canSelectText = preferences.getBoolean("canSelectText", false); - initTextDrawableIndex(); - } - - //阅读背景 - private void initTextDrawable() { - if (null == textDrawable) { - textDrawable = new ArrayList<>(); - Map temp1 = new HashMap<>(); - temp1.put("textColor", Color.parseColor("#3E3D3B")); - temp1.put("bgIsColor", 1); - temp1.put("textBackground", Color.parseColor("#F3F3F3")); - temp1.put("darkStatusIcon", 1); - textDrawable.add(temp1); - - Map temp2 = new HashMap<>(); - temp2.put("textColor", Color.parseColor("#5E432E")); - temp2.put("bgIsColor", 1); - temp2.put("textBackground", Color.parseColor("#C6BAA1")); - temp2.put("darkStatusIcon", 1); - textDrawable.add(temp2); - - Map temp3 = new HashMap<>(); - temp3.put("textColor", Color.parseColor("#22482C")); - temp3.put("bgIsColor", 1); - temp3.put("textBackground", Color.parseColor("#E1F1DA")); - temp3.put("darkStatusIcon", 1); - textDrawable.add(temp3); - - Map temp4 = new HashMap<>(); - temp4.put("textColor", Color.parseColor("#FFFFFF")); - temp4.put("bgIsColor", 1); - temp4.put("textBackground", Color.parseColor("#015A86")); - temp4.put("darkStatusIcon", 0); - textDrawable.add(temp4); - - Map temp5 = new HashMap<>(); - temp5.put("textColor", Color.parseColor("#808080")); - temp5.put("bgIsColor", 1); - temp5.put("textBackground", Color.parseColor("#000000")); - temp5.put("darkStatusIcon", 0); - textDrawable.add(temp5); - } - } - - public void initTextDrawableIndex() { - if (getIsNightTheme()) { - textDrawableIndex = preferences.getInt("textDrawableIndexNight", 4); - } else { - textDrawableIndex = preferences.getInt("textDrawableIndex", DEFAULT_BG); - } - if (textDrawableIndex == -1) { - textDrawableIndex = DEFAULT_BG; - } - initPageStyle(); - setTextDrawable(); - } - - @SuppressWarnings("ConstantConditions") - private void initPageStyle() { - int bgCustom = getBgCustom(textDrawableIndex); - if ((bgCustom == 2 || bgCustom == 3) && getBgPath(textDrawableIndex) != null) { - bgIsColor = false; - String bgPath = getBgPath(textDrawableIndex); - Resources resources = MyApplication.getApplication().getResources(); - DisplayMetrics dm = resources.getDisplayMetrics(); - int width = dm.widthPixels; - int height = dm.heightPixels; - if (bgCustom == 2) { - bgBitmap = BitmapUtil.getFitSampleBitmap(bgPath, width, height); - } else { - bgBitmap = MeUtils.getFitAssetsSampleBitmap(MyApplication.getApplication().getAssets(), bgPath, width, height); - } - if (bgBitmap != null) { - return; - } - } else if (getBgCustom(textDrawableIndex) == 1) { - bgIsColor = true; - bgColor = getBgColor(textDrawableIndex); - return; - } - bgIsColor = true; - bgColor = textDrawable.get(textDrawableIndex).get("textBackground"); - } - - private void setTextDrawable() { - darkStatusIcon = getDarkStatusIcon(textDrawableIndex); - textColor = getTextColor(textDrawableIndex); - } - - public int getTextColor(int textDrawableIndex) { - if (preferences.getInt("textColor" + textDrawableIndex, 0) != 0) { - return preferences.getInt("textColor" + textDrawableIndex, 0); - } else { - return getDefaultTextColor(textDrawableIndex); - } - } - - public void setTextColor(int textDrawableIndex, int textColor) { - preferences.edit() - .putInt("textColor" + textDrawableIndex, textColor) - .apply(); - } - - @SuppressWarnings("ConstantConditions") - public Drawable getBgDrawable(int textDrawableIndex, Context context, int width, int height) { - int color; - try { - Bitmap bitmap = null; - switch (getBgCustom(textDrawableIndex)) { - case 3: - bitmap = MeUtils.getFitAssetsSampleBitmap(context.getAssets(), getBgPath(textDrawableIndex), width, height); - if (bitmap != null) { - return new BitmapDrawable(context.getResources(), bitmap); - } - case 2: - bitmap = BitmapUtil.getFitSampleBitmap(getBgPath(textDrawableIndex), width, height); - if (bitmap != null) { - return new BitmapDrawable(context.getResources(), bitmap); - } - break; - case 1: - color = getBgColor(textDrawableIndex); - return new ColorDrawable(color); - } - if (textDrawable.get(textDrawableIndex).get("bgIsColor") != 0) { - color = textDrawable.get(textDrawableIndex).get("textBackground"); - return new ColorDrawable(color); - } else { - return getDefaultBgDrawable(textDrawableIndex, context); - } - } catch (Exception e) { - if (textDrawable.get(textDrawableIndex).get("bgIsColor") != 0) { - color = textDrawable.get(textDrawableIndex).get("textBackground"); - return new ColorDrawable(color); - } else { - return getDefaultBgDrawable(textDrawableIndex, context); - } - } - } - - @SuppressWarnings("ConstantConditions") - public Drawable getDefaultBgDrawable(int textDrawableIndex, Context context) { - if (textDrawable.get(textDrawableIndex).get("bgIsColor") != 0) { - return new ColorDrawable(textDrawable.get(textDrawableIndex).get("textBackground")); - } else { - return context.getResources().getDrawable(getDefaultBg(textDrawableIndex)); - } - } - - public int getBgCustom(int textDrawableIndex) { - return preferences.getInt("bgCustom" + textDrawableIndex, 0); - } - - public void setBgCustom(int textDrawableIndex, int bgCustom) { - preferences.edit() - .putInt("bgCustom" + textDrawableIndex, bgCustom) - .apply(); - } - - public String getBgPath(int textDrawableIndex) { - return preferences.getString("bgPath" + textDrawableIndex, null); - } - - public void setBgPath(int textDrawableIndex, String bgUri) { - preferences.edit() - .putString("bgPath" + textDrawableIndex, bgUri) - .apply(); - } - - @SuppressWarnings("ConstantConditions") - public int getDefaultTextColor(int textDrawableIndex) { - return textDrawable.get(textDrawableIndex).get("textColor"); - } - - @SuppressWarnings("ConstantConditions") - private int getDefaultBg(int textDrawableIndex) { - return textDrawable.get(textDrawableIndex).get("textBackground"); - } - - public int getBgColor(int index) { - return preferences.getInt("bgColor" + index, Color.parseColor("#1e1e1e")); - } - - public void setBgColor(int index, int bgColor) { - preferences.edit() - .putInt("bgColor" + index, bgColor) - .apply(); - } - - private boolean getIsNightTheme() { - return MyApplication.getApplication().isNightTheme(); - } - - public boolean getImmersionStatusBar() { - return preferences.getBoolean("immersionStatusBar", false); - } - - public void setImmersionStatusBar(boolean immersionStatusBar) { - preferences.edit() - .putBoolean("immersionStatusBar", immersionStatusBar) - .apply(); - } - - public int getTextSize() { - return textSize; - } - - public void setTextSize(int textSize) { - this.textSize = textSize; - preferences.edit() - .putInt("textSize", textSize) - .apply(); - } - - public int getTextColor() { - return textColor; - } - - public boolean bgIsColor() { - return bgIsColor; - } - - public Drawable getTextBackground(Context context) { - if (bgIsColor) { - return new ColorDrawable(bgColor); - } - return new BitmapDrawable(context.getResources(), bgBitmap); - } - - public int getBgColor() { - return bgColor; - } - - public boolean bgBitmapIsNull() { - return bgBitmap == null || bgBitmap.isRecycled(); - } - - public Bitmap getBgBitmap() { - return bgBitmap.copy(Bitmap.Config.ARGB_8888, true); - } - - public int getTextDrawableIndex() { - return textDrawableIndex; - } - - public void setTextDrawableIndex(int textDrawableIndex) { - this.textDrawableIndex = textDrawableIndex; - if (getIsNightTheme()) { - preferences.edit() - .putInt("textDrawableIndexNight", textDrawableIndex) - .apply(); - } else { - preferences.edit() - .putInt("textDrawableIndex", textDrawableIndex) - .apply(); - } - setTextDrawable(); - } - - public void setTextConvert(int textConvert) { - this.textConvert = textConvert; - preferences.edit() - .putInt("textConvertInt", textConvert) - .apply(); - } - - public void setNavBarColor(int navBarColor) { - this.navBarColor = navBarColor; - preferences.edit() - .putInt("navBarColorInt", navBarColor) - .apply(); - } - - public int getNavBarColor() { - return navBarColor; - } - - - public void setTextBold(boolean textBold) { - this.textBold = textBold; - preferences.edit() - .putBoolean("textBold", textBold) - .apply(); - } - - public void setReadBookFont(String fontPath) { - this.fontPath = fontPath; - preferences.edit() - .putString("fontPath", fontPath) - .apply(); - } - - public String getFontPath() { - return fontPath; - } - - public int getTextConvert() { - return textConvert == -1 ? 2 : textConvert; - } - - public Boolean getTextBold() { - return textBold; - } - - public Boolean getCanKeyTurn(Boolean isPlay) { - if (!canKeyTurn) { - return false; - } else if (readAloudCanKeyTurn) { - return true; - } else { - return !isPlay; - } - } - - public Boolean getCanKeyTurn() { - return canKeyTurn; - } - - public void setCanKeyTurn(Boolean canKeyTurn) { - this.canKeyTurn = canKeyTurn; - preferences.edit() - .putBoolean("canKeyTurn", canKeyTurn) - .apply(); - } - - public Boolean getAloudCanKeyTurn() { - return readAloudCanKeyTurn; - } - - public void setAloudCanKeyTurn(Boolean canAloudKeyTurn) { - this.readAloudCanKeyTurn = canAloudKeyTurn; - preferences.edit() - .putBoolean("readAloudCanKeyTurn", canAloudKeyTurn) - .apply(); - } - - public Boolean getCanClickTurn() { - return canClickTurn; - } - - public void setCanClickTurn(Boolean canClickTurn) { - this.canClickTurn = canClickTurn; - preferences.edit() - .putBoolean("canClickTurn", canClickTurn) - .apply(); - } - - public float getTextLetterSpacing() { - return textLetterSpacing; - } - - public void setTextLetterSpacing(float textLetterSpacing) { - this.textLetterSpacing = textLetterSpacing; - preferences.edit() - .putFloat("textLetterSpacing", textLetterSpacing) - .apply(); - } - - public float getLineMultiplier() { - return lineMultiplier; - } - - public void setLineMultiplier(float lineMultiplier) { - this.lineMultiplier = lineMultiplier; - preferences.edit() - .putFloat("lineMultiplier", lineMultiplier) - .apply(); - } - - public float getParagraphSize() { - return paragraphSize; - } - - public void setParagraphSize(float paragraphSize) { - this.paragraphSize = paragraphSize; - preferences.edit() - .putFloat("paragraphSize", paragraphSize) - .apply(); - } - - public int getCPM() { - return CPM; - } - - public void setCPM(int cpm) { - if (cpm < minCPM || cpm > maxCPM) cpm = defaultCPM; - this.CPM = cpm; - preferences.edit() - .putInt("CPM", cpm) - .apply(); - } - - public Boolean getClickAllNext() { - return clickAllNext; - } - - public void setClickAllNext(Boolean clickAllNext) { - this.clickAllNext = clickAllNext; - preferences.edit() - .putBoolean("clickAllNext", clickAllNext) - .apply(); - } - - public int getSpeechRate() { - return speechRate; - } - - public void setSpeechRate(int speechRate) { - this.speechRate = speechRate; - preferences.edit() - .putInt("speechRate", speechRate) - .apply(); - } - - public boolean isSpeechRateFollowSys() { - return speechRateFollowSys; - } - - public void setSpeechRateFollowSys(boolean speechRateFollowSys) { - this.speechRateFollowSys = speechRateFollowSys; - preferences.edit() - .putBoolean("speechRateFollowSys", speechRateFollowSys) - .apply(); - } - - public Boolean getShowTitle() { - return showTitle; - } - - public void setShowTitle(Boolean showTitle) { - this.showTitle = showTitle; - preferences.edit() - .putBoolean("showTitle", showTitle) - .apply(); - } - - public Boolean getShowTimeBattery() { - return showTimeBattery; - } - - public void setShowTimeBattery(Boolean showTimeBattery) { - this.showTimeBattery = showTimeBattery; - preferences.edit() - .putBoolean("showTimeBattery", showTimeBattery) - .apply(); - } - - public Boolean getHideStatusBar() { - return hideStatusBar; - } - - public void setHideStatusBar(Boolean hideStatusBar) { - this.hideStatusBar = hideStatusBar; - preferences.edit() - .putBoolean("hide_status_bar", hideStatusBar) - .apply(); - } - - public Boolean getToLh() { - return preferences.getBoolean("toLh", false); - } - - public void setToLh(Boolean toLh) { - preferences.edit() - .putBoolean("toLh", toLh) - .apply(); - } - - public Boolean getHideNavigationBar() { - return hideNavigationBar; - } - - public void setHideNavigationBar(Boolean hideNavigationBar) { - this.hideNavigationBar = hideNavigationBar; - preferences.edit() - .putBoolean("hide_navigation_bar", hideNavigationBar) - .apply(); - } - - public Boolean getShowLine() { - return showLine; - } - - public void setShowLine(Boolean showLine) { - this.showLine = showLine; - preferences.edit() - .putBoolean("showLine", showLine) - .apply(); - } - - public boolean getDarkStatusIcon() { - return darkStatusIcon; - } - - @SuppressWarnings("ConstantConditions") - public boolean getDarkStatusIcon(int textDrawableIndex) { - return preferences.getBoolean("darkStatusIcon" + textDrawableIndex, textDrawable.get(textDrawableIndex).get("darkStatusIcon") != 0); - } - - public void setDarkStatusIcon(int textDrawableIndex, Boolean darkStatusIcon) { - preferences.edit() - .putBoolean("darkStatusIcon" + textDrawableIndex, darkStatusIcon) - .apply(); - } - - public int getScreenTimeOut() { - return screenTimeOut; - } - - public void setScreenTimeOut(int screenTimeOut) { - this.screenTimeOut = screenTimeOut; - preferences.edit() - .putInt("screenTimeOut", screenTimeOut) - .apply(); - } - - public int getPaddingLeft() { - return paddingLeft; - } - - public void setPaddingLeft(int paddingLeft) { - this.paddingLeft = paddingLeft; - preferences.edit() - .putInt("paddingLeft", paddingLeft) - .apply(); - } - - public int getPaddingTop() { - return paddingTop; - } - - public void setPaddingTop(int paddingTop) { - this.paddingTop = paddingTop; - preferences.edit() - .putInt("paddingTop", paddingTop) - .apply(); - } - - public int getPaddingRight() { - return paddingRight; - } - - public void setPaddingRight(int paddingRight) { - this.paddingRight = paddingRight; - preferences.edit() - .putInt("paddingRight", paddingRight) - .apply(); - } - - public int getPaddingBottom() { - return paddingBottom; - } - - public void setPaddingBottom(int paddingBottom) { - this.paddingBottom = paddingBottom; - preferences.edit() - .putInt("paddingBottom", paddingBottom) - .apply(); - } - - public int getTipPaddingLeft() { - return tipPaddingLeft; - } - - public void setTipPaddingLeft(int tipPaddingLeft) { - this.tipPaddingLeft = tipPaddingLeft; - preferences.edit() - .putInt("tipPaddingLeft", tipPaddingLeft) - .apply(); - } - - public boolean isCanSelectText() { - return canSelectText; - } - - public void setCanSelectText(boolean canSelectText) { - this.canSelectText = canSelectText; - preferences.edit() - .putBoolean("canSelectText", canSelectText) - .apply(); - } - - public int getTipPaddingTop() { - return tipPaddingTop; - } - - public void setTipPaddingTop(int tipPaddingTop) { - this.tipPaddingTop = tipPaddingTop; - preferences.edit() - .putInt("tipPaddingTop", tipPaddingTop) - .apply(); - } - - public int getTipPaddingRight() { - return tipPaddingRight; - } - - public void setTipPaddingRight(int tipPaddingRight) { - this.tipPaddingRight = tipPaddingRight; - preferences.edit() - .putInt("tipPaddingRight", tipPaddingRight) - .apply(); - } - - public int getTipPaddingBottom() { - return tipPaddingBottom; - } - - public void setTipPaddingBottom(int tipPaddingBottom) { - this.tipPaddingBottom = tipPaddingBottom; - preferences.edit() - .putInt("tipPaddingBottom", tipPaddingBottom) - .apply(); - } - - public int getPageMode() { - return pageMode; - } - - public void setPageMode(int pageMode) { - this.pageMode = pageMode; - preferences.edit() - .putInt("pageMode", pageMode) - .apply(); - } - - public int getScreenDirection() { - return screenDirection; - } - - public void setScreenDirection(int screenDirection) { - this.screenDirection = screenDirection; - preferences.edit() - .putInt("screenDirection", screenDirection) - .apply(); - } - - public void setIndent(int indent) { - this.indent = indent; - preferences.edit() - .putInt("indent", indent) - .apply(); - } - - public int getIndent() { - return indent; - } - - public int getLight() { - return preferences.getInt("light", getScreenBrightness()); - } - - public void setLight(int light) { - preferences.edit() - .putInt("light", light) - .apply(); - } - - public Boolean getLightFollowSys() { - return preferences.getBoolean("lightFollowSys", true); - } - - public void setLightFollowSys(boolean isFollowSys) { - preferences.edit() - .putBoolean("lightFollowSys", isFollowSys) - .apply(); - } - - private int getScreenBrightness() { - int value = 0; - ContentResolver cr = MyApplication.getApplication().getContentResolver(); - try { - value = Settings.System.getInt(cr, Settings.System.SCREEN_BRIGHTNESS); - } catch (Settings.SettingNotFoundException ignored) { - } - return value; - } - - public boolean disableScrollClickTurn() { - return preferences.getBoolean("disableScrollClickTurn", false); - } -} diff --git a/app/src/main/java/xyz/fycz/myreader/source/UserDatabaseHelper.java b/app/src/main/java/xyz/fycz/myreader/source/UserDatabaseHelper.java deleted file mode 100644 index d7cf8a9..0000000 --- a/app/src/main/java/xyz/fycz/myreader/source/UserDatabaseHelper.java +++ /dev/null @@ -1,34 +0,0 @@ -package xyz.fycz.myreader.source; - -import android.content.Context; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteOpenHelper; - - -public class UserDatabaseHelper extends SQLiteOpenHelper { - - private static final String CREATE_USER = "create table UserCache(" - + "id integer primary key autoincrement, " - + "account varchar, " - + "password varchar) "; - - private Context mContext; - - public UserDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version){ - super(context,name,factory,version); - mContext = context; - - } - - @Override - public void onCreate(SQLiteDatabase db){ - db.execSQL(CREATE_USER); - } - - @Override - public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVerson){ - - } - - -} diff --git a/app/src/main/java/xyz/fycz/myreader/ui/activity/BookDetailedActivity.java b/app/src/main/java/xyz/fycz/myreader/ui/activity/BookDetailedActivity.java index 973ee9f..a411571 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/activity/BookDetailedActivity.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/activity/BookDetailedActivity.java @@ -82,6 +82,7 @@ import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @author fengyue @@ -748,10 +749,15 @@ public class BookDetailedActivity extends BaseActivity { back.compress(Bitmap.CompressFormat.PNG, 100, fos); fos.flush(); Log.i("tag", "saveBitmap success: " + share.getAbsolutePath()); + + back.recycle(); + img.recycle(); + QRCode.recycle(); + return share; } catch (Exception e) { e.printStackTrace(); - ToastUtils.showError(e.getLocalizedMessage()); + ToastUtils.showError(Objects.requireNonNull(e.getLocalizedMessage())); return null; } finally { IOUtils.close(fos); diff --git a/app/src/main/java/xyz/fycz/myreader/ui/popmenu/CustomizeLayoutMenu.java b/app/src/main/java/xyz/fycz/myreader/ui/popmenu/CustomizeLayoutMenu.java index 5063bfc..6e1bb35 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/popmenu/CustomizeLayoutMenu.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/popmenu/CustomizeLayoutMenu.java @@ -361,11 +361,11 @@ public class CustomizeLayoutMenu extends FrameLayout { holder.mTitle.setText(getFileName(path)); holder.mTitle.setTextColor(Color.parseColor("#909090")); try { - BitmapDrawable bitmapDrawable = (BitmapDrawable) holder.mImage.getDrawable(); + /*BitmapDrawable bitmapDrawable = (BitmapDrawable) holder.mImage.getDrawable(); //如果图片还未回收,先强制回收该图片 if (bitmapDrawable != null && !bitmapDrawable.getBitmap().isRecycled()) { bitmapDrawable.getBitmap().recycle(); - } + }*/ //该变现实的图片 Bitmap bmp = MeUtils.getFitAssetsSampleBitmap(context.getAssets(), getItemAssetsFile(position - 1), 256, 256); holder.mImage.setImageBitmap(bmp); diff --git a/app/src/main/java/xyz/fycz/myreader/util/DipPxUtil.java b/app/src/main/java/xyz/fycz/myreader/util/DipPxUtil.java deleted file mode 100644 index 5737f01..0000000 --- a/app/src/main/java/xyz/fycz/myreader/util/DipPxUtil.java +++ /dev/null @@ -1,24 +0,0 @@ -package xyz.fycz.myreader.util; - -import android.content.Context; - - - -public class DipPxUtil { - - /** - * 根据手机的分辨率从 dp 的单位 转成为 px(像素) - */ - public static int dp2px(Context context, float dpValue) { - final float scale = context.getResources().getDisplayMetrics().density; - return (int) (dpValue * scale+0.5f); - } - - /** - * 根据手机的分辨率从 px(像素) 的单位 转成为 dp - */ - public static int px2dip(Context context, float pxValue) { - final float scale = context.getResources().getDisplayMetrics().density; - return (int) (pxValue / scale + 0.5f); - } -} diff --git a/app/src/main/java/xyz/fycz/myreader/util/JsonArrayToObjectArray.java b/app/src/main/java/xyz/fycz/myreader/util/JsonArrayToObjectArray.java deleted file mode 100644 index 7a9cda6..0000000 --- a/app/src/main/java/xyz/fycz/myreader/util/JsonArrayToObjectArray.java +++ /dev/null @@ -1,24 +0,0 @@ -package xyz.fycz.myreader.util; - -import com.google.gson.Gson; - -import org.json.JSONArray; - -import java.util.ArrayList; - - - -public class JsonArrayToObjectArray { - - public static ArrayList getArray(String json, Class c) throws Exception { - ArrayList arrayList = new ArrayList<>(); - - JSONArray jsonArray = new JSONArray(json); - for (int i = 0; i < jsonArray.length(); i++) { - arrayList.add(new Gson().fromJson(jsonArray.getString(i), c)); - } - - return arrayList; - } - -} diff --git a/app/src/main/java/xyz/fycz/myreader/util/ToastUtils.java b/app/src/main/java/xyz/fycz/myreader/util/ToastUtils.java index ac4d836..c724edc 100644 --- a/app/src/main/java/xyz/fycz/myreader/util/ToastUtils.java +++ b/app/src/main/java/xyz/fycz/myreader/util/ToastUtils.java @@ -1,8 +1,8 @@ package xyz.fycz.myreader.util; -import android.os.Build; -import android.widget.Toast; import androidx.annotation.NonNull; +import androidx.core.content.ContextCompat; + import es.dmoral.toasty.Toasty; import xyz.fycz.myreader.R; import xyz.fycz.myreader.application.MyApplication; @@ -18,76 +18,51 @@ public class ToastUtils { } public static void show(@NonNull String msg) { - MyApplication.runOnUiThread(() -> { - if (showOld(msg)) return; - Toasty.custom(MyApplication.getmContext(), msg, - MyApplication.getmContext().getDrawable(R.drawable.ic_smile_face), - MyApplication.getmContext().getColor(R.color.toast_default), - MyApplication.getmContext().getColor(R.color.white), - Toasty.LENGTH_SHORT, true, true).show(); - }); + MyApplication.runOnUiThread(() -> Toasty.custom(MyApplication.getmContext(), msg, + ContextCompat.getDrawable(MyApplication.getmContext(), R.drawable.ic_smile_face), + MyApplication.getmContext().getResources().getColor(R.color.toast_default), + MyApplication.getmContext().getResources().getColor(R.color.white), + Toasty.LENGTH_SHORT, true, true).show()); } //红色 public static void showError(@NonNull String msg) { - MyApplication.runOnUiThread(() -> { - if (showOld(msg)) return; - Toasty.custom(MyApplication.getmContext(), msg, - MyApplication.getmContext().getDrawable(R.drawable.ic_error), - MyApplication.getmContext().getColor(R.color.toast_red), - MyApplication.getmContext().getColor(R.color.white), - Toasty.LENGTH_SHORT, true, true).show(); - }); + MyApplication.runOnUiThread(() -> Toasty.custom(MyApplication.getmContext(), msg, + ContextCompat.getDrawable(MyApplication.getmContext(), R.drawable.ic_error), + MyApplication.getmContext().getResources().getColor(R.color.toast_red), + MyApplication.getmContext().getResources().getColor(R.color.white), + Toasty.LENGTH_SHORT, true, true).show()); } //绿色 public static void showSuccess(@NonNull String msg) { - MyApplication.runOnUiThread(() -> { - if (showOld(msg)) return; - Toasty.custom(MyApplication.getmContext(), msg, - MyApplication.getmContext().getDrawable(R.drawable.ic_success), - MyApplication.getmContext().getColor(R.color.toast_green), - MyApplication.getmContext().getColor(R.color.white), - Toasty.LENGTH_SHORT, true, true).show(); - }); + MyApplication.runOnUiThread(() -> Toasty.custom(MyApplication.getmContext(), msg, + ContextCompat.getDrawable(MyApplication.getmContext(), R.drawable.ic_success), + MyApplication.getmContext().getResources().getColor(R.color.toast_green), + MyApplication.getmContext().getResources().getColor(R.color.white), + Toasty.LENGTH_SHORT, true, true).show()); } //蓝色 public static void showInfo(@NonNull String msg) { - MyApplication.runOnUiThread(() -> { - if (showOld(msg)) return; - Toasty.custom(MyApplication.getmContext(), msg, - MyApplication.getmContext().getDrawable(R.drawable.ic_smile_face), - MyApplication.getmContext().getColor(R.color.toast_blue), - MyApplication.getmContext().getColor(R.color.white), - Toasty.LENGTH_SHORT, true, true).show(); - }); + MyApplication.runOnUiThread(() -> Toasty.custom(MyApplication.getmContext(), msg, + ContextCompat.getDrawable(MyApplication.getmContext(), R.drawable.ic_smile_face), + MyApplication.getmContext().getResources().getColor(R.color.toast_blue), + MyApplication.getmContext().getResources().getColor(R.color.white), + Toasty.LENGTH_SHORT, true, true).show()); } //黄色 public static void showWarring(@NonNull String msg) { - MyApplication.runOnUiThread(() -> { - if (showOld(msg)) return; - Toasty.warning(MyApplication.getmContext(), msg, Toasty.LENGTH_SHORT, true).show(); - }); + MyApplication.runOnUiThread(() -> Toasty.warning(MyApplication.getmContext(), msg, Toasty.LENGTH_SHORT, true).show()); } public static void showExit(@NonNull String msg) { - MyApplication.runOnUiThread(() -> { - if (showOld(msg)) return; - Toasty.custom(MyApplication.getmContext(), msg, - MyApplication.getmContext().getDrawable(R.drawable.ic_cry_face), - MyApplication.getmContext().getColor(R.color.toast_blue), - MyApplication.getmContext().getColor(R.color.white), - Toasty.LENGTH_SHORT, true, true).show(); - }); + MyApplication.runOnUiThread(() -> Toasty.custom(MyApplication.getmContext(), msg, + ContextCompat.getDrawable(MyApplication.getmContext(), R.drawable.ic_cry_face), + MyApplication.getmContext().getResources().getColor(R.color.toast_blue), + MyApplication.getmContext().getResources().getColor(R.color.white), + Toasty.LENGTH_SHORT, true, true).show()); } - private static boolean showOld(@NonNull String msg){ - if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { - Toast.makeText(MyApplication.getmContext(), msg, Toast.LENGTH_SHORT).show(); - return true; - } - return false; - } } diff --git a/app/src/main/java/xyz/fycz/myreader/util/help/ChapterContentHelp.java b/app/src/main/java/xyz/fycz/myreader/util/help/ChapterContentHelp.java index 6bd6501..0d76240 100644 --- a/app/src/main/java/xyz/fycz/myreader/util/help/ChapterContentHelp.java +++ b/app/src/main/java/xyz/fycz/myreader/util/help/ChapterContentHelp.java @@ -4,7 +4,8 @@ import android.text.TextUtils; import com.luhuiguo.chinese.ChineseUtils; -import xyz.fycz.myreader.entity.ReadBookControl; +import xyz.fycz.myreader.application.SysManager; +import xyz.fycz.myreader.enums.Language; import xyz.fycz.myreader.greendao.entity.ReplaceRuleBean; import xyz.fycz.myreader.model.ReplaceRuleManager; @@ -22,14 +23,14 @@ public class ChapterContentHelp { * 转繁体 */ private String toTraditional(String content) { - int convertCTS = ReadBookControl.getInstance().getTextConvert(); + Language convertCTS = SysManager.getSetting().getLanguage(); switch (convertCTS) { - case 0: + case normal: break; - case 1: + case simplified: content = ChineseUtils.toSimplified(content); break; - case 2: + case traditional: content = ChineseUtils.toTraditional(content); break; } diff --git a/app/src/main/java/xyz/fycz/myreader/util/webdav/README.md b/app/src/main/java/xyz/fycz/myreader/util/webdav/README.md deleted file mode 100644 index f6ac57a..0000000 --- a/app/src/main/java/xyz/fycz/myreader/util/webdav/README.md +++ /dev/null @@ -1 +0,0 @@ -## 用于网络备份的WebDav \ No newline at end of file diff --git a/app/src/main/java/xyz/fycz/myreader/webapi/BaseApi.java b/app/src/main/java/xyz/fycz/myreader/webapi/BaseApi.java index 771da51..4d8c566 100644 --- a/app/src/main/java/xyz/fycz/myreader/webapi/BaseApi.java +++ b/app/src/main/java/xyz/fycz/myreader/webapi/BaseApi.java @@ -1,22 +1,17 @@ package xyz.fycz.myreader.webapi; -import xyz.fycz.myreader.application.SysManager; import xyz.fycz.myreader.common.ErrorCode; import xyz.fycz.myreader.entity.JsonModel; import xyz.fycz.myreader.util.HttpUtil; -import xyz.fycz.myreader.util.JsonArrayToObjectArray; import com.google.gson.Gson; + +import xyz.fycz.myreader.util.utils.GsonExtensionsKt; import xyz.fycz.myreader.webapi.callback.JsonCallback; import xyz.fycz.myreader.webapi.callback.ResultCallback; -import xyz.fycz.myreader.source.HttpDataSource; import xyz.fycz.myreader.util.ToastUtils; import java.util.Map; -/** - * Created by zhao on 2017/6/20. - */ - public class BaseApi { /** @@ -185,7 +180,7 @@ public class BaseApi { public void onFinish(JsonModel jsonModel) { if (jsonModel.isSuccess()) { try { - callback.onFinish(JsonArrayToObjectArray.getArray(jsonModel.getResult(),c), jsonModel.getError()); + callback.onFinish(GsonExtensionsKt.getGSON().fromJson(jsonModel.getResult(), c), jsonModel.getError()); }catch (Exception e){ callback.onError(e); e.printStackTrace(); diff --git a/app/src/main/java/xyz/fycz/myreader/webapi/BookStoreApi.java b/app/src/main/java/xyz/fycz/myreader/webapi/BookStoreApi.java index cffecef..85dbc4d 100644 --- a/app/src/main/java/xyz/fycz/myreader/webapi/BookStoreApi.java +++ b/app/src/main/java/xyz/fycz/myreader/webapi/BookStoreApi.java @@ -5,10 +5,6 @@ import xyz.fycz.myreader.entity.bookstore.BookType; import xyz.fycz.myreader.webapi.callback.ResultCallback; import xyz.fycz.myreader.webapi.crawler.base.FindCrawler; -/** - * Created by zhao on 2017/7/24. - */ - public class BookStoreApi extends BaseApi{ diff --git a/app/src/main/java/xyz/fycz/myreader/source/HttpDataSource.java b/app/src/main/java/xyz/fycz/myreader/webapi/HttpDataSource.java similarity index 99% rename from app/src/main/java/xyz/fycz/myreader/source/HttpDataSource.java rename to app/src/main/java/xyz/fycz/myreader/webapi/HttpDataSource.java index cba8af7..b319a8c 100644 --- a/app/src/main/java/xyz/fycz/myreader/source/HttpDataSource.java +++ b/app/src/main/java/xyz/fycz/myreader/webapi/HttpDataSource.java @@ -1,4 +1,4 @@ -package xyz.fycz.myreader.source; +package xyz.fycz.myreader.webapi; import android.graphics.Bitmap; import android.graphics.BitmapFactory; @@ -23,9 +23,6 @@ import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Map; -/** - * Created by zhao on 2016/4/16. - */ public class HttpDataSource { diff --git a/app/src/main/java/xyz/fycz/myreader/widget/custom/DragFloatBtnT.java b/app/src/main/java/xyz/fycz/myreader/widget/custom/DragFloatBtnT.java index b51299a..72beeef 100644 --- a/app/src/main/java/xyz/fycz/myreader/widget/custom/DragFloatBtnT.java +++ b/app/src/main/java/xyz/fycz/myreader/widget/custom/DragFloatBtnT.java @@ -7,7 +7,7 @@ import android.view.MotionEvent; import android.view.ViewGroup; import android.view.animation.BounceInterpolator; import com.google.android.material.floatingactionbutton.FloatingActionButton; -import xyz.fycz.myreader.util.DipPxUtil; +import xyz.fycz.myreader.util.utils.ScreenUtils; public class DragFloatBtnT extends FloatingActionButton { @@ -34,7 +34,7 @@ public class DragFloatBtnT extends FloatingActionButton { } private void init() { - padding = DipPxUtil.dp2px(getContext(), 15); + padding = ScreenUtils.dpToPx(15); } @SuppressLint("ClickableViewAccessibility") diff --git a/app/src/main/java/xyz/fycz/myreader/widget/page2/ChapterProvider.java b/app/src/main/java/xyz/fycz/myreader/widget/page2/ChapterProvider.java deleted file mode 100644 index b4b6528..0000000 --- a/app/src/main/java/xyz/fycz/myreader/widget/page2/ChapterProvider.java +++ /dev/null @@ -1,213 +0,0 @@ -package xyz.fycz.myreader.widget.page2; - -import android.text.Layout; -import android.text.StaticLayout; - -import androidx.annotation.NonNull; - -import java.util.ArrayList; -import java.util.List; - -import xyz.fycz.myreader.greendao.entity.Chapter; -import xyz.fycz.myreader.util.help.ChapterContentHelp; -import xyz.fycz.myreader.util.utils.NetworkUtils; - -class ChapterProvider { - private PageLoader pageLoader; - private ChapterContentHelp contentHelper = new ChapterContentHelp(); - - ChapterProvider(PageLoader pageLoader) { - this.pageLoader = pageLoader; - } - - TxtChapter dealLoadPageList(Chapter chapter, boolean isPrepare) { - TxtChapter txtChapter = new TxtChapter(chapter.getNumber()); - // 判断章节是否存在 - if (!isPrepare || pageLoader.noChapterData(chapter)) { - if (pageLoader instanceof PageLoaderNet && !NetworkUtils.isNetWorkAvailable()) { - txtChapter.setStatus(TxtChapter.Status.ERROR); - txtChapter.setMsg("网络连接不可用"); - } - return txtChapter; - } - String content; - try { - content = pageLoader.getChapterContent(chapter); - } catch (Exception e) { - txtChapter.setStatus(TxtChapter.Status.ERROR); - txtChapter.setMsg("读取内容出错\n" + e.getLocalizedMessage()); - return txtChapter; - } - if (content == null) { - txtChapter.setStatus(TxtChapter.Status.ERROR); - txtChapter.setMsg("缓存文件不存在"); - return txtChapter; - } - return loadPageList(chapter, content); - } - - /** - * 将章节数据,解析成页面列表 - * - * @param chapter:章节信息 - * @param content:章节的文本 - */ - private TxtChapter loadPageList(Chapter chapter, @NonNull String content) { - //生成的页面 - TxtChapter txtChapter = new TxtChapter(chapter.getNumber()); - /*if (pageLoader.book.isAudio()) { - txtChapter.setStatus(TxtChapter.Status.FINISH); - txtChapter.setMsg(content); - TxtPage page = new TxtPage(txtChapter.getTxtPageList().size()); - page.setTitle(chapter.getDurChapterName()); - page.addLine(chapter.getDurChapterName()); - page.addLine(content); - page.setTitleLines(1); - txtChapter.addPage(page); - addTxtPageLength(txtChapter, page.getContent().length()); - txtChapter.addPage(page); - return txtChapter; - }*/ - content = contentHelper.replaceContent(pageLoader.book.getName(), pageLoader.book.getTag(), content, pageLoader.book.getReplaceEnable()); - String[] allLine = content.split("\n"); - List lines = new ArrayList<>(); - List txtLists = new ArrayList<>();//记录每个字的位置 //pzl - int rHeight = pageLoader.mVisibleHeight - pageLoader.contentMarginHeight * 2; - int titleLinesCount = 0; - boolean showTitle = pageLoader.readBookControl.getShowTitle(); // 是否展示标题 - String paragraph = null; - if (showTitle) { - paragraph = contentHelper.replaceContent(pageLoader.book.getName(), pageLoader.book.getTag(), chapter.getTitle(), pageLoader.book.getReplaceEnable()); - paragraph = paragraph.trim() + "\n"; - } - int i = 1; - while (showTitle || i < allLine.length) { - // 重置段落 - if (!showTitle) { - paragraph = allLine[i].replaceAll("\\s", " ").trim(); - i++; - if (paragraph.equals("")) continue; - paragraph = pageLoader.indent + paragraph + "\n"; - } - addParagraphLength(txtChapter, paragraph.length()); - int wordCount; - String subStr; - while (paragraph.length() > 0) { - //当前空间,是否容得下一行文字 - if (showTitle) { - rHeight -= pageLoader.mTitlePaint.getTextSize(); - } else { - rHeight -= pageLoader.mTextPaint.getTextSize(); - } - // 一页已经填充满了,创建 TextPage - if (rHeight <= 0) { - // 创建Page - TxtPage page = new TxtPage(txtChapter.getTxtPageList().size()); - page.setTitle(chapter.getTitle()); - page.addLines(lines); - page.setTxtLists(new ArrayList<>(txtLists)); - page.setTitleLines(titleLinesCount); - txtChapter.addPage(page); - addTxtPageLength(txtChapter, page.getContent().length()); - // 重置Lines - lines.clear(); - txtLists.clear();//pzl - rHeight = pageLoader.mVisibleHeight - pageLoader.contentMarginHeight * 2; - titleLinesCount = 0; - - continue; - } - - //测量一行占用的字节数 - if (showTitle) { - Layout tempLayout = new StaticLayout(paragraph, pageLoader.mTitlePaint, pageLoader.mVisibleWidth, Layout.Alignment.ALIGN_NORMAL, 0, 0, false); - wordCount = tempLayout.getLineEnd(0); - } else { - Layout tempLayout = new StaticLayout(paragraph, pageLoader.mTextPaint, pageLoader.mVisibleWidth, Layout.Alignment.ALIGN_NORMAL, 0, 0, false); - wordCount = tempLayout.getLineEnd(0); - } - - subStr = paragraph.substring(0, wordCount); - if (!subStr.equals("\n")) { - //将一行字节,存储到lines中 - lines.add(subStr); - //begin pzl - //记录每个字的位置 - char[] cs = subStr.toCharArray(); - TxtLine txtList = new TxtLine();//每一行 - txtList.setCharsData(new ArrayList()); - for (char c : cs) { - String mesasrustr = String.valueOf(c); - float charwidth = pageLoader.mTextPaint.measureText(mesasrustr); - if (showTitle) { - charwidth = pageLoader.mTitlePaint.measureText(mesasrustr); - } - TxtChar txtChar = new TxtChar(); - txtChar.setChardata(c); - txtChar.setCharWidth(charwidth);//字宽 - txtChar.setIndex(66);//每页每个字的位置 - txtList.getCharsData().add(txtChar); - } - txtLists.add(txtList); - //end pzl - //设置段落间距 - if (showTitle) { - titleLinesCount += 1; - rHeight -= pageLoader.mTitleInterval; - } else { - rHeight -= pageLoader.mTextInterval; - } - } - //裁剪 - paragraph = paragraph.substring(wordCount); - } - - //增加段落的间距 - if (!showTitle && lines.size() != 0) { - rHeight = rHeight - pageLoader.mTextPara + pageLoader.mTextInterval; - } - - if (showTitle) { - rHeight = rHeight - pageLoader.mTitlePara + pageLoader.mTitleInterval; - showTitle = false; - } - } - - if (lines.size() != 0) { - //创建Page - TxtPage page = new TxtPage(txtChapter.getTxtPageList().size()); - page.setTitle(chapter.getTitle()); - page.addLines(lines); - page.setTxtLists(new ArrayList<>(txtLists)); - page.setTitleLines(titleLinesCount); - txtChapter.addPage(page); - addTxtPageLength(txtChapter, page.getContent().length()); - //重置Lines - lines.clear(); - txtLists.clear(); - } - if (txtChapter.getPageSize() > 0) { - txtChapter.setStatus(TxtChapter.Status.FINISH); - } else { - txtChapter.setStatus(TxtChapter.Status.ERROR); - txtChapter.setMsg("未加载到内容"); - } - return txtChapter; - } - - private void addTxtPageLength(TxtChapter txtChapter, int length) { - if (txtChapter.getTxtPageLengthList().isEmpty()) { - txtChapter.addTxtPageLength(length); - } else { - txtChapter.addTxtPageLength(txtChapter.getTxtPageLengthList().get(txtChapter.getTxtPageLengthList().size() - 1) + length); - } - } - - private void addParagraphLength(TxtChapter txtChapter, int length) { - if (txtChapter.getParagraphLengthList().isEmpty()) { - txtChapter.addParagraphLength(length); - } else { - txtChapter.addParagraphLength(txtChapter.getParagraphLengthList().get(txtChapter.getParagraphLengthList().size() - 1) + length); - } - } -} diff --git a/app/src/main/java/xyz/fycz/myreader/widget/page2/LocalPageLoader.java b/app/src/main/java/xyz/fycz/myreader/widget/page2/LocalPageLoader.java deleted file mode 100644 index c6d98f7..0000000 --- a/app/src/main/java/xyz/fycz/myreader/widget/page2/LocalPageLoader.java +++ /dev/null @@ -1,401 +0,0 @@ -package xyz.fycz.myreader.widget.page2; - -import android.util.Log; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import io.reactivex.Single; -import io.reactivex.SingleObserver; -import io.reactivex.SingleOnSubscribe; -import io.reactivex.disposables.Disposable; -import xyz.fycz.myreader.common.APPCONST; -import xyz.fycz.myreader.entity.Setting; -import xyz.fycz.myreader.greendao.entity.Book; -import xyz.fycz.myreader.greendao.entity.Chapter; -import xyz.fycz.myreader.greendao.service.ChapterService; -import xyz.fycz.myreader.util.IOUtils; -import xyz.fycz.myreader.util.StringHelper; -import xyz.fycz.myreader.util.utils.Charset; -import xyz.fycz.myreader.util.utils.FileUtils; -import xyz.fycz.myreader.util.utils.RxUtils; -import xyz.fycz.myreader.webapi.callback.ResultCallback; -import xyz.fycz.myreader.widget.page.BookChapterBean; - -import static xyz.fycz.myreader.widget.page.PageLoader.STATUS_PARING; - -/** - * Created by newbiechen on 17-7-1. - * 问题: - * 1. 异常处理没有做好 - */ - -public class LocalPageLoader extends PageLoader { - private static final String TAG = "LocalPageLoader"; - //默认从文件中获取数据的长度 - private final static int BUFFER_SIZE = 512 * 1024; - //没有标题的时候,每个章节的最大长度 - private final static int MAX_LENGTH_WITH_NO_CHAPTER = 10 * 1024; - - // "序(章)|前言" - private final static Pattern mPreChapterPattern = Pattern.compile("^(\\s{0,10})((\u5e8f[\u7ae0\u8a00]?)|(\u524d\u8a00)|(\u6954\u5b50))(\\s{0,10})$", Pattern.MULTILINE); - - //正则表达式章节匹配模式 - // "(第)([0-9零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]{1,10})([章节回集卷])(.*)" - private static final String[] CHAPTER_PATTERNS = new String[]{"^(.{0,8})(\u7b2c)([0-9\u96f6\u4e00\u4e8c\u4e24\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d\u5341\u767e\u5343\u4e07\u58f9\u8d30\u53c1\u8086\u4f0d\u9646\u67d2\u634c\u7396\u62fe\u4f70\u4edf]{1,10})([\u7ae0\u8282\u56de\u96c6\u5377])(.{0,30})$", - "^(\\s{0,4})([\\(\u3010\u300a]?(\u5377)?)([0-9\u96f6\u4e00\u4e8c\u4e24\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d\u5341\u767e\u5343\u4e07\u58f9\u8d30\u53c1\u8086\u4f0d\u9646\u67d2\u634c\u7396\u62fe\u4f70\u4edf]{1,10})([\\.:\uff1a\u0020\f\t])(.{0,30})$", - "^(\\s{0,4})([\\(\uff08\u3010\u300a])(.{0,30})([\\)\uff09\u3011\u300b])(\\s{0,2})$", - "^(\\s{0,4})(\u6b63\u6587)(.{0,20})$", - "^(.{0,4})(Chapter|chapter)(\\s{0,4})([0-9]{1,4})(.{0,30})$"}; - - //章节解析模式 - private Pattern mChapterPattern = null; - //获取书本的文件 - private File mBookFile; - //编码类型 - private String mCharset; - - private Disposable mChapterDisp = null; - - private ChapterService mChapterService; - - public LocalPageLoader(PageView pageView, Book book, Callback callback) { - super(pageView, book, callback); - this.mChapterService = ChapterService.getInstance(); - } - - - /** - * 未完成的部分: - * 1. 序章的添加 - * 2. 章节存在的书本的虚拟分章效果 - */ - public List loadChapters() throws IOException { - mBookFile = new File(book.getChapterUrl()); - //获取文件编码 - mCharset = FileUtils.getFileEncode(mBookFile.getAbsolutePath()); - List chapters = new ArrayList<>(); - RandomAccessFile bookStream = null; - boolean hasChapter = false; - //获取文件流 - bookStream = new RandomAccessFile(mBookFile, "r"); - //寻找匹配文章标题的正则表达式,判断是否存在章节名 - hasChapter = checkChapterType(bookStream); - //加载章节 - byte[] buffer = new byte[BUFFER_SIZE]; - //获取到的块起始点,在文件中的位置 - long curOffset = 0; - //block的个数 - int blockPos = 0; - //读取的长度 - int length; - - //获取文件中的数据到buffer,直到没有数据为止 - while ((length = bookStream.read(buffer, 0, buffer.length)) > 0) { - ++blockPos; - //如果存在Chapter - if (hasChapter) { - //将数据转换成String - String blockContent = new String(buffer, 0, length, mCharset); - //当前Block下使过的String的指针 - int seekPos = 0; - //进行正则匹配 - Matcher matcher = mChapterPattern.matcher(blockContent); - //如果存在相应章节 - while (matcher.find()) { - //获取匹配到的字符在字符串中的起始位置 - int chapterStart = matcher.start(); - - //如果 seekPos == 0 && nextChapterPos != 0 表示当前block处前面有一段内容 - //第一种情况一定是序章 第二种情况可能是上一个章节的内容 - if (seekPos == 0 && chapterStart != 0) { - //获取当前章节的内容 - String chapterContent = blockContent.substring(seekPos, chapterStart); - //设置指针偏移 - seekPos += chapterContent.length(); - - //如果当前对整个文件的偏移位置为0的话,那么就是序章 - if (curOffset == 0) { - //创建序章 - BookChapterBean preChapter = new BookChapterBean(); - preChapter.title = "序章"; - preChapter.start = 0; - preChapter.end = chapterContent.getBytes(mCharset).length; //获取String的byte值,作为最终值 - - //如果序章大小大于30才添加进去 - if (preChapter.end - preChapter.start > 30) { - chapters.add(preChapter); - } - - //创建当前章节 - BookChapterBean curChapter = new BookChapterBean(); - curChapter.title = matcher.group(); - curChapter.start = preChapter.end; - chapters.add(curChapter); - } - //否则就block分割之后,上一个章节的剩余内容 - else { - //获取上一章节 - BookChapterBean lastChapter = chapters.get(chapters.size() - 1); - //将当前段落添加上一章去 - lastChapter.end += chapterContent.getBytes(mCharset).length; - - //如果章节内容太小,则移除 - if (lastChapter.end - lastChapter.start < 30) { - chapters.remove(lastChapter); - } - - //创建当前章节 - BookChapterBean curChapter = new BookChapterBean(); - curChapter.title = matcher.group(); - curChapter.start = lastChapter.end; - chapters.add(curChapter); - } - } else { - //是否存在章节 - if (chapters.size() != 0) { - //获取章节内容 - String chapterContent = blockContent.substring(seekPos, matcher.start()); - seekPos += chapterContent.length(); - - //获取上一章节 - BookChapterBean lastChapter = chapters.get(chapters.size() - 1); - lastChapter.end = lastChapter.start + chapterContent.getBytes(mCharset).length; - - //如果章节内容太小,则移除 - if (lastChapter.end - lastChapter.start < 30) { - chapters.remove(lastChapter); - } - - //创建当前章节 - BookChapterBean curChapter = new BookChapterBean(); - curChapter.title = matcher.group(); - curChapter.start = lastChapter.end; - chapters.add(curChapter); - } - //如果章节不存在则创建章节 - else { - BookChapterBean curChapter = new BookChapterBean(); - curChapter.title = matcher.group(); - curChapter.start = 0; - chapters.add(curChapter); - } - } - } - } - //进行本地虚拟分章 - else { - //章节在buffer的偏移量 - int chapterOffset = 0; - //当前剩余可分配的长度 - int strLength = length; - //分章的位置 - int chapterPos = 0; - - while (strLength > 0) { - ++chapterPos; - //是否长度超过一章 - if (strLength > MAX_LENGTH_WITH_NO_CHAPTER) { - //在buffer中一章的终止点 - int end = length; - //寻找换行符作为终止点 - for (int i = chapterOffset + MAX_LENGTH_WITH_NO_CHAPTER; i < length; ++i) { - if (buffer[i] == Charset.BLANK) { - end = i; - break; - } - } - BookChapterBean chapter = new BookChapterBean(); - chapter.title = "第" + blockPos + "章" + "(" + chapterPos + ")"; - chapter.start = curOffset + chapterOffset + 1; - chapter.end = curOffset + end; - chapters.add(chapter); - //减去已经被分配的长度 - strLength = strLength - (end - chapterOffset); - //设置偏移的位置 - chapterOffset = end; - } else { - BookChapterBean chapter = new BookChapterBean(); - chapter.title = "第" + blockPos + "章" + "(" + chapterPos + ")"; - chapter.start = curOffset + chapterOffset + 1; - chapter.end = curOffset + length; - chapters.add(chapter); - strLength = 0; - } - } - } - - //block的偏移点 - curOffset += length; - - if (hasChapter) { - //设置上一章的结尾 - BookChapterBean lastChapter = chapters.get(chapters.size() - 1); - lastChapter.end = curOffset; - } - - //当添加的block太多的时候,执行GC - if (blockPos % 15 == 0) { - System.gc(); - System.runFinalization(); - } - } - - IOUtils.close(bookStream); - System.gc(); - System.runFinalization(); - return chapters; - } - - public void loadChapters(final ResultCallback resultCallback) { - // 通过RxJava异步处理分章事件 - Single.create((SingleOnSubscribe>) e -> { - e.onSuccess(loadChapters()); - }).compose(RxUtils::toSimpleSingle).subscribe(new SingleObserver>() { - @Override - public void onSubscribe(Disposable d) { - mChapterDisp = d; - } - - @Override - public void onSuccess(List chapters) { - mChapterDisp = null; - isChapterListPrepare = true; - List mChapters = new ArrayList<>(); - int i = 0; - for (BookChapterBean bookChapterBean : chapters) { - Chapter chapter = new Chapter(); - chapter.setBookId(book.getId()); - chapter.setTitle(bookChapterBean.getTitle().replace("\n", "").replaceAll("^\\s+|\\s+$", "")); - chapter.setId(StringHelper.getStringRandom(25)); - String content = getChapterContent(bookChapterBean); - if (StringHelper.isEmpty(content)) { - continue; - } - chapter.setNumber(i++); - mChapterService.saveOrUpdateChapter(chapter, content); - mChapters.add(chapter); - } - if (resultCallback != null) { - resultCallback.onFinish(mChapters, 1); - } - } - - @Override - public void onError(Throwable e) { - resultCallback.onError((Exception) e); - durDhapterError(e.getMessage()); - Log.d(TAG, "file load error:" + e.toString()); - } - }); - - } - - /** - * 从文件中提取一章的内容 - * - * @param chapter - * @return - */ - private String getChapterContent(BookChapterBean chapter) { - RandomAccessFile bookStream = null; - try { - bookStream = new RandomAccessFile(mBookFile, "r"); - bookStream.seek(chapter.start); - int extent = (int) (chapter.end - chapter.start); - byte[] content = new byte[extent]; - bookStream.read(content, 0, extent); - return new String(content, mCharset); - } catch (IOException e) { - e.printStackTrace(); - } finally { - IOUtils.close(bookStream); - } - return null; - } - - /** - * 1. 检查文件中是否存在章节名 - * 2. 判断文件中使用的章节名类型的正则表达式 - * - * @return 是否存在章节名 - */ - private boolean checkChapterType(RandomAccessFile bookStream) throws IOException { - //首先获取128k的数据 - byte[] buffer = new byte[BUFFER_SIZE / 4]; - int length = bookStream.read(buffer, 0, buffer.length); - //进行章节匹配 - for (String str : CHAPTER_PATTERNS) { - Pattern pattern = Pattern.compile(str, Pattern.MULTILINE); - Matcher matcher = pattern.matcher(new String(buffer, 0, length, mCharset)); - //如果匹配存在,那么就表示当前章节使用这种匹配方式 - if (matcher.find()) { - mChapterPattern = pattern; - //重置指针位置 - bookStream.seek(0); - return true; - } - } - - //重置指针位置 - bookStream.seek(0); - return false; - } - - - @Override - public void closeBook() { - super.closeBook(); - if (mChapterDisp != null) { - mChapterDisp.dispose(); - mChapterDisp = null; - } - } - - @Override - public void refreshChapterList() { - // 对于文件是否存在,或者为空的判断,不作处理。 ==> 在文件打开前处理过了。 - mBookFile = new File(book.getChapterUrl()); - - // 判断文件是否已经加载过,并具有缓存 - if (book.getChapterTotalNum() != 0) { - List chapters = mChapterService.findBookAllChapterByBookId(book.getId()); - - isChapterListPrepare = true; - // 目录加载完成,执行回调操作。 - if (!chapters.isEmpty()) { - callback.onCategoryFinish(chapters); - } - // 打开章节 - skipToChapter(book.getHisttoryChapterNum(), book.getLastReadPosition()); - } - } - - - @Override - public String getChapterContent(Chapter chapter) { - File file = new File(APPCONST.BOOK_CACHE_PATH + book.getId() - + File.separator + chapter.getTitle() + FileUtils.SUFFIX_FY); - if (!file.exists()) return null; - byte[] contentByte = FileUtils.getBytes(file); - return new String(contentByte, StandardCharsets.UTF_8); - } - - @Override - protected boolean noChapterData(Chapter chapter) { - return !ChapterService.isChapterCached(book.getId(), chapter.getTitle()); - } - - @Override - public void updateChapter() { - - } -} diff --git a/app/src/main/java/xyz/fycz/myreader/widget/page2/PageLoader.java b/app/src/main/java/xyz/fycz/myreader/widget/page2/PageLoader.java deleted file mode 100644 index c0953e1..0000000 --- a/app/src/main/java/xyz/fycz/myreader/widget/page2/PageLoader.java +++ /dev/null @@ -1,1866 +0,0 @@ -package xyz.fycz.myreader.widget.page2; - -import android.annotation.SuppressLint; -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Paint; -import android.graphics.Point; -import android.graphics.Rect; -import android.graphics.Typeface; -import android.os.Build; -import android.text.Layout; -import android.text.StaticLayout; -import android.text.TextPaint; -import android.text.TextUtils; -import android.widget.Toast; - -import java.text.DecimalFormat; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import io.reactivex.Single; -import io.reactivex.SingleObserver; -import io.reactivex.SingleOnSubscribe; -import io.reactivex.disposables.CompositeDisposable; -import io.reactivex.disposables.Disposable; -import xyz.fycz.myreader.R; -import xyz.fycz.myreader.entity.ReadBookControl; -import xyz.fycz.myreader.greendao.entity.Book; -import xyz.fycz.myreader.greendao.entity.Chapter; -import xyz.fycz.myreader.model.audio.ReadAloudService; -import xyz.fycz.myreader.util.help.ChapterContentHelp; -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.animation.PageAnimation; - -/** - * 页面加载器 - */ - -public abstract class PageLoader { - private static final String TAG = "PageLoader"; - - // 默认的显示参数配置 - private static final int DEFAULT_MARGIN_HEIGHT = 20; - public static final int DEFAULT_MARGIN_WIDTH = 15; - private static final int DEFAULT_TIP_SIZE = 12; - private static final float MAX_SCROLL_OFFSET = 100; - private static final int TIP_ALPHA = 180; - // 监听器 - Callback callback; - private Context mContext; - Book book; - // 页面显示类 - PageView mPageView; - private List chapterContainers = new ArrayList<>(); - - // 绘制电池的画笔 - private TextPaint mBatteryPaint; - // 绘制提示的画笔(章节名称和时间) - private TextPaint mTipPaint; - private float pageOffset = 0; - // 绘制标题的画笔 - TextPaint mTitlePaint; - // 绘制小说内容的画笔 - TextPaint mTextPaint; - // 绘制结束的画笔 - private TextPaint mTextEndPaint; - // 阅读器的配置选项 - ReadBookControl readBookControl = ReadBookControl.getInstance(); - //缩进 - String indent; - /*****************params**************************/ - // 判断章节列表是否加载完成 - boolean isChapterListPrepare; - private boolean isClose; - // 页面的翻页效果模式 - private PageAnimation.Mode mPageMode; - //书籍绘制区域的宽高 - int mVisibleWidth; - int mVisibleHeight; - //应用的宽高 - int mDisplayWidth; - private int mDisplayHeight; - //间距 - private int mMarginTop; - private int mMarginBottom; - private int mMarginLeft; - private int mMarginRight; - int contentMarginHeight; - private int tipMarginTop; - private int tipMarginBottom; - private int oneSpPx; - //标题的大小 - private int mTitleSize; - //字体的大小 - private int mTextSize; - private int mTextEndSize; - //行间距 - int mTextInterval; - //标题的行间距 - int mTitleInterval; - //段落距离(基于行间距的额外距离) - int mTextPara; - int mTitlePara; - private int textInterval; - private int textPara; - private int titleInterval; - private int titlePara; - private float tipBottomTop; - private float tipBottomBot; - private float tipDistance; - private float tipMarginLeft; - private float displayRightEnd; - private float tipVisibleWidth; - - private boolean hideStatusBar; - private boolean showTimeBattery; - - //电池的百分比 - private int mBatteryLevel; - - // 当前章 - int mCurChapterPos; - private int mCurPagePos; - private int readTextLength; //已读字符数 - private boolean resetReadAloud; //是否重新朗读 - private int readAloudParagraph; //正在朗读章节 - - Bitmap cover; - private int linePos = 0; - private boolean isLastPage = false; - - CompositeDisposable compositeDisposable; - //翻页时间 - private long skipPageTime = 0; - - /*****************************init params*******************************/ - PageLoader(PageView pageView, Book book, Callback callback) { - mPageView = pageView; - this.book = book; - this.callback = callback; - for (int i = 0; i < 3; i++) { - chapterContainers.add(new ChapterContainer()); - } - mContext = pageView.getContext(); - mCurChapterPos = book.getHisttoryChapterNum(); - mCurPagePos = book.getLastReadPosition(); - compositeDisposable = new CompositeDisposable(); - oneSpPx = ScreenUtils.spToPx(1); - // 初始化数据 - initData(); - // 初始化画笔 - initPaint(); - } - - private void initData() { - // 获取配置参数 - hideStatusBar = readBookControl.getHideStatusBar(); - showTimeBattery = hideStatusBar && readBookControl.getShowTimeBattery(); - mPageMode = PageAnimation.Mode.getPageMode(readBookControl.getPageMode()); - // 初始化参数 - indent = StringUtils.repeat(StringUtils.halfToFull(" "), readBookControl.getIndent()); - // 配置文字有关的参数 - setUpTextParams(); - } - - /** - * 屏幕大小变化处理 - */ - void prepareDisplay(int w, int h) { - // 获取PageView的宽高 - mDisplayWidth = w; - mDisplayHeight = h; - - // 设置边距 - mMarginTop = hideStatusBar ? - ScreenUtils.dpToPx(readBookControl.getTipPaddingTop() + readBookControl.getPaddingTop() + DEFAULT_MARGIN_HEIGHT) - : ScreenUtils.dpToPx(readBookControl.getPaddingTop()); - mMarginBottom = ScreenUtils.dpToPx(readBookControl.getTipPaddingBottom() + readBookControl.getPaddingBottom() + DEFAULT_MARGIN_HEIGHT); - mMarginLeft = ScreenUtils.dpToPx(readBookControl.getPaddingLeft()); - mMarginRight = ScreenUtils.dpToPx(readBookControl.getPaddingRight()); - contentMarginHeight = oneSpPx; - tipMarginTop = ScreenUtils.dpToPx(readBookControl.getTipPaddingTop() + DEFAULT_MARGIN_HEIGHT); - tipMarginBottom = ScreenUtils.dpToPx(readBookControl.getTipPaddingBottom() + DEFAULT_MARGIN_HEIGHT); - - Paint.FontMetrics fontMetrics = mTipPaint.getFontMetrics(); - float tipMarginTopHeight = (tipMarginTop + fontMetrics.top - fontMetrics.bottom) / 2; - float tipMarginBottomHeight = (tipMarginBottom + fontMetrics.top - fontMetrics.bottom) / 2; - tipBottomTop = tipMarginTopHeight - fontMetrics.top; - tipBottomBot = mDisplayHeight - fontMetrics.bottom - tipMarginBottomHeight; - tipDistance = ScreenUtils.dpToPx(DEFAULT_MARGIN_WIDTH); - tipMarginLeft = ScreenUtils.dpToPx(readBookControl.getTipPaddingLeft()); - float tipMarginRight = ScreenUtils.dpToPx(readBookControl.getTipPaddingRight()); - displayRightEnd = mDisplayWidth - tipMarginRight; - tipVisibleWidth = mDisplayWidth - tipMarginLeft - tipMarginRight; - - // 获取内容显示位置的大小 - mVisibleWidth = mDisplayWidth - mMarginLeft - mMarginRight; - mVisibleHeight = readBookControl.getHideStatusBar() - ? mDisplayHeight - mMarginTop - mMarginBottom - : mDisplayHeight - mMarginTop - mMarginBottom - mPageView.getStatusBarHeight(); - - // 设置翻页模式 - mPageView.setPageMode(mPageMode, mMarginTop, mMarginBottom); - skipToChapter(mCurChapterPos, mCurPagePos); - } - - /** - * 设置与文字相关的参数 - */ - private void setUpTextParams() { - // 文字大小 - mTextSize = ScreenUtils.spToPx(readBookControl.getTextSize()); - mTitleSize = mTextSize + oneSpPx; - mTextEndSize = mTextSize - oneSpPx; - // 行间距(大小为字体的一半) - mTextInterval = (int) (mTextSize * readBookControl.getLineMultiplier() / 2); - mTitleInterval = (int) (mTitleSize * readBookControl.getLineMultiplier() / 2); - // 段落间距(大小为字体的高度) - mTextPara = (int) (mTextSize * readBookControl.getLineMultiplier() * readBookControl.getParagraphSize() / 2); - mTitlePara = (int) (mTitleSize * readBookControl.getLineMultiplier() * readBookControl.getParagraphSize() / 2); - } - - /** - * 初始化画笔 - */ - private void initPaint() { - Typeface typeface; - try { - if (!TextUtils.isEmpty(readBookControl.getFontPath())) { - typeface = Typeface.createFromFile(readBookControl.getFontPath()); - } else { - typeface = Typeface.SANS_SERIF; - } - } catch (Exception e) { - Toast.makeText(mContext, "字体文件未找,到恢复默认字体", Toast.LENGTH_SHORT).show(); - readBookControl.setReadBookFont(null); - typeface = Typeface.SANS_SERIF; - } - // 绘制提示的画笔 - mTipPaint = new TextPaint(); - mTipPaint.setColor(readBookControl.getTextColor()); - mTipPaint.setTextAlign(Paint.Align.LEFT); // 绘制的起始点 - mTipPaint.setTextSize(ScreenUtils.spToPx(DEFAULT_TIP_SIZE)); // Tip默认的字体大小 - mTipPaint.setTypeface(Typeface.create(typeface, Typeface.NORMAL)); - mTipPaint.setAntiAlias(true); - mTipPaint.setSubpixelText(true); - - // 绘制标题的画笔 - mTitlePaint = new TextPaint(); - mTitlePaint.setColor(readBookControl.getTextColor()); - mTitlePaint.setTextSize(mTitleSize); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - mTitlePaint.setLetterSpacing(readBookControl.getTextLetterSpacing()); - } - mTitlePaint.setStyle(Paint.Style.FILL_AND_STROKE); - mTitlePaint.setTypeface(Typeface.create(typeface, Typeface.BOLD)); - mTitlePaint.setTextAlign(Paint.Align.CENTER); - mTitlePaint.setAntiAlias(true); - - // 绘制页面内容的画笔 - mTextPaint = new TextPaint(); - mTextPaint.setColor(readBookControl.getTextColor()); - mTextPaint.setTextSize(mTextSize); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - mTextPaint.setLetterSpacing(readBookControl.getTextLetterSpacing()); - } - int bold = readBookControl.getTextBold() ? Typeface.BOLD : Typeface.NORMAL; - mTextPaint.setTypeface(Typeface.create(typeface, bold)); - mTextPaint.setAntiAlias(true); - - // 绘制结束的画笔 - mTextEndPaint = new TextPaint(); - mTextEndPaint.setColor(readBookControl.getTextColor()); - mTextEndPaint.setTextSize(mTextEndSize); - mTextEndPaint.setTypeface(Typeface.create(typeface, Typeface.NORMAL)); - mTextEndPaint.setAntiAlias(true); - mTextEndPaint.setSubpixelText(true); - mTextEndPaint.setTextAlign(Paint.Align.CENTER); - - // 绘制电池的画笔 - mBatteryPaint = new TextPaint(); - mBatteryPaint.setAntiAlias(true); - mBatteryPaint.setDither(true); - mBatteryPaint.setTextSize(ScreenUtils.spToPx(DEFAULT_TIP_SIZE - 3)); - mBatteryPaint.setTypeface(Typeface.createFromAsset(mContext.getAssets(), "number.ttf")); - - setupTextInterval(); - // 初始化页面样式 - initPageStyle(); - } - - /** - * 设置文字相关参数 - */ - public void setTextSize() { - // 设置文字相关参数 - setUpTextParams(); - initPaint(); - skipToChapter(mCurChapterPos, mCurPagePos); - } - - private void setupTextInterval() { - textInterval = mTextInterval + (int) mTextPaint.getTextSize(); - textPara = mTextPara + (int) mTextPaint.getTextSize(); - titleInterval = mTitleInterval + (int) mTitlePaint.getTextSize(); - titlePara = mTitlePara + (int) mTextPaint.getTextSize(); - } - - /** - * 设置页面样式 - */ - private void initPageStyle() { - mTipPaint.setColor(readBookControl.getTextColor()); - mTitlePaint.setColor(readBookControl.getTextColor()); - mTextPaint.setColor(readBookControl.getTextColor()); - mBatteryPaint.setColor(readBookControl.getTextColor()); - mTextEndPaint.setColor(readBookControl.getTextColor()); - mTipPaint.setAlpha(TIP_ALPHA); - mBatteryPaint.setAlpha(TIP_ALPHA); - mTextEndPaint.setAlpha(TIP_ALPHA); - } - - /** - * 设置翻页动画 - */ - public void setPageMode(PageAnimation.Mode pageMode) { - mPageMode = pageMode; - mPageView.setPageMode(mPageMode, mMarginTop, mMarginBottom); - skipToChapter(mCurChapterPos, mCurPagePos); - } - - /** - * 设置内容与屏幕的间距 单位为 px - */ - public void upMargin() { - prepareDisplay(mDisplayWidth, mDisplayHeight); - } - - /** - * 刷新界面 - */ - public void refreshUi() { - initData(); - initPaint(); - mPageView.setPageMode(mPageMode, mMarginTop, mMarginBottom); - skipToChapter(mCurChapterPos, mCurPagePos); - } - - /** - * 跳转到上一章 - */ - public void skipPreChapter() { - if (mCurChapterPos <= 0) { - return; - } - - // 载入上一章。 - mCurChapterPos = mCurChapterPos - 1; - mCurPagePos = 0; - Collections.swap(chapterContainers, 2, 1); - Collections.swap(chapterContainers, 1, 0); - prevChapter().txtChapter = null; - parsePrevChapter(); - - chapterChangeCallback(); - openChapter(mCurPagePos); - pagingEnd(PageAnimation.Direction.NONE); - } - - /** - * 跳转到下一章 - */ - public boolean skipNextChapter() { - if (mCurChapterPos + 1 >= book.getChapterTotalNum()) { - return false; - } - - //载入下一章 - mCurChapterPos = mCurChapterPos + 1; - mCurPagePos = 0; - Collections.swap(chapterContainers, 0, 1); - Collections.swap(chapterContainers, 1, 2); - nextChapter().txtChapter = null; - parseNextChapter(); - - chapterChangeCallback(); - openChapter(mCurPagePos); - pagingEnd(PageAnimation.Direction.NONE); - return true; - } - - /** - * 跳转到指定章节页 - */ - public void skipToChapter(int chapterPos, int pagePos) { - // 设置参数 - mCurChapterPos = chapterPos; - mCurPagePos = pagePos; - - prevChapter().txtChapter = null; - curChapter().txtChapter = null; - nextChapter().txtChapter = null; - - openChapter(pagePos); - } - - /** - * 跳转到指定的页 - */ - public void skipToPage(int pos) { - if (!isChapterListPrepare) { - return; - } - openChapter(pos); - } - - /** - * 翻到上一页 - */ - public void skipToPrePage() { - if ((System.currentTimeMillis() - skipPageTime) > 300) { - mPageView.autoPrevPage(); - skipPageTime = System.currentTimeMillis(); - } - } - - /** - * 翻到下一页 - */ - public void skipToNextPage() { - if ((System.currentTimeMillis() - skipPageTime) > 300) { - mPageView.autoNextPage(); - skipPageTime = System.currentTimeMillis(); - } - } - - /** - * 翻到下一页,无动画 - */ - private void noAnimationToNextPage() { - if (getCurPagePos() < curChapter().txtChapter.getPageSize() - 1) { - skipToPage(getCurPagePos() + 1); - return; - } - skipNextChapter(); - } - - /** - * 更新时间 - */ - public void updateTime() { - if (readBookControl.getHideStatusBar() && readBookControl.getShowTimeBattery()) { - if (mPageMode == PageAnimation.Mode.SCROLL) { - mPageView.drawBackground(0); - } else { - upPage(); - } - mPageView.invalidate(); - } - } - - /** - * 更新电量 - */ - public boolean updateBattery(int level) { - if (mBatteryLevel == level) { - return false; - } - mBatteryLevel = level; - if (readBookControl.getHideStatusBar() && readBookControl.getShowTimeBattery()) { - if (mPageMode == PageAnimation.Mode.SCROLL) { - mPageView.drawBackground(0); - } else if (curChapter().txtChapter != null) { - upPage(); - } - mPageView.invalidate(); - return true; - } - return false; - } - - /** - * 获取当前页的状态 - */ - public TxtChapter.Status getPageStatus() { - return curChapter().txtChapter != null ? curChapter().txtChapter.getStatus() : TxtChapter.Status.LOADING; - } - - /** - * 获取当前页的页码 - */ - int getCurPagePos() { - return mCurPagePos; - } - - /** - * 更新状态 - */ - public void setStatus(TxtChapter.Status status) { - curChapter().txtChapter.setStatus(status); - reSetPage(); - mPageView.invalidate(); - } - - /** - * 加载错误 - */ - void durDhapterError(String msg) { - if (curChapter().txtChapter == null) { - curChapter().txtChapter = new TxtChapter(mCurChapterPos); - } - if (curChapter().txtChapter.getStatus() == TxtChapter.Status.FINISH) return; - curChapter().txtChapter.setStatus(TxtChapter.Status.ERROR); - curChapter().txtChapter.setMsg(msg); - if (mPageMode != PageAnimation.Mode.SCROLL) { - upPage(); - } else { - mPageView.drawPage(0); - } - mPageView.invalidate(); - } - - /** - * @return 当前章节所有内容 - */ - public String getAllContent() { - return getContentStartPage(0); - } - - /** - * @return 本页未读内容 - */ - public String getContent() { - if (curChapter().txtChapter == null) return null; - if (curChapter().txtChapter.getPageSize() == 0) return null; - TxtPage txtPage = curChapter().txtChapter.getPage(mCurPagePos); - StringBuilder s = new StringBuilder(); - int size = txtPage.size(); - int start = mPageMode == PageAnimation.Mode.SCROLL ? Math.min(Math.max(0, linePos), size - 1) : 0; - for (int i = start; i < size; i++) { - s.append(txtPage.getLine(i)); - } - return s.toString(); - } - - /** - * @return 本章未读内容 - */ - public String getUnReadContent() { - if (curChapter().txtChapter == null) return null; - //if (book.isAudio()) return curChapter().txtChapter.getMsg(); - if (curChapter().txtChapter.getTxtPageList().isEmpty()) return null; - StringBuilder s = new StringBuilder(); - String content = getContent(); - if (content != null) { - s.append(content); - } - content = getContentStartPage(mCurPagePos + 1); - if (content != null) { - s.append(content); - } - readTextLength = mCurPagePos > 0 ? curChapter().txtChapter.getPageLength(mCurPagePos - 1) : 0; - if (mPageMode == PageAnimation.Mode.SCROLL) { - for (int i = 0; i < Math.min(Math.max(0, linePos), curChapter().txtChapter.getPage(mCurPagePos).size() - 1); i++) { - readTextLength += curChapter().txtChapter.getPage(mCurPagePos).getLine(i).length(); - } - } - return s.toString(); - } - - /** - * * @return curPageLength 当前页字数 - */ - public int curPageLength() { - if (curChapter().txtChapter == null) return 0; - if (curChapter().txtChapter.getStatus() != TxtChapter.Status.FINISH) return 0; - String str; - int strLength = 0; - TxtPage txtPage = curChapter().txtChapter.getPage(mCurPagePos); - if (txtPage != null) { - for (int i = txtPage.getTitleLines(); i < txtPage.size(); ++i) { - str = txtPage.getLine(i); - strLength = strLength + str.length(); - } - } - return strLength; - } - - /** - * @param page 开始页数 - * @return 从page页开始的的当前章节所有内容 - */ - private String getContentStartPage(int page) { - if (curChapter().txtChapter == null) return null; - if (curChapter().txtChapter.getTxtPageList().isEmpty()) return null; - StringBuilder s = new StringBuilder(); - if (curChapter().txtChapter.getPageSize() > page) { - for (int i = page; i < curChapter().txtChapter.getPageSize(); i++) { - s.append(curChapter().txtChapter.getPage(i).getContent()); - } - } - return s.toString(); - } - - /** - * @param start 开始朗读字数 - */ - public void readAloudStart(int start) { - start = readTextLength + start; - int x = curChapter().txtChapter.getParagraphIndex(start); - if (readAloudParagraph != x) { - readAloudParagraph = x; - mPageView.drawPage(0); - mPageView.invalidate(); - mPageView.drawPage(-1); - mPageView.drawPage(1); - mPageView.invalidate(); - } - } - - /** - * @param readAloudLength 已朗读字数 - */ - public void readAloudLength(int readAloudLength) { - if (curChapter().txtChapter == null) return; - if (curChapter().txtChapter.getStatus() != TxtChapter.Status.FINISH) return; - if (curChapter().txtChapter.getPageLength(mCurPagePos) < 0) return; - if (mPageView.isRunning()) return; - readAloudLength = readTextLength + readAloudLength; - if (readAloudLength >= curChapter().txtChapter.getPageLength(mCurPagePos)) { - resetReadAloud = false; - noAnimationToNextPage(); - mPageView.invalidate(); - } - } - - /** - * 刷新章节列表 - */ - public abstract void refreshChapterList(); - - /** - * 获取章节的文本 - */ - protected abstract String getChapterContent(Chapter chapter) throws Exception; - - /** - * 章节数据是否存在 - */ - protected abstract boolean noChapterData(Chapter chapter); - - /** - * 打开当前章节指定页 - */ - void openChapter(int pagePos) { - mCurPagePos = pagePos; - if (!mPageView.isPrepare()) { - return; - } - - if (curChapter().txtChapter == null) { - curChapter().txtChapter = new TxtChapter(mCurChapterPos); - reSetPage(); - } else if (curChapter().txtChapter.getStatus() == TxtChapter.Status.FINISH) { - reSetPage(); - mPageView.invalidate(); - pagingEnd(PageAnimation.Direction.NONE); - return; - } - - // 如果章节目录没有准备好 - if (!isChapterListPrepare) { - curChapter().txtChapter.setStatus(TxtChapter.Status.LOADING); - reSetPage(); - mPageView.invalidate(); - return; - } - - // 如果获取到的章节目录为空 - if (callback.getChapterList().isEmpty()) { - curChapter().txtChapter.setStatus(TxtChapter.Status.CATEGORY_EMPTY); - reSetPage(); - mPageView.invalidate(); - return; - } - - parseCurChapter(); - resetPageOffset(); - } - - /** - * 重置页面 - */ - private void reSetPage() { - if (mPageMode == PageAnimation.Mode.SCROLL) { - resetPageOffset(); - mPageView.invalidate(); - } else { - upPage(); - } - } - - /** - * 更新页面 - */ - private void upPage() { - if (mPageMode != PageAnimation.Mode.SCROLL) { - mPageView.drawPage(0); - if (mCurPagePos > 0 || curChapter().txtChapter.getPosition() > 0) { - mPageView.drawPage(-1); - } - if (mCurPagePos < curChapter().txtChapter.getPageSize() - 1 || curChapter().txtChapter.getPosition() < callback.getChapterList().size() - 1) { - mPageView.drawPage(1); - } - } - } - - /** - * 翻页完成 - */ - void pagingEnd(PageAnimation.Direction direction) { - if (!isChapterListPrepare) { - return; - } - switch (direction) { - case NEXT: - if (mCurPagePos < curChapter().txtChapter.getPageSize() - 1) { - mCurPagePos = mCurPagePos + 1; - } else if (mCurChapterPos < book.getChapterTotalNum() - 1) { - mCurChapterPos = mCurChapterPos + 1; - mCurPagePos = 0; - Collections.swap(chapterContainers, 0, 1); - Collections.swap(chapterContainers, 1, 2); - nextChapter().txtChapter = null; - parseNextChapter(); - chapterChangeCallback(); - } - if (mPageMode != PageAnimation.Mode.SCROLL) { - mPageView.drawPage(1); - } - break; - case PREV: - if (mCurPagePos > 0) { - mCurPagePos = mCurPagePos - 1; - } else if (mCurChapterPos > 0) { - mCurChapterPos = mCurChapterPos - 1; - mCurPagePos = prevChapter().txtChapter.getPageSize() - 1; - Collections.swap(chapterContainers, 2, 1); - Collections.swap(chapterContainers, 1, 0); - prevChapter().txtChapter = null; - parsePrevChapter(); - chapterChangeCallback(); - } - if (mPageMode != PageAnimation.Mode.SCROLL) { - mPageView.drawPage(-1); - } - break; - } - mPageView.setContentDescription(getContent()); - book.setHisttoryChapterNum(mCurChapterPos); - book.setLastReadPosition(mCurPagePos); - callback.onPageChange(mCurChapterPos, getCurPagePos(), resetReadAloud); - resetReadAloud = true; - } - - /** - * 绘制页面 - * pageOnCur: 位于当前页的位置, 小于0上一页, 0 当前页, 大于0下一页 - */ - synchronized void drawPage(Bitmap bitmap, int pageOnCur) { - TxtChapter txtChapter; - TxtPage txtPage = null; - if (curChapter().txtChapter == null) { - curChapter().txtChapter = new TxtChapter(mCurChapterPos); - } - if (pageOnCur == 0) { //当前页 - txtChapter = curChapter().txtChapter; - txtPage = txtChapter.getPage(mCurPagePos); - } else if (pageOnCur < 0) { //上一页 - if (mCurPagePos > 0) { - txtChapter = curChapter().txtChapter; - txtPage = txtChapter.getPage(mCurPagePos - 1); - } else { - if (prevChapter().txtChapter == null) { - txtChapter = new TxtChapter(mCurChapterPos + 1); - txtChapter.setStatus(TxtChapter.Status.ERROR); - txtChapter.setMsg("未加载完成"); - } else { - txtChapter = prevChapter().txtChapter; - txtPage = txtChapter.getPage(txtChapter.getPageSize() - 1); - } - } - } else { //下一页 - if (mCurPagePos + 1 < curChapter().txtChapter.getPageSize()) { - txtChapter = curChapter().txtChapter; - txtPage = txtChapter.getPage(mCurPagePos + 1); - } else { - if (mCurChapterPos + 1 >= callback.getChapterList().size()) { - txtChapter = new TxtChapter(mCurChapterPos + 1); - txtChapter.setStatus(TxtChapter.Status.ERROR); - txtChapter.setMsg("没有下一页"); - } else if (nextChapter().txtChapter == null) { - txtChapter = new TxtChapter(mCurChapterPos + 1); - txtChapter.setStatus(TxtChapter.Status.ERROR); - txtChapter.setMsg("未加载完成"); - } else { - txtChapter = nextChapter().txtChapter; - txtPage = txtChapter.getPage(0); - } - } - } - if (bitmap != null) - drawBackground(bitmap, txtChapter, txtPage); - drawContent(bitmap, txtChapter, txtPage); - } - - /** - * 滚动模式绘制背景 - */ - void drawBackground(Canvas canvas) { - if (curChapter().txtChapter == null) { - curChapter().txtChapter = new TxtChapter(mCurChapterPos); - } - drawBackground(canvas, curChapter().txtChapter, curChapter().txtChapter.getPage(mCurPagePos)); - } - - /** - * 横翻模式绘制背景 - */ - private synchronized void drawBackground(Bitmap bitmap, TxtChapter txtChapter, TxtPage txtPage) { - if (bitmap == null) return; - Canvas canvas = new Canvas(bitmap); - if (!readBookControl.bgIsColor() && !readBookControl.bgBitmapIsNull()) { - Rect mDestRect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); - canvas.drawBitmap(readBookControl.getBgBitmap(), null, mDestRect, null); - } else { - canvas.drawColor(readBookControl.getBgColor()); - } - drawBackground(canvas, txtChapter, txtPage); - } - - /** - * 绘制背景 - */ - @SuppressLint("DefaultLocale") - private synchronized void drawBackground(final Canvas canvas, TxtChapter txtChapter, TxtPage txtPage) { - if (canvas == null) return; - if (!callback.getChapterList().isEmpty()) { - String title = callback.getChapterList().size() > txtChapter.getPosition() ? callback.getChapterList().get(txtChapter.getPosition()).getTitle() : ""; - title = ChapterContentHelp.getInstance().replaceContent(book.getName(), book.getTag(), title, book.getReplaceEnable()); - String page = (txtChapter.getStatus() != TxtChapter.Status.FINISH || txtPage == null) ? "" - : String.format("%d/%d", txtPage.getPosition() + 1, txtChapter.getPageSize()); - String progress = (txtChapter.getStatus() != TxtChapter.Status.FINISH) ? "" - : getReadProgress(mCurChapterPos, book.getChapterTotalNum(), mCurPagePos, curChapter().txtChapter.getPageSize()); - - float tipBottom; - float tipLeft; - //初始化标题的参数 - //需要注意的是:绘制text的y的起始点是text的基准线的位置,而不是从text的头部的位置 - if (!hideStatusBar) { //显示状态栏 - if (txtChapter.getStatus() != TxtChapter.Status.FINISH) { - if (isChapterListPrepare) { - //绘制标题 - title = TextUtils.ellipsize(title, mTipPaint, tipVisibleWidth, TextUtils.TruncateAt.END).toString(); - canvas.drawText(title, tipMarginLeft, tipBottomBot, mTipPaint); - } - } else { - //绘制总进度 - tipLeft = displayRightEnd - mTipPaint.measureText(progress); - canvas.drawText(progress, tipLeft, tipBottomBot, mTipPaint); - //绘制页码 - tipLeft = tipLeft - tipDistance - mTipPaint.measureText(page); - canvas.drawText(page, tipLeft, tipBottomBot, mTipPaint); - //绘制标题 - title = TextUtils.ellipsize(title, mTipPaint, tipLeft - tipDistance, TextUtils.TruncateAt.END).toString(); - canvas.drawText(title, tipMarginLeft, tipBottomBot, mTipPaint); - } - if (readBookControl.getShowLine()) { - //绘制分隔线 - tipBottom = mDisplayHeight - tipMarginBottom; - canvas.drawRect(tipMarginLeft, tipBottom, displayRightEnd, tipBottom + 2, mTipPaint); - } - } else { //隐藏状态栏 - if (getPageStatus() != TxtChapter.Status.FINISH) { - if (isChapterListPrepare) { - //绘制标题 - title = TextUtils.ellipsize(title, mTipPaint, tipVisibleWidth, TextUtils.TruncateAt.END).toString(); - canvas.drawText(title, tipMarginLeft, tipBottomTop, mTipPaint); - } - } else { - //绘制标题 - float titleTipLength = showTimeBattery ? tipVisibleWidth - mTipPaint.measureText(progress) - tipDistance : tipVisibleWidth; - title = TextUtils.ellipsize(title, mTipPaint, titleTipLength, TextUtils.TruncateAt.END).toString(); - canvas.drawText(title, tipMarginLeft, tipBottomTop, mTipPaint); - // 绘制页码 - canvas.drawText(page, tipMarginLeft, tipBottomBot, mTipPaint); - //绘制总进度 - float progressTipLeft = displayRightEnd - mTipPaint.measureText(progress); - float progressTipBottom = showTimeBattery ? tipBottomTop : tipBottomBot; - canvas.drawText(progress, progressTipLeft, progressTipBottom, mTipPaint); - } - if (readBookControl.getShowLine()) { - //绘制分隔线 - tipBottom = tipMarginTop - 2; - canvas.drawRect(tipMarginLeft, tipBottom, displayRightEnd, tipBottom + 2, mTipPaint); - } - } - } - - int visibleRight = (int) displayRightEnd; - if (hideStatusBar && showTimeBattery) { - //绘制当前时间 - String time = StringUtils.dateConvert(System.currentTimeMillis(), "HH:mm"); - float timeTipLeft = (mDisplayWidth - mTipPaint.measureText(time)) / 2; - canvas.drawText(time, timeTipLeft, tipBottomBot, mTipPaint); - - //绘制电池 - int polarHeight = ScreenUtils.dpToPx(4); - int polarWidth = ScreenUtils.dpToPx(2); - int border = 2; - int outFrameWidth = (int) mBatteryPaint.measureText("0000") + polarWidth; - int outFrameHeight = (int) mBatteryPaint.getTextSize() + oneSpPx; - int visibleBottom = mDisplayHeight - (tipMarginBottom - outFrameHeight) / 2; - - //电极的制作 - int polarLeft = visibleRight - polarWidth; - int polarTop = visibleBottom - (outFrameHeight + polarHeight) / 2; - Rect polar = new Rect(polarLeft, polarTop, visibleRight, polarTop + polarHeight); - - mBatteryPaint.setStyle(Paint.Style.FILL); - canvas.drawRect(polar, mBatteryPaint); - - //外框的制作 - int outFrameLeft = polarLeft - outFrameWidth; - int outFrameTop = visibleBottom - outFrameHeight; - Rect outFrame = new Rect(outFrameLeft, outFrameTop, polarLeft, visibleBottom); - - mBatteryPaint.setStyle(Paint.Style.STROKE); - mBatteryPaint.setStrokeWidth(border); - canvas.drawRect(outFrame, mBatteryPaint); - - //绘制电量 - mBatteryPaint.setStyle(Paint.Style.FILL); - Paint.FontMetrics fontMetrics = mBatteryPaint.getFontMetrics(); - String batteryLevel = String.valueOf(mBatteryLevel); - float batTextLeft = outFrameLeft + (outFrameWidth - mBatteryPaint.measureText(batteryLevel)) / 2; - float batTextBaseLine = visibleBottom - outFrameHeight / 2f - fontMetrics.top / 2 - fontMetrics.bottom / 2; - canvas.drawText(batteryLevel, batTextLeft, batTextBaseLine, mBatteryPaint); - } - } - - - /** - * 绘制内容 - */ - private synchronized void drawContent(Bitmap bitmap, TxtChapter txtChapter, TxtPage txtPage) { - if (bitmap == null) return; - Canvas canvas = new Canvas(bitmap); - if (mPageMode == PageAnimation.Mode.SCROLL) { - bitmap.eraseColor(Color.TRANSPARENT); - } - - Paint.FontMetrics fontMetricsForTitle = mTitlePaint.getFontMetrics(); - Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics(); - - if (txtChapter.getStatus() != TxtChapter.Status.FINISH) { - //绘制字体 - String tip = getStatusText(txtChapter); - drawErrorMsg(canvas, tip, 0); - } else { - float top = contentMarginHeight - fontMetrics.ascent; - if (mPageMode != PageAnimation.Mode.SCROLL) { - top += readBookControl.getHideStatusBar() ? mMarginTop : mPageView.getStatusBarHeight() + mMarginTop; - } - int ppp = 0;//pzl,文字位置 - //对标题进行绘制 - String str; - int strLength = 0; - boolean isLight; - for (int i = 0; i < txtPage.getTitleLines(); ++i) { - str = txtPage.getLine(i); - strLength = strLength + str.length(); - isLight = ReadAloudService.running && readAloudParagraph == 0; - mTitlePaint.setColor(isLight ? mContext.getResources().getColor(R.color.sys_color) : readBookControl.getTextColor()); - - //进行绘制 - canvas.drawText(str, mDisplayWidth / 2f, top, mTitlePaint); - - //pzl - float leftposition = mDisplayWidth / 2; - float rightposition = 0; - float bottomposition = top + mTitlePaint.getFontMetrics().descent; - float TextHeight = Math.abs(fontMetricsForTitle.ascent) + Math.abs(fontMetricsForTitle.descent); - - if (txtPage.getTxtLists() != null) { - for (TxtChar c : txtPage.getTxtLists().get(i).getCharsData()) { - rightposition = leftposition + c.getCharWidth(); - Point tlp = new Point(); - c.setTopLeftPosition(tlp); - tlp.x = (int) leftposition; - tlp.y = (int) (bottomposition - TextHeight); - - Point blp = new Point(); - c.setBottomLeftPosition(blp); - blp.x = (int) leftposition; - blp.y = (int) bottomposition; - - Point trp = new Point(); - c.setTopRightPosition(trp); - trp.x = (int) rightposition; - trp.y = (int) (bottomposition - TextHeight); - - Point brp = new Point(); - c.setBottomRightPosition(brp); - brp.x = (int) rightposition; - brp.y = (int) bottomposition; - ppp++; - c.setIndex(ppp); - - leftposition = rightposition; - } - } - - //设置尾部间距 - if (i == txtPage.getTitleLines() - 1) { - top += titlePara; - } else { - //行间距 - top += titleInterval; - } - } - - if (txtPage.getLines().isEmpty()) { - return; - } - //对内容进行绘制 - for (int i = txtPage.getTitleLines(); i < txtPage.size(); ++i) { - str = txtPage.getLine(i); - strLength = strLength + str.length(); - int paragraphLength = txtPage.getPosition() == 0 ? strLength : txtChapter.getPageLength(txtPage.getPosition() - 1) + strLength; - isLight = ReadAloudService.running && readAloudParagraph == txtChapter.getParagraphIndex(paragraphLength); - mTextPaint.setColor(isLight ? mContext.getResources().getColor(R.color.sys_color) : readBookControl.getTextColor()); - Layout tempLayout = new StaticLayout(str, mTextPaint, mVisibleWidth, Layout.Alignment.ALIGN_NORMAL, 0, 0, false); - float width = StaticLayout.getDesiredWidth(str, tempLayout.getLineStart(0), tempLayout.getLineEnd(0), mTextPaint); - if (needScale(str)) { - drawScaledText(canvas, str, width, mTextPaint, top, i, txtPage.getTxtLists()); - } else { - canvas.drawText(str, mMarginLeft, top, mTextPaint); - } - - //记录文字位置 --开始 pzl - float leftposition = mMarginLeft; - if (isFirstLineOfParagraph(str)) { - String blanks = StringUtils.halfToFull(" "); - //canvas.drawText(blanks, x, top, mTextPaint); - float bw = StaticLayout.getDesiredWidth(blanks, mTextPaint); - leftposition += bw; - } - float rightposition = 0; - float bottomposition = top + mTextPaint.getFontMetrics().descent; - float textHeight = Math.abs(fontMetrics.ascent) + Math.abs(fontMetrics.descent); - - if (txtPage.getTxtLists() != null) { - for (TxtChar c : txtPage.getTxtLists().get(i).getCharsData()) { - rightposition = leftposition + c.getCharWidth(); - Point tlp = new Point(); - c.setTopLeftPosition(tlp); - tlp.x = (int) leftposition; - tlp.y = (int) (bottomposition - textHeight); - - Point blp = new Point(); - c.setBottomLeftPosition(blp); - blp.x = (int) leftposition; - blp.y = (int) bottomposition; - - Point trp = new Point(); - c.setTopRightPosition(trp); - trp.x = (int) rightposition; - trp.y = (int) (bottomposition - textHeight); - - Point brp = new Point(); - c.setBottomRightPosition(brp); - brp.x = (int) rightposition; - brp.y = (int) bottomposition; - - leftposition = rightposition; - - ppp++; - c.setIndex(ppp); - } - } - //记录文字位置 --结束 pzl - - //设置尾部间距 - if (str.endsWith("\n")) { - top += textPara; - } else { - top += textInterval; - } - } - } - } - - public void drawCover(Canvas canvas, float top) { - } - - private int getCoverHeight() { - return cover == null ? 0 : cover.getHeight() + 20; - } - - /** - * 绘制内容-滚动 - */ - void drawContent(final Canvas canvas, float offset) { - - if (offset > MAX_SCROLL_OFFSET) { - offset = MAX_SCROLL_OFFSET; - } else if (offset < 0 - MAX_SCROLL_OFFSET) { - offset = -MAX_SCROLL_OFFSET; - } - - boolean pageChanged = false; - Paint.FontMetrics fontMetricsForTitle = mTitlePaint.getFontMetrics(); - Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics(); - - final float totalHeight = mVisibleHeight + titleInterval; - if (curChapter().txtChapter == null) { - curChapter().txtChapter = new TxtChapter(mCurChapterPos); - } - - if (!isLastPage || offset < 0) { - pageOffset += offset; - isLastPage = false; - } - // 首页 - if (pageOffset < 0 && mCurChapterPos == 0 && mCurPagePos == 0) { - pageOffset = 0; - } - - float cHeight = getFixedPageHeight(curChapter().txtChapter, mCurPagePos); - cHeight = cHeight > 0 ? cHeight : mVisibleHeight; - if (offset > 0 && pageOffset > cHeight) { - while (pageOffset > cHeight) { - switchToPageOffset(1); - pageOffset -= cHeight; - cHeight = getFixedPageHeight(curChapter().txtChapter, mCurPagePos); - cHeight = cHeight > 0 ? cHeight : mVisibleHeight; - pageChanged = true; - } - } else if (offset < 0 && pageOffset < 0) { - while (pageOffset < 0) { - switchToPageOffset(-1); - cHeight = getFixedPageHeight(curChapter().txtChapter, mCurPagePos); - cHeight = cHeight > 0 ? cHeight : mVisibleHeight; - pageOffset += cHeight; - pageChanged = true; - } - } - - if (pageChanged) { - chapterChangeCallback(); - pagingEnd(PageAnimation.Direction.NONE); - } - - float top = contentMarginHeight - mTextPaint.ascent() - pageOffset; - - int chapterPos = mCurChapterPos; - int pagePos = mCurPagePos; - boolean isLight; - int ppp = 0;//pzl,文字位置 - - if (curChapter().txtChapter.getStatus() != TxtChapter.Status.FINISH) { - String tip = getStatusText(curChapter().txtChapter); - drawErrorMsg(canvas, tip, pageOffset); - top += mVisibleHeight; - chapterPos += 1; - pagePos = 0; - } - String str; - linePos = 0; - boolean linePosSet = false; - boolean bookEnd = false; - float startHeight = -2 * titleInterval; - if (pageOffset < mTextPaint.getTextSize()) { - linePos = 0; - linePosSet = true; - } - while (top < totalHeight) { - TxtChapter chapter = chapterPos == mCurChapterPos ? curChapter().txtChapter : nextChapter().txtChapter; - if (chapter == null || chapterPos - mCurChapterPos > 1) break; - if (chapter.getStatus() != TxtChapter.Status.FINISH) { - String tip = getStatusText(chapter); - drawErrorMsg(canvas, tip, 0 - top); - top += mVisibleHeight; - chapterPos += 1; - pagePos = 0; - continue; - } - if (chapter.getPageSize() == 0) break; - TxtPage page = chapter.getPage(pagePos); - if (page.getLines().isEmpty()) break; - if (top > totalHeight) break; - float topi = top; - int strLength = 0; - isLight = ReadAloudService.running && readAloudParagraph == 0; - mTitlePaint.setColor(isLight ? mContext.getResources().getColor(R.color.sys_color) : readBookControl.getTextColor()); - for (int i = 0; i < page.getTitleLines(); i++) { - if (top > totalHeight) { - break; - } else if (top > startHeight) { - str = page.getLine(i); - strLength = strLength + str.length(); - //进行绘制 - canvas.drawText(str, mDisplayWidth / 2f, top, mTitlePaint); - //pzl - float leftposition = mDisplayWidth / 2f; - float rightPosition = 0; - float bottomPosition = top + mTitlePaint.getFontMetrics().descent; - float TextHeight = Math.abs(fontMetricsForTitle.ascent) + Math.abs(fontMetricsForTitle.descent); - - if (page.getTxtLists() != null) { - for (TxtChar c : page.getTxtLists().get(i).getCharsData()) { - rightPosition = leftposition + c.getCharWidth(); - Point tlp = new Point(); - c.setTopLeftPosition(tlp); - tlp.x = (int) leftposition; - tlp.y = (int) (bottomPosition - TextHeight); - - Point blp = new Point(); - c.setBottomLeftPosition(blp); - blp.x = (int) leftposition; - blp.y = (int) bottomPosition; - - Point trp = new Point(); - c.setTopRightPosition(trp); - trp.x = (int) rightPosition; - trp.y = (int) (bottomPosition - TextHeight); - - Point brp = new Point(); - c.setBottomRightPosition(brp); - brp.x = (int) rightPosition; - brp.y = (int) bottomPosition; - ppp++; - c.setIndex(ppp); - - leftposition = rightPosition; - } - } - //pzl - } - top += (i == page.getTitleLines() - 1) ? titlePara : titleInterval; - if (!linePosSet && chapterPos == mCurChapterPos && top > titlePara) { - linePos = i; - linePosSet = true; - } - } - if (top > totalHeight) break; - // 首页画封面 - if (pagePos == 0 && chapterPos == 0) { - drawCover(canvas, top); - top += getCoverHeight(); - } - if (top > totalHeight) break; - for (int i = page.getTitleLines(); i < page.size(); i++) { - str = page.getLine(i); - strLength = strLength + str.length(); - int paragraphLength = page.getPosition() == 0 ? strLength : chapter.getPageLength(page.getPosition() - 1) + strLength; - isLight = ReadAloudService.running && readAloudParagraph == chapter.getParagraphIndex(paragraphLength); - mTextPaint.setColor(isLight ? mContext.getResources().getColor(R.color.sys_color) : readBookControl.getTextColor()); - if (top > totalHeight) { - break; - } else if (top > startHeight) { - Layout tempLayout = new StaticLayout(str, mTextPaint, mVisibleWidth, Layout.Alignment.ALIGN_NORMAL, 0, 0, false); - float width = StaticLayout.getDesiredWidth(str, tempLayout.getLineStart(0), tempLayout.getLineEnd(0), mTextPaint); - if (needScale(str)) { - drawScaledText(canvas, str, width, mTextPaint, top, i, page.getTxtLists()); - } else { - canvas.drawText(str, mMarginLeft, top, mTextPaint); - } - //记录文字位置 --开始 pzl - - float leftposition = mMarginLeft; - - if (isFirstLineOfParagraph(str)) { - String blanks = StringUtils.halfToFull(" "); - //canvas.drawText(blanks, x, top, mTextPaint); - float bw = StaticLayout.getDesiredWidth(blanks, mTextPaint); - leftposition += bw; - } - - float rightposition = 0; - float bottomposition = top + mTextPaint.getFontMetrics().descent; - float textHeight = Math.abs(fontMetrics.ascent) + Math.abs(fontMetrics.descent); - - if (page.getTxtLists() != null) { - for (TxtChar c : page.getTxtLists().get(i).getCharsData()) { - - rightposition = leftposition + c.getCharWidth(); - Point tlp = new Point(); - c.setTopLeftPosition(tlp); - tlp.x = (int) leftposition; - tlp.y = (int) (bottomposition - textHeight); - - Point blp = new Point(); - c.setBottomLeftPosition(blp); - blp.x = (int) leftposition; - blp.y = (int) bottomposition; - - Point trp = new Point(); - c.setTopRightPosition(trp); - trp.x = (int) rightposition; - trp.y = (int) (bottomposition - textHeight); - - Point brp = new Point(); - c.setBottomRightPosition(brp); - brp.x = (int) rightposition; - brp.y = (int) bottomposition; - - leftposition = rightposition; - - ppp++; - c.setIndex(ppp); - } - } - //记录文字位置 --结束 pzl - } - top += str.endsWith("\n") ? textPara : textInterval; - if (!linePosSet && chapterPos == mCurChapterPos && top >= textPara) { - linePos = i; - linePosSet = true; - } - } - if (top > totalHeight) break; - if (pagePos == chapter.getPageSize() - 1) { - String sign = "\u23af \u23af"; - if (chapterPos == book.getChapterTotalNum() - 1) { - bookEnd = pagePos == mCurPagePos; - str = sign + " 所有章节已读完 " + sign; - } else { - str = sign + " 本章完 " + sign; - } - top += textPara; - canvas.drawText(str, mDisplayWidth / 2f, top, mTextEndPaint); - top += textPara * 2; - } - if (top > totalHeight) break; - if (chapter.getPageSize() == 1) { - float pHeight = getFixedPageHeight(chapter, pagePos); - if (top - topi < pHeight) { - top = topi + pHeight; - } - if (top > totalHeight) break; - } - if (pagePos >= chapter.getPageSize() - 1) { - chapterPos += 1; - pagePos = 0; - top += 60; - } else { - pagePos += 1; - } - if (bookEnd && top < mVisibleHeight) { - isLastPage = true; - break; - } - } - } - - void resetPageOffset() { - pageOffset = 0; - linePos = 0; - isLastPage = false; - } - - private void switchToPageOffset(int offset) { - switch (offset) { - case 1: - if (mCurPagePos < curChapter().txtChapter.getPageSize() - 1) { - mCurPagePos = mCurPagePos + 1; - } else if (mCurChapterPos < book.getChapterTotalNum() - 1) { - mCurChapterPos = mCurChapterPos + 1; - Collections.swap(chapterContainers, 0, 1); - Collections.swap(chapterContainers, 1, 2); - nextChapter().txtChapter = null; - mCurPagePos = 0; - if (curChapter().txtChapter == null) { - curChapter().txtChapter = new TxtChapter(mCurChapterPos); - parseCurChapter(); - } else { - parseNextChapter(); - } - } - break; - case -1: - if (mCurPagePos > 0) { - mCurPagePos = mCurPagePos - 1; - } else if (mCurChapterPos > 0) { - mCurChapterPos = mCurChapterPos - 1; - Collections.swap(chapterContainers, 2, 1); - Collections.swap(chapterContainers, 1, 0); - prevChapter().txtChapter = null; - if (curChapter().txtChapter == null) { - curChapter().txtChapter = new TxtChapter(mCurChapterPos); - mCurPagePos = 0; - parseCurChapter(); - } else { - mCurPagePos = curChapter().txtChapter.getPageSize() - 1; - parsePrevChapter(); - } - } - break; - default: - break; - } - } - - private float getFixedPageHeight(TxtChapter chapter, int pagePos) { - float height = getPageHeight(chapter, pagePos); - if (height == 0) { - return height; - } - int lastPageIndex = chapter.getPageSize() - 1; - if (pagePos == lastPageIndex) { - height += 60 + textPara * 3; - } - if (lastPageIndex <= 0 && height < mVisibleHeight / 2.0f) { - height = mVisibleHeight / 2.0f; - } - return height; - } - - private float getPageHeight(TxtChapter chapter, int pagePos) { - float height = 0; - if (chapter == null || chapter.getStatus() != TxtChapter.Status.FINISH) { - return height; - } - if (pagePos >= 0 && pagePos < chapter.getPageSize()) { - height = getPageHeight(chapter.getPage(pagePos)); - } - if (chapter.getPosition() == 0 && pagePos == 0) { - height += getCoverHeight(); - } - return height; - } - - private float getPageHeight(TxtPage page) { - if (page.getLines().isEmpty()) - return 0; - float height = 0; - if (page.getTitleLines() > 0) - height += titleInterval * (page.getTitleLines() - 1) + titlePara; - for (int i = page.getTitleLines(); i < page.size(); i++) { - height += page.getLine(i).endsWith("\n") ? textPara : textInterval; - } - return height; - } - - private void drawErrorMsg(Canvas canvas, String msg, float offset) { - Layout tempLayout = new StaticLayout(msg, mTextPaint, mVisibleWidth, Layout.Alignment.ALIGN_NORMAL, 0, 0, false); - List linesData = new ArrayList<>(); - for (int i = 0; i < tempLayout.getLineCount(); i++) { - linesData.add(msg.substring(tempLayout.getLineStart(i), tempLayout.getLineEnd(i))); - } - float pivotY = (mDisplayHeight - textInterval * linesData.size()) / 3f - offset; - for (String str : linesData) { - float textWidth = mTextPaint.measureText(str); - float pivotX = (mDisplayWidth - textWidth) / 2; - canvas.drawText(str, pivotX, pivotY, mTextPaint); - pivotY += textInterval; - } - } - - /** - * 获取状态文本 - */ - private String getStatusText(TxtChapter chapter) { - String tip = ""; - switch (chapter.getStatus()) { - case LOADING: - tip = mContext.getString(R.string.loading); - break; - case ERROR: - tip = mContext.getString(R.string.load_error_msg, curChapter().txtChapter.getMsg()); - break; - case EMPTY: - tip = mContext.getString(R.string.content_empty); - break; - case CATEGORY_EMPTY: - tip = mContext.getString(R.string.chapter_list_empty); - break; - case CHANGE_SOURCE: - tip = mContext.getString(R.string.on_change_source); - } - return tip; - } - - /** - * 判断是否存在上一页 - */ - boolean hasPrev() { - // 以下情况禁止翻页 - if (canNotTurnPage()) { - return false; - } - if (getPageStatus() == TxtChapter.Status.FINISH) { - // 先查看是否存在上一页 - if (mCurPagePos > 0) { - return true; - } - } - return mCurChapterPos > 0; - } - - /** - * 判断是否下一页存在 - */ - boolean hasNext(int pageOnCur) { - // 以下情况禁止翻页 - if (canNotTurnPage()) { - return false; - } - if (getPageStatus() == TxtChapter.Status.FINISH) { - // 先查看是否存在下一页 - if (mCurPagePos + pageOnCur < curChapter().txtChapter.getPageSize() - 1) { - return true; - } - } - return mCurChapterPos + 1 < book.getChapterTotalNum(); - } - - /** - * 解析当前页数据 - */ - void parseCurChapter() { - if (curChapter().txtChapter.getStatus() != TxtChapter.Status.FINISH) { - Single.create((SingleOnSubscribe) e -> { - ChapterProvider chapterProvider = new ChapterProvider(this); - TxtChapter txtChapter = chapterProvider.dealLoadPageList(callback.getChapterList().get(mCurChapterPos), mPageView.isPrepare()); - e.onSuccess(txtChapter); - }) - .compose(RxUtils::toSimpleSingle) - .subscribe(new SingleObserver() { - @Override - public void onSubscribe(Disposable d) { - compositeDisposable.add(d); - } - - @Override - public void onSuccess(TxtChapter txtChapter) { - upTextChapter(txtChapter); - } - - @Override - public void onError(Throwable e) { - if (curChapter().txtChapter == null || curChapter().txtChapter.getStatus() != TxtChapter.Status.FINISH) { - curChapter().txtChapter = new TxtChapter(mCurChapterPos); - curChapter().txtChapter.setStatus(TxtChapter.Status.ERROR); - curChapter().txtChapter.setMsg(e.getMessage()); - } - } - }); - } - parsePrevChapter(); - parseNextChapter(); - } - - /** - * 解析上一章数据 - */ - void parsePrevChapter() { - final int prevChapterPos = mCurChapterPos - 1; - if (prevChapterPos < 0) { - prevChapter().txtChapter = null; - return; - } - if (prevChapter().txtChapter == null) - prevChapter().txtChapter = new TxtChapter(prevChapterPos); - if (prevChapter().txtChapter.getStatus() == TxtChapter.Status.FINISH) { - return; - } - Single.create((SingleOnSubscribe) e -> { - ChapterProvider chapterProvider = new ChapterProvider(this); - TxtChapter txtChapter = chapterProvider.dealLoadPageList(callback.getChapterList().get(prevChapterPos), mPageView.isPrepare()); - e.onSuccess(txtChapter); - }) - .compose(RxUtils::toSimpleSingle) - .subscribe(new SingleObserver() { - @Override - public void onSubscribe(Disposable d) { - compositeDisposable.add(d); - } - - @Override - public void onSuccess(TxtChapter txtChapter) { - upTextChapter(txtChapter); - } - - @Override - public void onError(Throwable e) { - if (prevChapter().txtChapter == null || prevChapter().txtChapter.getStatus() != TxtChapter.Status.FINISH) { - prevChapter().txtChapter = new TxtChapter(prevChapterPos); - prevChapter().txtChapter.setStatus(TxtChapter.Status.ERROR); - prevChapter().txtChapter.setMsg(e.getMessage()); - } - } - }); - } - - /** - * 解析下一章数据 - */ - void parseNextChapter() { - final int nextChapterPos = mCurChapterPos + 1; - if (nextChapterPos >= callback.getChapterList().size()) { - nextChapter().txtChapter = null; - return; - } - if (nextChapter().txtChapter == null) - nextChapter().txtChapter = new TxtChapter(nextChapterPos); - if (nextChapter().txtChapter.getStatus() == TxtChapter.Status.FINISH) { - return; - } - Single.create((SingleOnSubscribe) e -> { - ChapterProvider chapterProvider = new ChapterProvider(this); - TxtChapter txtChapter = chapterProvider.dealLoadPageList(callback.getChapterList().get(nextChapterPos), mPageView.isPrepare()); - e.onSuccess(txtChapter); - }) - .compose(RxUtils::toSimpleSingle) - .subscribe(new SingleObserver() { - @Override - public void onSubscribe(Disposable d) { - compositeDisposable.add(d); - } - - @Override - public void onSuccess(TxtChapter txtChapter) { - upTextChapter(txtChapter); - } - - @Override - public void onError(Throwable e) { - if (nextChapter().txtChapter == null || nextChapter().txtChapter.getStatus() != TxtChapter.Status.FINISH) { - nextChapter().txtChapter = new TxtChapter(nextChapterPos); - nextChapter().txtChapter.setStatus(TxtChapter.Status.ERROR); - nextChapter().txtChapter.setMsg(e.getMessage()); - } - } - }); - } - - private void upTextChapter(TxtChapter txtChapter) { - if (txtChapter.getPosition() == mCurChapterPos - 1) { - prevChapter().txtChapter = txtChapter; - if (mPageMode == PageAnimation.Mode.SCROLL) { - mPageView.drawContent(-1); - } else { - mPageView.drawPage(-1); - } - } else if (txtChapter.getPosition() == mCurChapterPos) { - curChapter().txtChapter = txtChapter; - reSetPage(); - chapterChangeCallback(); - pagingEnd(PageAnimation.Direction.NONE); - } else if (txtChapter.getPosition() == mCurChapterPos + 1) { - nextChapter().txtChapter = txtChapter; - if (mPageMode == PageAnimation.Mode.SCROLL) { - mPageView.drawContent(1); - } else { - mPageView.drawPage(1); - } - } - } - - private void drawScaledText(Canvas canvas, String line, float lineWidth, TextPaint paint, float top, int y, List txtLists) { - float x = mMarginLeft; - - if (isFirstLineOfParagraph(line)) { - canvas.drawText(indent, x, top, paint); - float bw = StaticLayout.getDesiredWidth(indent, paint); - x += bw; - line = line.substring(readBookControl.getIndent()); - } - int gapCount = line.length() - 1; - int i = 0; - - TxtLine txtList = new TxtLine();//每一行pzl - txtList.setCharsData(new ArrayList<>());//pzl - - float d = ((mDisplayWidth - (mMarginLeft + mMarginRight)) - lineWidth) / gapCount; - for (; i < line.length(); i++) { - String c = String.valueOf(line.charAt(i)); - float cw = StaticLayout.getDesiredWidth(c, paint); - canvas.drawText(c, x, top, paint); - //pzl - TxtChar txtChar = new TxtChar(); - txtChar.setChardata(line.charAt(i)); - if (i == 0) txtChar.setCharWidth(cw + d / 2); - if (i == gapCount) txtChar.setCharWidth(cw + d / 2); - txtChar.setCharWidth(cw + d); - ;//字宽 - //txtChar.Index = y;//每页每个字的位置 - txtList.getCharsData().add(txtChar); - //pzl - x += cw + d; - } - if (txtLists != null) { - txtLists.set(y, txtList);//pzl - } - } - - //判断是不是d'hou - private boolean isFirstLineOfParagraph(String line) { - return line.length() > 3 && line.charAt(0) == (char) 12288 && line.charAt(1) == (char) 12288; - } - - private boolean needScale(String line) {//判断不是空行 - return line != null && line.length() != 0 && line.charAt(line.length() - 1) != '\n'; - } - - private void chapterChangeCallback() { - if (callback != null) { - readAloudParagraph = -1; - callback.onChapterChange(mCurChapterPos); - callback.onPageCountChange(curChapter().txtChapter != null ? curChapter().txtChapter.getPageSize() : 0); - } - } - /** - * 获取书籍进度 - * - * @param durChapterIndex - * @param chapterAll - * @param durPageIndex - * @param durPageAll - * @return - */ - private static String getReadProgress(int durChapterIndex, int chapterAll, int durPageIndex, int durPageAll) { - DecimalFormat df = new DecimalFormat("0.0%"); - if (chapterAll == 0 || (durPageAll == 0 && durChapterIndex == 0)) { - return "0.0%"; - } else if (durPageAll == 0) { - return df.format((durChapterIndex + 1.0f) / chapterAll); - } - String percent = df.format(durChapterIndex * 1.0f / chapterAll + 1.0f / chapterAll * (durPageIndex + 1) / durPageAll); - if (percent.equals("100.0%") && (durChapterIndex + 1 != chapterAll || durPageIndex + 1 != durPageAll)) { - percent = "99.9%"; - } - return percent; - } - - public abstract void updateChapter(); - - /** - * 根据当前状态,决定是否能够翻页 - */ - private boolean canNotTurnPage() { - return !isChapterListPrepare - || getPageStatus() == TxtChapter.Status.CHANGE_SOURCE; - } - - /** - * 关闭书本 - */ - public void closeBook() { - compositeDisposable.dispose(); - compositeDisposable = null; - - isChapterListPrepare = false; - isClose = true; - - prevChapter().txtChapter = null; - curChapter().txtChapter = null; - nextChapter().txtChapter = null; - } - - public boolean isClose() { - return isClose; - } - - private ChapterContainer prevChapter() { - return chapterContainers.get(0); - } - - ChapterContainer curChapter() { - return chapterContainers.get(1); - } - - private ChapterContainer nextChapter() { - return chapterContainers.get(2); - } - - /*****************************************interface*****************************************/ - - static class ChapterContainer { - TxtChapter txtChapter; - } - - /** - * -------------------- - * TODO 检测获取按压坐标所在位置的字符,没有的话返回null - * -------------------- - * author: huangwei - * 2017年7月4日上午10:23:19 - */ - TxtChar detectPressTxtChar(float down_X2, float down_Y2) { - TxtPage txtPage = curChapter().txtChapter.getPage(mCurPagePos); - if (txtPage == null) return null; - List txtLines = txtPage.getTxtLists(); - if (txtLines == null) return null; - for (TxtLine l : txtLines) { - List txtChars = l.getCharsData(); - if (txtChars != null) { - for (TxtChar c : txtChars) { - 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; - } - - } - } - } - return null; - } - - public interface Callback { - List getChapterList(); - - /** - * 作用:章节切换的时候进行回调 - * - * @param pos:切换章节的序号 - */ - void onChapterChange(int pos); - - /** - * 作用:章节目录加载完成时候回调 - * - * @param chapters:返回章节目录 - */ - void onCategoryFinish(List chapters); - - /** - * 作用:章节页码数量改变之后的回调。==> 字体大小的调整,或者是否关闭虚拟按钮功能都会改变页面的数量。 - * - * @param count:页面的数量 - */ - void onPageCountChange(int count); - - /** - * 作用:当页面改变的时候回调 - * - * @param chapterIndex 章节序号 - * @param pageIndex 页数 - * @param resetReadAloud 是否重置朗读 - */ - void onPageChange(int chapterIndex, int pageIndex, boolean resetReadAloud); - - } -} diff --git a/app/src/main/java/xyz/fycz/myreader/widget/page2/PageLoaderNet.java b/app/src/main/java/xyz/fycz/myreader/widget/page2/PageLoaderNet.java deleted file mode 100644 index dd7b691..0000000 --- a/app/src/main/java/xyz/fycz/myreader/widget/page2/PageLoaderNet.java +++ /dev/null @@ -1,266 +0,0 @@ -package xyz.fycz.myreader.widget.page2; - -import android.annotation.SuppressLint; - -import java.io.File; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.List; - -import xyz.fycz.myreader.common.APPCONST; -import xyz.fycz.myreader.greendao.entity.Book; -import xyz.fycz.myreader.greendao.entity.Chapter; -import xyz.fycz.myreader.greendao.service.ChapterService; -import xyz.fycz.myreader.util.utils.FileUtils; - -/** - * 网络页面加载器 - */ - -public class PageLoaderNet extends PageLoader { - private static final String TAG = "PageLoaderNet"; - private List downloadingChapterList = new ArrayList<>(); - - PageLoaderNet(PageView pageView, Book bookShelfBean, Callback callback) { - super(pageView, bookShelfBean, callback); - } - - @Override - public void refreshChapterList() { - if (!callback.getChapterList().isEmpty()) { - isChapterListPrepare = true; - // 打开章节 - skipToChapter(book.getHisttoryChapterNum(), book.getLastReadPosition()); - } else { - /*WebBookModel.getInstance().getChapterList(book) - .compose(RxUtils::toSimpleSingle) - .subscribe(new MyObserver>() { - @Override - public void onSubscribe(Disposable d) { - compositeDisposable.add(d); - } - - @Override - public void onNext(List chapterBeanList) { - isChapterListPrepare = true; - // 目录加载完成 - if (!chapterBeanList.isEmpty()) { - BookshelfHelp.delChapterList(book.getNoteUrl()); - callback.onCategoryFinish(chapterBeanList); - } - // 加载并显示当前章节 - skipToChapter(book.getDurChapter(), book.getDurChapterPage()); - } - - @Override - public void onError(Throwable e) { - if (e instanceof WebBook.NoSourceThrowable) { - mPageView.autoChangeSource(); - } else { - durDhapterError(e.getMessage()); - } - } - });*/ - } - } - - - public void changeSourceFinish(Book bookShelfBean) { - if (bookShelfBean == null) { - openChapter(book.getHisttoryChapterNum()); - } else { - this.book = bookShelfBean; - refreshChapterList(); - } - } - - /*@SuppressLint("DefaultLocale") - private synchronized void loadContent(final int chapterIndex) { - if (downloadingChapterList.size() >= 20) return; - if (chapterIndex >= callback.getChapterList().size() - || DownloadingList(listHandle.CHECK, callback.getChapterList().get(chapterIndex).getUrl())) - return; - if (null != book && callback.getChapterList().size() > 0) { - Observable.create((ObservableOnSubscribe) e -> { - if (shouldRequestChapter(chapterIndex)) { - DownloadingList(listHandle.ADD, callback.getChapterList().get(chapterIndex).getUrl()); - e.onNext(chapterIndex); - } - e.onComplete(); - }) - .flatMap(index -> WebBookModel.getInstance().getBookContent(book, callback.getChapterList().get(chapterIndex), null)) - .subscribeOn(scheduler) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new MyObserver() { - @Override - public void onSubscribe(Disposable d) { - compositeDisposable.add(d); - } - - @SuppressLint("DefaultLocale") - @Override - public void onNext(BookContentBean bookContentBean) { - DownloadingList(listHandle.REMOVE, bookContentBean.getDurChapterUrl()); - finishContent(bookContentBean.getDurChapterIndex()); - } - - @Override - public void onError(Throwable e) { - DownloadingList(listHandle.REMOVE, callback.getChapterList().get(chapterIndex).getDurChapterUrl()); - if (chapterIndex == book.getDurChapter()) { - if (e instanceof WebBook.NoSourceThrowable) { - mPageView.autoChangeSource(); - } else if (e instanceof VipThrowable) { - callback.vipPop(); - } else { - durDhapterError(e.getMessage()); - } - } - } - }); - } - }*/ - - /** - * 编辑下载列表 - */ - private synchronized boolean DownloadingList(listHandle editType, String value) { - if (editType == listHandle.ADD) { - downloadingChapterList.add(value); - return true; - } else if (editType == listHandle.REMOVE) { - downloadingChapterList.remove(value); - return true; - } else { - return downloadingChapterList.indexOf(value) != -1; - } - } - - /** - * 章节下载完成 - */ - private void finishContent(int chapterIndex) { - if (chapterIndex == mCurChapterPos) { - super.parseCurChapter(); - } - if (chapterIndex == mCurChapterPos - 1) { - super.parsePrevChapter(); - } - if (chapterIndex == mCurChapterPos + 1) { - super.parseNextChapter(); - } - } - - /** - * 刷新当前章节 - */ - @SuppressLint("DefaultLocale") - /*public void refreshDurChapter() { - if (callback.getChapterList().isEmpty()) { - updateChapter(); - return; - } - if (callback.getChapterList().size() - 1 < mCurChapterPos) { - mCurChapterPos = callback.getChapterList().size() - 1; - } - BookshelfHelp.delChapter(BookshelfHelp.getCachePathName(book.getBookInfoBean().getName(), book.getTag()), - mCurChapterPos, callback.getChapterList().get(mCurChapterPos).getDurChapterName()); - skipToChapter(mCurChapterPos, 0); - }*/ - - @Override - protected String getChapterContent(Chapter chapter) { - File file = new File(APPCONST.BOOK_CACHE_PATH + book.getId() - + File.separator + chapter.getTitle() + FileUtils.SUFFIX_FY); - if (!file.exists()) return null; - byte[] contentByte = FileUtils.getBytes(file); - return new String(contentByte, StandardCharsets.UTF_8); - //return BookshelfHelp.getChapterCache(book, chapter); - } - - @SuppressLint("DefaultLocale") - @Override - protected boolean noChapterData(Chapter chapter) { - //return !BookshelfHelp.isChapterCached(book.getBookInfoBean().getName(), book.getTag(), chapter, book.isAudio()); - return !ChapterService.isChapterCached(book.getId(), chapter.getTitle()); - } - - /*private boolean shouldRequestChapter(Integer chapterIndex) { - return NetworkUtils.isNetWorkAvailable() && noChapterData(callback.getChapterList().get(chapterIndex)); - }*/ - - // 装载上一章节的内容 - @Override - void parsePrevChapter() { - /*if (mCurChapterPos >= 1) { - loadContent(mCurChapterPos - 1); - }*/ - super.parsePrevChapter(); - } - - // 装载当前章内容。 - @Override - void parseCurChapter() { - /*for (int i = mCurChapterPos; i < Math.min(mCurChapterPos + 5, book.getChapterTotalNum()); i++) { - loadContent(i); - }*/ - super.parseCurChapter(); - } - - // 装载下一章节的内容 - @Override - void parseNextChapter() { - /*for (int i = mCurChapterPos; i < Math.min(mCurChapterPos + 5, book.getChapterTotalNum()); i++) { - loadContent(i); - }*/ - super.parseNextChapter(); - } - - @Override - public void updateChapter() { - /*mPageView.getActivity().toast("目录更新中"); - WebBookModel.getInstance().getChapterList(book) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new Observer>() { - @Override - public void onSubscribe(Disposable d) { - compositeDisposable.add(d); - } - - @Override - public void onNext(List chapterBeanList) { - isChapterListPrepare = true; - - if (chapterBeanList.size() > callback.getChapterList().size()) { - mPageView.getActivity().toast("更新完成,有新章节"); - callback.onCategoryFinish(chapterBeanList); - } else { - mPageView.getActivity().toast("更新完成,无新章节"); - } - - // 加载并显示当前章节 - skipToChapter(book.getDurChapter(), book.getDurChapterPage()); - } - - @Override - public void onError(Throwable e) { - durDhapterError(e.getMessage()); - } - - @Override - public void onComplete() { - - } - });*/ - } - - @Override - public void closeBook() { - super.closeBook(); - } - - public enum listHandle { - ADD, REMOVE, CHECK - } -} diff --git a/app/src/main/java/xyz/fycz/myreader/widget/page2/PageView.java b/app/src/main/java/xyz/fycz/myreader/widget/page2/PageView.java deleted file mode 100644 index 3099089..0000000 --- a/app/src/main/java/xyz/fycz/myreader/widget/page2/PageView.java +++ /dev/null @@ -1,713 +0,0 @@ -package xyz.fycz.myreader.widget.page2; - -import android.annotation.SuppressLint; -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Paint; -import android.graphics.Path; -import android.graphics.RectF; -import android.util.AttributeSet; -import android.view.MotionEvent; -import android.view.View; -import android.view.ViewConfiguration; - -import com.gyf.immersionbar.ImmersionBar; - -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; - -import xyz.fycz.myreader.entity.ReadBookControl; -import xyz.fycz.myreader.greendao.entity.Book; -import xyz.fycz.myreader.ui.activity.ReadActivity; -import xyz.fycz.myreader.util.utils.FileUtils; -import xyz.fycz.myreader.util.utils.ScreenUtils; -import xyz.fycz.myreader.util.utils.SnackbarUtils; -import xyz.fycz.myreader.widget.page2.animation.CoverPageAnim; -import xyz.fycz.myreader.widget.page2.animation.HorizonPageAnim; -import xyz.fycz.myreader.widget.page2.animation.NonePageAnim; -import xyz.fycz.myreader.widget.page2.animation.PageAnimation; -import xyz.fycz.myreader.widget.page2.animation.ScrollPageAnim; -import xyz.fycz.myreader.widget.page2.animation.SimulationPageAnim; -import xyz.fycz.myreader.widget.page2.animation.SlidePageAnim; - -import static xyz.fycz.myreader.util.utils.ScreenUtils.getDisplayMetrics; - - -/** - * 绘制页面显示内容的类 - */ -public class PageView extends View implements PageAnimation.OnPageChangeListener { - - private ReadActivity activity; - - private int mViewWidth = 0; // 当前View的宽 - private int mViewHeight = 0; // 当前View的高 - private int statusBarHeight = 0; //状态栏高度 - - private boolean actionFromEdge = false; - // 初始化参数 - private ReadBookControl readBookControl = ReadBookControl.getInstance(); - private boolean isPrepare; - // 动画类 - private PageAnimation mPageAnim; - //点击监听 - private TouchListener mTouchListener; - //内容加载器 - private PageLoader mPageLoader; - - //文字选择画笔 - private Paint mTextSelectPaint = null; - //文字选择画笔颜色 - private int TextSelectColor = Color.parseColor("#77fadb08"); - - private Path mSelectTextPath = new Path(); - - //触摸到起始位置 - private int mStartX = 0; - private int mStartY = 0; - // 是否发触了长按事件 - private boolean isLongPress = false; - //第一个选择的文字 - private TxtChar firstSelectTxtChar = null; - //最后选择的一个文字 - private TxtChar lastSelectTxtChar = null; - //选择模式 - private SelectMode selectMode = SelectMode.Normal; - //文本高度 - private float textHeight = 0; - // 唤醒菜单的区域 - private RectF mCenterRect = null; - //是否在移动 - private boolean isMove = false; - //长按的runnable - private Runnable mLongPressRunnable; - //长按时间 - private static final int LONG_PRESS_TIMEOUT = 1000; - //选择的列 - private List mSelectLines = new ArrayList(); - - - public PageView(Context context) { - this(context, null); - } - - public PageView(Context context, AttributeSet attrs) { - this(context, attrs, 0); - } - - public PageView(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - init(); - } - - private void init() { - //初始化画笔 - mTextSelectPaint = new Paint(); - mTextSelectPaint.setAntiAlias(true); - mTextSelectPaint.setTextSize(19); - mTextSelectPaint.setColor(TextSelectColor); - - mLongPressRunnable = () -> { - if (mPageLoader == null) return; - performLongClick(); - if (mStartX > 0 && mStartY > 0) {// 说明还没释放,是长按事件 - isLongPress = true;//长按 - TxtChar p = mPageLoader.detectPressTxtChar(mStartX, mStartY);//找到长按的点 - firstSelectTxtChar = p;//设置开始位置字符 - lastSelectTxtChar = p;//设置结束位置字符 - selectMode = SelectMode.PressSelectText;//设置模式为长按选择 - mTouchListener.onLongPress();//响应长按事件,供上层调用 - } - }; - } - - @Override - protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight) { - super.onSizeChanged(width, height, oldWidth, oldHeight); - mViewWidth = width; - mViewHeight = height; - - isPrepare = true; - - if (mPageLoader != null) { - mPageLoader.prepareDisplay(width, height); - } - //设置中间区域范围 - mCenterRect = new RectF(mViewWidth / 3f, mViewHeight / 3f, - mViewWidth * 2f / 3, mViewHeight * 2f / 3); - } - - //设置翻页的模式 - void setPageMode(PageAnimation.Mode pageMode, int marginTop, int marginBottom) { - //视图未初始化的时候,禁止调用 - if (mViewWidth == 0 || mViewHeight == 0 || mPageLoader == null) return; - if (!readBookControl.getHideStatusBar()) { - marginTop = marginTop + statusBarHeight; - } - switch (pageMode) { - case COVER: - mPageAnim = new CoverPageAnim(mViewWidth, mViewHeight, this, this); - break; - case SLIDE: - mPageAnim = new SlidePageAnim(mViewWidth, mViewHeight, this, this); - break; - case NONE: - mPageAnim = new NonePageAnim(mViewWidth, mViewHeight, this, this); - break; - case SCROLL: - mPageAnim = new ScrollPageAnim(mViewWidth, mViewHeight, 0, - marginTop, marginBottom, this, this); - break; - default: - mPageAnim = new SimulationPageAnim(mViewWidth, mViewHeight, this, this); - } - } - - public ReadActivity getActivity() { - return activity; - } - - public int getStatusBarHeight() { - return statusBarHeight; - } - - public Bitmap getBgBitmap(int pageOnCur) { - if (mPageAnim == null) return null; - return mPageAnim.getBgBitmap(pageOnCur); - } - - public void autoPrevPage() { - if (mPageAnim instanceof ScrollPageAnim) { - ((ScrollPageAnim) mPageAnim).startAnim(PageAnimation.Direction.PREV); - } else { - startHorizonPageAnim(PageAnimation.Direction.PREV); - } - } - - public void autoNextPage() { - if (mPageAnim instanceof ScrollPageAnim) { - ((ScrollPageAnim) mPageAnim).startAnim(PageAnimation.Direction.NEXT); - } else { - startHorizonPageAnim(PageAnimation.Direction.NEXT); - } - } - - private synchronized void startHorizonPageAnim(PageAnimation.Direction direction) { - if (mTouchListener == null) return; - //结束动画 - mPageAnim.abortAnim(); - if (direction == PageAnimation.Direction.NEXT) { - int x = mViewWidth; - int y = mViewHeight; - //初始化动画 - mPageAnim.setStartPoint(x, y); - //设置点击点 - mPageAnim.setTouchPoint(x, y); - //设置方向 - boolean hasNext = hasNextPage(0); - - mPageAnim.setDirection(direction); - if (!hasNext) { - ((HorizonPageAnim) mPageAnim).setNoNext(true); - return; - } - } else if (direction == PageAnimation.Direction.PREV) { - int x = 0; - int y = mViewHeight; - //初始化动画 - mPageAnim.setStartPoint(x, y); - //设置点击点 - mPageAnim.setTouchPoint(x, y); - mPageAnim.setDirection(direction); - //设置方向方向 - boolean hashPrev = hasPrevPage(); - if (!hashPrev) { - ((HorizonPageAnim) mPageAnim).setNoNext(true); - return; - } - } else { - return; - } - ((HorizonPageAnim) mPageAnim).setNoNext(false); - ((HorizonPageAnim) mPageAnim).setCancel(false); - mPageAnim.startAnim(); - } - - public void drawPage(int pageOnCur) { - if (!isPrepare) return; - if (mPageLoader != null) { - mPageLoader.drawPage(getBgBitmap(pageOnCur), pageOnCur); - } - invalidate(); - } - - /** - * 绘制滚动背景 - */ - @Override - public void drawBackground(Canvas canvas) { - if (!isPrepare) return; - if (mPageLoader != null) { - mPageLoader.drawBackground(canvas); - } - } - - /** - * 绘制滚动内容 - */ - @Override - public void drawContent(Canvas canvas, float offset) { - if (!isPrepare) return; - if (mPageLoader != null) { - mPageLoader.drawContent(canvas, offset); - } - } - - /** - * 绘制横翻背景 - */ - public void drawBackground(int pageOnCur) { - if (!isPrepare) return; - if (mPageLoader != null) { - mPageLoader.drawPage(getBgBitmap(pageOnCur), pageOnCur); - } - invalidate(); - } - - /** - * 绘制横翻内容 - * - * @param pageOnCur 相对当前页的位置 - */ - public void drawContent(int pageOnCur) { - if (!isPrepare) return; - if (mPageLoader != null) { - mPageLoader.drawPage(getBgBitmap(pageOnCur), pageOnCur); - } - invalidate(); - } - - @Override - protected void onDraw(Canvas canvas) { - if (mPageAnim instanceof ScrollPageAnim) - super.onDraw(canvas); - //绘制动画 - if (mPageAnim != null) { - mPageAnim.draw(canvas); - } - if (selectMode != SelectMode.Normal && !isRunning() && !isMove) { - DrawSelectText(canvas); - } - } - - private void DrawSelectText(Canvas canvas) { - if (selectMode == SelectMode.PressSelectText) { - drawPressSelectText(canvas); - } else if (selectMode == SelectMode.SelectMoveForward) { - drawMoveSelectText(canvas); - } else if (selectMode == SelectMode.SelectMoveBack) { - drawMoveSelectText(canvas); - } - } - - - private void drawPressSelectText(Canvas canvas) { - if (lastSelectTxtChar != null) {// 找到了选择的字符 - mSelectTextPath.reset(); - mSelectTextPath.moveTo(firstSelectTxtChar.getTopLeftPosition().x, firstSelectTxtChar.getTopLeftPosition().y); - mSelectTextPath.lineTo(firstSelectTxtChar.getTopRightPosition().x, firstSelectTxtChar.getTopRightPosition().y); - mSelectTextPath.lineTo(firstSelectTxtChar.getBottomRightPosition().x, firstSelectTxtChar.getBottomRightPosition().y); - mSelectTextPath.lineTo(firstSelectTxtChar.getBottomLeftPosition().x, firstSelectTxtChar.getBottomLeftPosition().y); - canvas.drawPath(mSelectTextPath, mTextSelectPaint); - } - } - - - public String getSelectStr() { - - if (mSelectLines.size() == 0) { - return String.valueOf(firstSelectTxtChar.getChardata()); - } - StringBuilder sb = new StringBuilder(); - for (TxtLine l : mSelectLines) { - //Log.e("selectline", l.getLineData() + ""); - sb.append(l.getLineData()); - } - - return sb.toString(); - } - - - private void drawMoveSelectText(Canvas canvas) { - if (firstSelectTxtChar == null || lastSelectTxtChar == null) - return; - getSelectData(); - drawSelectLines(canvas); - } - - List mLinseData = null; - - private void getSelectData() { - TxtPage txtPage = mPageLoader.curChapter().txtChapter.getPage(mPageLoader.getCurPagePos()); - if (txtPage != null) { - mLinseData = txtPage.getTxtLists(); - - Boolean Started = false; - Boolean Ended = false; - - mSelectLines.clear(); - - // 找到选择的字符数据,转化为选择的行,然后将行选择背景画出来 - for (TxtLine l : mLinseData) { - - TxtLine selectline = new TxtLine(); - selectline.setCharsData(new ArrayList<>()); - - for (TxtChar c : l.getCharsData()) { - if (!Started) { - if (c.getIndex() == firstSelectTxtChar.getIndex()) { - Started = true; - selectline.getCharsData().add(c); - if (c.getIndex() == lastSelectTxtChar.getIndex()) { - Ended = true; - break; - } - } - } else { - if (c.getIndex() == lastSelectTxtChar.getIndex()) { - Ended = true; - if (!selectline.getCharsData().contains(c)) { - selectline.getCharsData().add(c); - } - break; - } else { - selectline.getCharsData().add(c); - } - } - } - - mSelectLines.add(selectline); - - if (Started && Ended) { - break; - } - } - } - } - - public SelectMode getSelectMode() { - return selectMode; - } - - public void setSelectMode(SelectMode mCurrentMode) { - this.selectMode = mCurrentMode; - } - - private void drawSelectLines(Canvas canvas) { - drawOaleSeletLinesBg(canvas); - } - - public void clearSelect() { - firstSelectTxtChar = null; - lastSelectTxtChar = null; - selectMode = SelectMode.Normal; - mSelectTextPath.reset(); - invalidate(); - - } - - - //根据当前坐标返回文字 - public TxtChar getCurrentTxtChar(float x, float y) { - return mPageLoader.detectPressTxtChar(x, y); - } - - private void drawOaleSeletLinesBg(Canvas canvas) {// 绘制椭圆型的选中背景 - for (TxtLine l : mSelectLines) { - if (l.getCharsData() != null && l.getCharsData().size() > 0) { - - TxtChar fistchar = l.getCharsData().get(0); - TxtChar lastchar = l.getCharsData().get(l.getCharsData().size() - 1); - - float fw = fistchar.getCharWidth(); - float lw = lastchar.getCharWidth(); - - RectF rect = new RectF(fistchar.getTopLeftPosition().x, fistchar.getTopLeftPosition().y, - lastchar.getTopRightPosition().x, lastchar.getBottomRightPosition().y); - - canvas.drawRoundRect(rect, fw / 2, - textHeight / 2, mTextSelectPaint); - } - } - } - - public TxtChar getFirstSelectTxtChar() { - return firstSelectTxtChar; - } - - public void setFirstSelectTxtChar(TxtChar firstSelectTxtChar) { - this.firstSelectTxtChar = firstSelectTxtChar; - } - - public TxtChar getLastSelectTxtChar() { - return lastSelectTxtChar; - } - - public void setLastSelectTxtChar(TxtChar lastSelectTxtChar) { - this.lastSelectTxtChar = lastSelectTxtChar; - } - - @Override - public void computeScroll() { - //进行滑动 - if (mPageAnim != null) { - mPageAnim.scrollAnim(); - } - super.computeScroll(); - } - - @SuppressLint("ClickableViewAccessibility") - @Override - public boolean onTouchEvent(MotionEvent event) { - super.onTouchEvent(event); - if (mPageAnim == null) return true; - if (mPageLoader == null) return true; - - Paint.FontMetrics fontMetrics = mPageLoader.mTextPaint.getFontMetrics(); - textHeight = Math.abs(fontMetrics.ascent) + Math.abs(fontMetrics.descent); - - if (actionFromEdge) { - if (event.getAction() == MotionEvent.ACTION_UP) - actionFromEdge = false; - return true; - } - - int x = (int) event.getX(); - int y = (int) event.getY(); - - switch (event.getAction()) { - case MotionEvent.ACTION_DOWN: - mPageAnim.initTouch(x, y); - if (event.getEdgeFlags() != 0 || event.getRawY() < ScreenUtils.dpToPx(5) || event.getRawY() > getDisplayMetrics().heightPixels - ScreenUtils.dpToPx(5)) { - actionFromEdge = true; - return true; - } - mStartX = x; - mStartY = y; - isMove = false; - - // - if (readBookControl.isCanSelectText() && mPageLoader.getPageStatus() == TxtChapter.Status.FINISH) { - postDelayed(mLongPressRunnable, LONG_PRESS_TIMEOUT); - } - - // - isLongPress = false; - mTouchListener.onTouch(); - mPageAnim.onTouchEvent(event); - - selectMode = SelectMode.Normal; - - mTouchListener.onTouchClearCursor(); - - break; - case MotionEvent.ACTION_MOVE: - mPageAnim.initTouch(x, y); - // 判断是否大于最小滑动值。 - int slop = ViewConfiguration.get(getContext()).getScaledTouchSlop(); - if (!isMove) { - isMove = Math.abs(mStartX - event.getX()) > slop || Math.abs(mStartY - event.getY()) > slop; - } - - // 如果滑动了,且不是长按,则进行翻页。 - if (isMove) { - if (readBookControl.isCanSelectText()) { - removeCallbacks(mLongPressRunnable); - } - mPageAnim.onTouchEvent(event); - } - break; - case MotionEvent.ACTION_CANCEL: - case MotionEvent.ACTION_UP: - mPageAnim.initTouch(x, y); - mPageAnim.setTouchInitFalse(); - if (!isMove) { - if (readBookControl.isCanSelectText()) { - removeCallbacks(mLongPressRunnable); - } - - //是否点击了中间 - if (mCenterRect.contains(x, y)) { - if (firstSelectTxtChar == null) { - if (mTouchListener != null) { - mTouchListener.center(); - } - } else { - if (mSelectTextPath != null) {//长安选择删除选中状态 - if (!isLongPress) { - firstSelectTxtChar = null; - mSelectTextPath.reset(); - invalidate(); - } - } - //清除移动选择状态 - } - return true; - } - - if (!readBookControl.getCanClickTurn()) { - return true; - } - - if (mPageAnim instanceof ScrollPageAnim && readBookControl.disableScrollClickTurn()) { - return true; - } - } - - if (firstSelectTxtChar == null || isMove) {//长安选择删除选中状态 - mPageAnim.onTouchEvent(event); - } else { - if (!isLongPress) { - //释放了 - if (LONG_PRESS_TIMEOUT != 0) { - removeCallbacks(mLongPressRunnable); - } - firstSelectTxtChar = null; - mSelectTextPath.reset(); - invalidate(); - } - } - break; - } - return true; - } - - /** - * 判断是否存在上一页 - */ - private boolean hasPrevPage() { - if (mPageLoader.hasPrev()) { - return true; - } else { - showSnackBar("已经是第一页了"); - return false; - } - } - - /** - * 判断是否下一页存在 - */ - private boolean hasNextPage(int pageOnCur) { - if (mPageLoader.hasNext(pageOnCur)) { - return true; - } else { - showSnackBar("已经是最后一页了"); - return false; - } - } - - public boolean isRunning() { - return mPageAnim != null && mPageAnim.isRunning(); - } - - public boolean isPrepare() { - return isPrepare; - } - - public void setTouchListener(TouchListener mTouchListener) { - this.mTouchListener = mTouchListener; - } - - @Override - protected void onDetachedFromWindow() { - super.onDetachedFromWindow(); - if (mPageAnim != null) { - mPageAnim.abortAnim(); - mPageAnim.clear(); - } - - mPageLoader = null; - mPageAnim = null; - } - - @Override - public void resetScroll() { - mPageLoader.resetPageOffset(); - } - - @Override - public boolean hasPrev() { - return PageView.this.hasPrevPage(); - } - - @Override - public boolean hasNext(int pageOnCur) { - return PageView.this.hasNextPage(pageOnCur); - } - - @Override - public void changePage(PageAnimation.Direction direction) { - mPageLoader.pagingEnd(direction); - } - - /** - * 获取 PageLoader - */ - public PageLoader getPageLoader(ReadActivity activity, Book bookShelfBean, PageLoader.Callback callback) { - this.activity = activity; - this.statusBarHeight = ImmersionBar.getStatusBarHeight(activity); - // 判是否已经存在 - if (mPageLoader != null) { - return mPageLoader; - } - // 根据书籍类型,获取具体的加载器 - //if (!Objects.equals(bookShelfBean.getTag(), BookShelfBean.LOCAL_TAG)) { - if (!"本地书籍".equals(bookShelfBean.getType())) { - mPageLoader = new PageLoaderNet(this, bookShelfBean, callback); - } else { - /*String fileSuffix = FileUtils.getFileSuffix(bookShelfBean.getChapterUrl()); - if (fileSuffix.equalsIgnoreCase(FileUtils.SUFFIX_EPUB)) { - mPageLoader = new PageLoaderEpub(this, bookShelfBean, callback); - } else { - mPageLoader = new PageLoaderText(this, bookShelfBean, callback); - }*/ - } - // 判断是否 PageView 已经初始化完成 - if (mViewWidth != 0 || mViewHeight != 0) { - // 初始化 PageLoader 的屏幕大小 - mPageLoader.prepareDisplay(mViewWidth, mViewHeight); - } - - return mPageLoader; - } - - public void autoChangeSource() { - mPageLoader.setStatus(TxtChapter.Status.CHANGE_SOURCE); - //activity.autoChangeSource(); - } - - /** - * 显示tips - * - * @param msg - */ - public void showSnackBar(String msg) { - SnackbarUtils.show(this, msg); - } - public enum SelectMode { - Normal, PressSelectText, SelectMoveForward, SelectMoveBack - } - - public interface TouchListener { - void onTouch(); - - void onTouchClearCursor(); - - void onLongPress(); - - void center(); - } -} diff --git a/app/src/main/java/xyz/fycz/myreader/widget/page2/TxtChapter.kt b/app/src/main/java/xyz/fycz/myreader/widget/page2/TxtChapter.kt deleted file mode 100644 index aa12d38..0000000 --- a/app/src/main/java/xyz/fycz/myreader/widget/page2/TxtChapter.kt +++ /dev/null @@ -1,57 +0,0 @@ -package xyz.fycz.myreader.widget.page2 - -import java.util.* -import kotlin.math.max -import kotlin.math.min - -/** - * 章节 - */ - -class TxtChapter internal constructor(val position: Int) { - val txtPageList = ArrayList() - val txtPageLengthList = ArrayList() - val paragraphLengthList = ArrayList() - var status = Status.LOADING - var msg: String? = null - - val pageSize: Int - get() = txtPageList.size - - fun addPage(txtPage: TxtPage) { - txtPageList.add(txtPage) - } - - fun getPage(page: Int): TxtPage? { - return if (txtPageList.isNotEmpty()) { - txtPageList[max(0, min(page, txtPageList.size - 1))] - } else null - } - - fun getPageLength(position: Int): Int { - return if (position >= 0 && position < txtPageLengthList.size) { - txtPageLengthList[position] - } else -1 - } - - fun addTxtPageLength(length: Int) { - txtPageLengthList.add(length) - } - - fun addParagraphLength(length: Int) { - paragraphLengthList.add(length) - } - - fun getParagraphIndex(length: Int): Int { - for (i in paragraphLengthList.indices) { - if ((i == 0 || paragraphLengthList[i - 1] < length) && length <= paragraphLengthList[i]) { - return i - } - } - return -1 - } - - enum class Status { - LOADING, FINISH, ERROR, EMPTY, CATEGORY_EMPTY, CHANGE_SOURCE - } -} diff --git a/app/src/main/java/xyz/fycz/myreader/widget/page2/TxtChar.kt b/app/src/main/java/xyz/fycz/myreader/widget/page2/TxtChar.kt deleted file mode 100644 index f1cc31b..0000000 --- a/app/src/main/java/xyz/fycz/myreader/widget/page2/TxtChar.kt +++ /dev/null @@ -1,26 +0,0 @@ -package xyz.fycz.myreader.widget.page2 - -import android.graphics.Point - - -class TxtChar { - var chardata: Char = ' '//字符数据 - - var selected: Boolean? = false//当前字符是否被选中 - - //记录文字的左上右上左下右下四个点坐标 - var topLeftPosition: Point? = null//左上 - var topRightPosition: Point? = null//右上 - var bottomLeftPosition: Point? = null//左下 - var bottomRightPosition: Point? = null//右下 - - var charWidth = 0f//字符宽度 - var Index = 0//当前字符位置 - - override fun toString(): String { - return ("ShowChar [chardata=" + chardata + ", Selected=" + selected + ", TopLeftPosition=" + topLeftPosition - + ", TopRightPosition=" + topRightPosition + ", BottomLeftPosition=" + bottomLeftPosition - + ", BottomRightPosition=" + bottomRightPosition + ", charWidth=" + charWidth + ", Index=" + Index - + "]"); - } -} \ No newline at end of file diff --git a/app/src/main/java/xyz/fycz/myreader/widget/page2/TxtLine.kt b/app/src/main/java/xyz/fycz/myreader/widget/page2/TxtLine.kt deleted file mode 100644 index 15c58c8..0000000 --- a/app/src/main/java/xyz/fycz/myreader/widget/page2/TxtLine.kt +++ /dev/null @@ -1,23 +0,0 @@ -package xyz.fycz.myreader.widget.page2 - -class TxtLine { - - var charsData: List? = null - - fun getLineData(): String { - var linedata = "" - if (charsData == null) return linedata - charsData?.let { - if (it.isEmpty()) return linedata - for (c in it) { - linedata += c.chardata - } - } - return linedata - } - - override fun toString(): String { - return "ShowLine [Linedata=" + getLineData() + "]" - } - -} \ No newline at end of file diff --git a/app/src/main/java/xyz/fycz/myreader/widget/page2/TxtPage.kt b/app/src/main/java/xyz/fycz/myreader/widget/page2/TxtPage.kt deleted file mode 100644 index 9723907..0000000 --- a/app/src/main/java/xyz/fycz/myreader/widget/page2/TxtPage.kt +++ /dev/null @@ -1,44 +0,0 @@ -package xyz.fycz.myreader.widget.page2 - -import java.util.* - -/** - * 页面 - */ - -class TxtPage(val position: Int) { - var title: String? = null - var titleLines: Int = 0 //当前 lines 中为 title 的行数。 - private val lines = ArrayList() - //存放每个字的位置 - var txtLists: List? = null - - val content: String - get() { - val s = StringBuilder() - for (i in lines.indices) { - s.append(lines[i]) - } - return s.toString() - } - - fun addLine(line: String) { - lines.add(line) - } - - fun addLines(lines: List) { - this.lines.addAll(lines) - } - - fun getLine(i: Int): String { - return lines[i] - } - - fun getLines(): List { - return lines - } - - fun size(): Int { - return lines.size - } -} diff --git a/app/src/main/java/xyz/fycz/myreader/widget/page2/animation/CoverPageAnim.java b/app/src/main/java/xyz/fycz/myreader/widget/page2/animation/CoverPageAnim.java deleted file mode 100644 index 59eedca..0000000 --- a/app/src/main/java/xyz/fycz/myreader/widget/page2/animation/CoverPageAnim.java +++ /dev/null @@ -1,87 +0,0 @@ -package xyz.fycz.myreader.widget.page2.animation; - -import android.graphics.Canvas; -import android.graphics.Rect; -import android.graphics.drawable.GradientDrawable; -import android.view.View; - -/** - * 覆盖翻页 - */ - -public class CoverPageAnim extends HorizonPageAnim { - - private Rect mSrcRect, mDestRect; - private GradientDrawable mBackShadowDrawableLR; - - public CoverPageAnim(int w, int h, View view, OnPageChangeListener listener) { - super(w, h, view, listener); - mSrcRect = new Rect(0, 0, mViewWidth, mViewHeight); - mDestRect = new Rect(0, 0, mViewWidth, mViewHeight); - int[] mBackShadowColors = new int[]{0x66000000, 0x00000000}; - mBackShadowDrawableLR = new GradientDrawable( - GradientDrawable.Orientation.LEFT_RIGHT, mBackShadowColors); - mBackShadowDrawableLR.setGradientType(GradientDrawable.LINEAR_GRADIENT); - } - - @Override - public void drawMove(Canvas canvas) { - int dis; - if (mDirection == Direction.NEXT) { - dis = (int) (mViewWidth - mStartX + mTouchX); - if (dis > mViewWidth) { - dis = mViewWidth; - } - //计算bitmap截取的区域 - mSrcRect.left = mViewWidth - dis; - //计算bitmap在canvas显示的区域 - mDestRect.right = dis; - canvas.drawBitmap(bitmapList.get(2), 0, 0, null); - canvas.drawBitmap(bitmapList.get(1), mSrcRect, mDestRect, null); - addShadow(dis, canvas); - } else { - dis = (int) (mTouchX - mStartX); - if (dis > mViewWidth) { - dis = mViewWidth; - } - mSrcRect.left = mViewWidth - dis; - mDestRect.right = dis; - canvas.drawBitmap(bitmapList.get(1), 0, 0, null); - canvas.drawBitmap(bitmapList.get(0), mSrcRect, mDestRect, null); - addShadow(dis, canvas); - } - } - - //添加阴影 - private void addShadow(int left, Canvas canvas) { - mBackShadowDrawableLR.setBounds(left, 0, left + 30, mScreenHeight); - mBackShadowDrawableLR.draw(canvas); - } - - @Override - public void startAnim() { - int dx; - if (mDirection == Direction.NEXT) { - if (isCancel) { - int dis = (int) ((mViewWidth - mStartX) + mTouchX); - if (dis > mViewWidth) { - dis = mViewWidth; - } - dx = mViewWidth - dis; - } else { - dx = (int) -(mTouchX + (mViewWidth - mStartX)); - } - } else { - if (isCancel) { - dx = (int) -(mTouchX - mStartX); - } else { - dx = (int) (mViewWidth - (mTouchX - mStartX)); - } - } - - //滑动速度保持一致 - int duration = (animationSpeed * Math.abs(dx)) / mViewWidth; - mScroller.startScroll((int) mTouchX, 0, dx, 0, duration); - super.startAnim(); - } -} diff --git a/app/src/main/java/xyz/fycz/myreader/widget/page2/animation/HorizonPageAnim.java b/app/src/main/java/xyz/fycz/myreader/widget/page2/animation/HorizonPageAnim.java deleted file mode 100644 index bb0d89f..0000000 --- a/app/src/main/java/xyz/fycz/myreader/widget/page2/animation/HorizonPageAnim.java +++ /dev/null @@ -1,190 +0,0 @@ -package xyz.fycz.myreader.widget.page2.animation; - -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.view.MotionEvent; -import android.view.View; -import android.view.ViewConfiguration; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * 横向动画的模板 - */ - -public abstract class HorizonPageAnim extends PageAnimation { - private static final String TAG = "HorizonPageAnim"; - List bitmapList = new ArrayList<>(); - - HorizonPageAnim(int w, int h, View view, OnPageChangeListener listener) { - super(w, h, view, listener); - //创建图片 - for (int i = 0; i < 3; i++) { - bitmapList.add(Bitmap.createBitmap(mViewWidth, mViewHeight, Bitmap.Config.ARGB_8888)); - } - } - - /** - * 转换页面,在显示下一章的时候,必须首先调用此方法 - */ - @Override - public boolean changePage() { - if (isCancel) return false; - switch (mDirection) { - case NEXT: - Collections.swap(bitmapList, 0, 1); - Collections.swap(bitmapList, 1, 2); - break; - case PREV: - Collections.swap(bitmapList, 1, 2); - Collections.swap(bitmapList, 0, 1); - break; - default: - return false; - } - return true; - } - - public abstract void drawMove(Canvas canvas); - - @Override - public void onTouchEvent(MotionEvent event) { - abortAnim(); - final int slop = ViewConfiguration.get(mView.getContext()).getScaledTouchSlop(); - //获取点击位置 - int x = (int) event.getX(); - int y = (int) event.getY(); - //设置触摸点 - setTouchPoint(x, y); - - switch (event.getAction()) { - case MotionEvent.ACTION_DOWN: - break; - case MotionEvent.ACTION_MOVE: - //判断是否移动了 - if (!isMove) { - isMove = Math.abs(mStartX - x) > slop || Math.abs(mStartY - y) > slop; - } - - if (isMove) { - //判断是否是准备移动的状态(将要移动但是还没有移动) - if (mMoveX == 0 && mMoveY == 0) { - //判断翻得是上一页还是下一页 - if (x - mStartX > 0) { - //上一页的参数配置 - isNext = false; - boolean hasPrev = mListener.hasPrev(); - setDirection(Direction.PREV); - //如果上一页不存在 - if (!hasPrev) { - noNext = true; - return; - } - } else { - //进行下一页的配置 - isNext = true; - //判断是否下一页存在 - boolean hasNext = mListener.hasNext(0); - //如果存在设置动画方向 - setDirection(Direction.NEXT); - - //如果不存在表示没有下一页了 - if (!hasNext) { - noNext = true; - return; - } - } - } else { - //判断是否取消翻页 - isCancel = isNext ? x - mMoveX > 0 : x - mMoveX < 0; - } - - mMoveX = x; - mMoveY = y; - isRunning = true; - mView.invalidate(); - } - break; - case MotionEvent.ACTION_CANCEL: - case MotionEvent.ACTION_UP: - isRunning = false; - if (!isMove) { - - if (!readBookControl.getCanClickTurn()) { - return; - } - - isNext = x > mScreenWidth / 2 || readBookControl.getClickAllNext(); - - if (isNext) { - //判断是否下一页存在 - boolean hasNext = mListener.hasNext(0); - //设置动画方向 - if (!hasNext) { - return; - } - setDirection(Direction.NEXT); - } else { - boolean hasPrev = mListener.hasPrev(); - if (!hasPrev) { - return; - } - setDirection(Direction.PREV); - } - } else { - isCancel = Math.abs(mLastX - mStartX) < slop * 3 || isCancel; - } - - // 开启翻页效果 - if (!noNext) { - startAnim(); - } - mView.invalidate(); - break; - } - } - - @Override - public void draw(Canvas canvas) { - if (isRunning && !noNext) { - drawMove(canvas); - } else { - canvas.drawBitmap(getBgBitmap(0), 0, 0, null); - isCancel = true; - } - } - - @Override - public void abortAnim() { - if (!mScroller.isFinished()) { - mScroller.abortAnimation(); - if (changePage()) { - mListener.changePage(mDirection); - setDirection(PageAnimation.Direction.NONE); - } - movingFinish(); - setTouchPoint(mScroller.getFinalX(), mScroller.getFinalY()); - mView.invalidate(); - } - } - - @Override - public Bitmap getBgBitmap(int pageOnCur) { - if (pageOnCur < 0) { - return bitmapList.get(0); - } else if (pageOnCur > 0) { - return bitmapList.get(2); - } - return bitmapList.get(1); - } - - public void setCancel(boolean cancel) { - isCancel = cancel; - } - - public void setNoNext(boolean noNext) { - this.noNext = noNext; - } -} diff --git a/app/src/main/java/xyz/fycz/myreader/widget/page2/animation/NonePageAnim.java b/app/src/main/java/xyz/fycz/myreader/widget/page2/animation/NonePageAnim.java deleted file mode 100644 index 097d6a7..0000000 --- a/app/src/main/java/xyz/fycz/myreader/widget/page2/animation/NonePageAnim.java +++ /dev/null @@ -1,26 +0,0 @@ -package xyz.fycz.myreader.widget.page2.animation; - -import android.graphics.Canvas; -import android.view.View; - -/** - * 无动画翻页 - */ - -public class NonePageAnim extends HorizonPageAnim { - - public NonePageAnim(int w, int h, View view, OnPageChangeListener listener) { - super(w, h, view, listener); - } - - @Override - public void drawMove(Canvas canvas) { - canvas.drawBitmap(bitmapList.get(1), 0, 0, null); - } - - @Override - public void startAnim() { - super.startAnim(); - isRunning = false; - } -} diff --git a/app/src/main/java/xyz/fycz/myreader/widget/page2/animation/PageAnimation.java b/app/src/main/java/xyz/fycz/myreader/widget/page2/animation/PageAnimation.java deleted file mode 100644 index d347f89..0000000 --- a/app/src/main/java/xyz/fycz/myreader/widget/page2/animation/PageAnimation.java +++ /dev/null @@ -1,273 +0,0 @@ -package xyz.fycz.myreader.widget.page2.animation; - -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.view.MotionEvent; -import android.view.View; -import android.view.animation.LinearInterpolator; -import android.widget.Scroller; - -import androidx.annotation.NonNull; - -import xyz.fycz.myreader.R; -import xyz.fycz.myreader.application.MyApplication; -import xyz.fycz.myreader.entity.ReadBookControl; - - -/** - * 翻页动画抽象类 - */ - -public abstract class PageAnimation { - //动画速度 - static final int animationSpeed = 300; - //正在使用的View - protected View mView; - protected ReadBookControl readBookControl = ReadBookControl.getInstance(); - //滑动装置 - Scroller mScroller; - //监听器 - protected OnPageChangeListener mListener; - //移动方向 - Direction mDirection = Direction.NONE; - - //屏幕的尺寸 - int mScreenWidth; - int mScreenHeight; - int mMarginTop; - //视图的尺寸 - int mViewWidth; - int mViewHeight; - //起始点 - float mStartX; - float mStartY; - //触碰点 - float mTouchX; - float mTouchY; - //上一个触碰点 - float mLastX; - float mLastY; - private boolean isMoving = false; - boolean isRunning = false; - private boolean touchInit = false; - //是否取消翻页 - boolean isCancel = false; - //可以使用 mLast代替 - int mMoveX = 0; - int mMoveY = 0; - //是否移动了 - boolean isMove = false; - //是否翻阅下一页。true表示翻到下一页,false表示上一页。 - boolean isNext = false; - //是否没下一页或者上一页 - boolean noNext = false; - - PageAnimation(int w, int h, View view, OnPageChangeListener listener) { - this(w, h, 0, 0, 0, view, listener); - } - - PageAnimation(int w, int h, int marginWidth, int marginTop, int marginBottom, View view, OnPageChangeListener listener) { - mScreenWidth = w; - mScreenHeight = h; - - //屏幕的间距 - mMarginTop = marginTop; - - mViewWidth = mScreenWidth - marginWidth * 2; - mViewHeight = mScreenHeight - mMarginTop - marginBottom; - - mView = view; - mListener = listener; - - mScroller = new Scroller(mView.getContext(), new LinearInterpolator()); - } - - public Scroller getScroller() { - return mScroller; - } - - public void setStartPoint(float x, float y) { - mStartX = x; - mStartY = y; - - mLastX = mStartX; - mLastY = mStartY; - } - - public void setTouchPoint(float x, float y) { - mLastX = mTouchX; - mLastY = mTouchY; - - mTouchX = x; - mTouchY = y; - } - - public void setTouchInitFalse() { - touchInit = false; - } - - public void initTouch(int x, int y) { - if (!touchInit) { - //移动的点击位置 - mMoveX = 0; - mMoveY = 0; - //是否移动 - isMove = false; - //是否存在下一章 - noNext = false; - //是下一章还是前一章 - isNext = false; - //是否正在执行动画 - isRunning = false; - //取消 - isCancel = false; - //设置起始位置的触摸点 - setStartPoint(x, y); - touchInit = true; - } - } - - public boolean isRunning() { - return isRunning; - } - - void movingFinish() { - isMoving = false; - isRunning = false; - } - - /** - * 开启翻页动画 - */ - public void startAnim() { - isRunning = true; - isMoving = true; - mView.invalidate(); - } - - public void setDirection(Direction direction) { - mDirection = direction; - } - - public void clear() { - mView = null; - } - - /** - * 点击事件的处理 - */ - public abstract void onTouchEvent(MotionEvent event); - - /** - * 绘制图形 - */ - public abstract void draw(Canvas canvas); - - /** - * 滚动动画 - * 必须放在computeScroll()方法中执行 - */ - public void scrollAnim() { - if (mScroller.computeScrollOffset()) { - int x = mScroller.getCurrX(); - int y = mScroller.getCurrY(); - - setTouchPoint(x, y); - - mView.postInvalidate(); - } else if (isMoving) { - if (changePage()) { - mListener.changePage(mDirection); - setDirection(Direction.NONE); - } - movingFinish(); - } - } - - /** - * 取消动画 - */ - public abstract void abortAnim(); - - public abstract boolean changePage(); - - /** - * 获取背景板 - * pageOnCur: 位于当前页的位置, 小于0上一页, 0 当前页, 大于0下一页 - */ - public abstract Bitmap getBgBitmap(int pageOnCur); - - /** - * 翻页模式 - */ - public enum Mode { - COVER(MyApplication.getApplication().getString(R.string.page_mode_COVER)), - SIMULATION(MyApplication.getApplication().getString(R.string.page_mode_SIMULATION)), - SLIDE(MyApplication.getApplication().getString(R.string.page_mode_SLIDE)), - SCROLL(MyApplication.getApplication().getString(R.string.page_mode_SCROLL)), - NONE(MyApplication.getApplication().getString(R.string.page_mode_NONE)); - - private String name; - - Mode(String name) { - this.name = name; - } - - public static Mode getPageMode(int pageMode) { - switch (pageMode) { - case 0: - return COVER; - case 1: - return SIMULATION; - case 2: - return SLIDE; - case 3: - return SCROLL; - case 4: - return NONE; - default: - return COVER; - } - } - - public static String[] getAllPageMode() { - return new String[]{COVER.name, SIMULATION.name, SLIDE.name, SCROLL.name, NONE.name}; - } - - @NonNull - @Override - public String toString() { - return this.name; - } - } - - /** - * 翻页方向 - */ - public enum Direction { - NONE(true), NEXT(true), PREV(true); - - public final boolean isHorizontal; - - Direction(boolean isHorizontal) { - this.isHorizontal = isHorizontal; - } - } - - public interface OnPageChangeListener { - - void resetScroll(); - - boolean hasPrev(); - - boolean hasNext(int pageOnCur); - - void drawContent(Canvas canvas, float offset); - - void drawBackground(Canvas canvas); - - void changePage(Direction direction); - - } - -} diff --git a/app/src/main/java/xyz/fycz/myreader/widget/page2/animation/ScrollPageAnim.java b/app/src/main/java/xyz/fycz/myreader/widget/page2/animation/ScrollPageAnim.java deleted file mode 100644 index bde29de..0000000 --- a/app/src/main/java/xyz/fycz/myreader/widget/page2/animation/ScrollPageAnim.java +++ /dev/null @@ -1,148 +0,0 @@ -package xyz.fycz.myreader.widget.page2.animation; - -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.view.MotionEvent; -import android.view.VelocityTracker; -import android.view.View; -import android.view.ViewConfiguration; - - -public class ScrollPageAnim extends PageAnimation { - private static final String TAG = "ScrollAnimation"; - // 滑动追踪的时间 - private static final int VELOCITY_DURATION = 1000; - private VelocityTracker mVelocity; - // 整个Bitmap的背景显示 - private Bitmap mBgBitmap; - - public ScrollPageAnim(int w, int h, int marginWidth, int marginTop, int marginBottom, View view, OnPageChangeListener listener) { - super(w, h, marginWidth, marginTop, marginBottom, view, listener); - mListener.resetScroll(); - mBgBitmap = Bitmap.createBitmap(mScreenWidth, mScreenHeight, Bitmap.Config.ARGB_8888); - } - - @Override - public void onTouchEvent(MotionEvent event) { - final int slop = ViewConfiguration.get(mView.getContext()).getScaledTouchSlop(); - int x = (int) event.getX(); - int y = (int) event.getY(); - - // 初始化速度追踪器 - if (mVelocity == null) { - mVelocity = VelocityTracker.obtain(); - } - - mVelocity.addMovement(event); - // 设置触碰点 - setTouchPoint(x, y); - - switch (event.getAction()) { - case MotionEvent.ACTION_DOWN: - isMove = false; - isRunning = false; - // 设置起始点 - setStartPoint(x, y); - // 停止动画 - abortAnim(); - break; - case MotionEvent.ACTION_MOVE: - if (!isMove) { - isMove = Math.abs(mStartX - x) > slop || Math.abs(mStartY - y) > slop; - } - mVelocity.computeCurrentVelocity(VELOCITY_DURATION); - isRunning = true; - // 进行刷新 - mView.postInvalidate(); - break; - case MotionEvent.ACTION_CANCEL: - case MotionEvent.ACTION_UP: - isRunning = false; - if (!isMove) { - - if (!readBookControl.getCanClickTurn() || readBookControl.disableScrollClickTurn()) { - return; - } - - //是否翻阅下一页。true表示翻到下一页,false表示上一页。 - boolean isNext = x > mScreenWidth / 2 || readBookControl.getClickAllNext(); - if (isNext) { - startAnim(Direction.NEXT); - } else { - startAnim(Direction.PREV); - } - } else { - // 开启动画 - startAnim(); - } - // 删除检测器 - if (mVelocity != null) { - mVelocity.recycle(); - mVelocity = null; - } - break; - } - } - - @Override - public void draw(Canvas canvas) { - //进行布局 - float offset = mLastY - mTouchY; - - //绘制背景 - mListener.drawBackground(canvas); - //绘制内容 - canvas.save(); - //移动位置 - canvas.translate(0, mMarginTop); - //裁剪显示区域 - canvas.clipRect(0, 0, mViewWidth, mViewHeight); - mListener.drawContent(canvas, offset); - canvas.restore(); - } - - @Override - public synchronized void startAnim() { - super.startAnim(); - //惯性滚动 - mScroller.fling(0, (int) mTouchY, 0, (int) mVelocity.getYVelocity(), - 0, 0, -10 * mViewHeight, 10 * mViewHeight); - } - - /** - * 翻页动画 - */ - public void startAnim(Direction direction) { - setStartPoint(0, 0); - setTouchPoint(0, 0); - switch (direction) { - case NEXT: - super.startAnim(); - mScroller.startScroll(0, 0, 0, -mViewHeight + 300, animationSpeed); - break; - case PREV: - super.startAnim(); - mScroller.startScroll(0, 0, 0, mViewHeight - 300, animationSpeed); - break; - } - } - - @Override - public void abortAnim() { - if (!mScroller.isFinished()) { - mScroller.abortAnimation(); - isRunning = false; - } - } - - @Override - public boolean changePage() { - return false; - } - - @Override - public Bitmap getBgBitmap(int pageOnCur) { - return mBgBitmap; - } - -} diff --git a/app/src/main/java/xyz/fycz/myreader/widget/page2/animation/SimulationPageAnim.java b/app/src/main/java/xyz/fycz/myreader/widget/page2/animation/SimulationPageAnim.java deleted file mode 100644 index 3cb3a03..0000000 --- a/app/src/main/java/xyz/fycz/myreader/widget/page2/animation/SimulationPageAnim.java +++ /dev/null @@ -1,569 +0,0 @@ -package xyz.fycz.myreader.widget.page2.animation; - -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.ColorMatrix; -import android.graphics.ColorMatrixColorFilter; -import android.graphics.Matrix; -import android.graphics.Paint; -import android.graphics.Path; -import android.graphics.PointF; -import android.graphics.Region; -import android.graphics.drawable.GradientDrawable; -import android.os.Build; -import android.view.View; - -/** - * 仿真翻页 - */ -public class SimulationPageAnim extends HorizonPageAnim { - private static final String TAG = "SimulationPageAnim"; - - private int mCornerX = 1; // 拖拽点对应的页脚 - private int mCornerY = 1; - private Path mPath0; - private Path mPath1; - - private PointF mBezierStart1 = new PointF(); // 贝塞尔曲线起始点 - private PointF mBezierControl1 = new PointF(); // 贝塞尔曲线控制点 - private PointF mBezierVertex1 = new PointF(); // 贝塞尔曲线顶点 - private PointF mBezierEnd1 = new PointF(); // 贝塞尔曲线结束点 - - private PointF mBezierStart2 = new PointF(); // 另一条贝塞尔曲线 - private PointF mBezierControl2 = new PointF(); - private PointF mBezierVertex2 = new PointF(); - private PointF mBezierEnd2 = new PointF(); - - private float mMiddleX; - private float mMiddleY; - private float mDegrees; - private float mTouchToCornerDis; - private ColorMatrixColorFilter mColorMatrixFilter; - private Matrix mMatrix; - private float[] mMatrixArray = {0, 0, 0, 0, 0, 0, 0, 0, 1.0f}; - - private boolean mIsRT_LB; // 是否属于右上左下 - private float mMaxLength; - private int[] mBackShadowColors;// 背面颜色组 - private int[] mFrontShadowColors;// 前面颜色组 - private GradientDrawable mBackShadowDrawableLR; // 有阴影的GradientDrawable - private GradientDrawable mBackShadowDrawableRL; - private GradientDrawable mFolderShadowDrawableLR; - private GradientDrawable mFolderShadowDrawableRL; - - private GradientDrawable mFrontShadowDrawableHBT; - private GradientDrawable mFrontShadowDrawableHTB; - private GradientDrawable mFrontShadowDrawableVLR; - private GradientDrawable mFrontShadowDrawableVRL; - - private Paint mPaint; - - - public SimulationPageAnim(int w, int h, View view, OnPageChangeListener listener) { - super(w, h, view, listener); - mPath0 = new Path(); - mPath1 = new Path(); - mMaxLength = (float) Math.hypot(mScreenWidth, mScreenHeight); - mPaint = new Paint(); - - mPaint.setStyle(Paint.Style.FILL); - - createDrawable(); - - ColorMatrix cm = new ColorMatrix();//设置颜色数组 - float[] array = {1, 0, 0, 0, 0, - 0, 1, 0, 0, 0, - 0, 0, 1, 0, 0, - 0, 0, 0, 1, 0}; - cm.set(array); - mColorMatrixFilter = new ColorMatrixColorFilter(cm); - mMatrix = new Matrix(); - - mTouchX = 0.01f; // 不让x,y为0,否则在点计算时会有问题 - mTouchY = 0.01f; - } - - @Override - public void setStartPoint(float x, float y) { - super.setStartPoint(x, y); - calcCornerXY(x, y); - } - - @Override - public void setTouchPoint(float x, float y) { - super.setTouchPoint(x, y); - //触摸y中间位置吧y变成屏幕高度 - if ((mStartY > mScreenHeight / 3.0 && mStartY < mScreenHeight * 2 / 3.0) || mDirection.equals(Direction.PREV)) { - mTouchY = mScreenHeight; - } - - if (mStartY > mScreenHeight / 3.0 && mStartY < mScreenHeight / 2.0 && mDirection.equals(Direction.NEXT)) { - mTouchY = 1; - } - } - - @Override - public void setDirection(Direction direction) { - super.setDirection(direction); - - switch (direction) { - case PREV: - //上一页滑动不出现对角 - if (mStartX > mScreenWidth / 2.0) { - calcCornerXY(mStartX, mScreenHeight); - } else { - calcCornerXY(mScreenWidth - mStartX, mScreenHeight); - } - break; - case NEXT: - if (mScreenWidth / 2.0 > mStartX) { - calcCornerXY(mScreenWidth - mStartX, mStartY); - } - break; - } - } - - @Override - public void startAnim() { - int dx, dy; - // dx 水平方向滑动的距离,负值会使滚动向左滚动 - // dy 垂直方向滑动的距离,负值会使滚动向上滚动 - if (isCancel) { - - if (mCornerX > 0 && mDirection.equals(Direction.NEXT)) { - dx = (int) (mScreenWidth - mTouchX); - } else { - dx = -(int) mTouchX; - } - - if (!mDirection.equals(Direction.NEXT)) { - dx = (int) -(mScreenWidth + mTouchX); - } - - if (mCornerY > 0) { - dy = (int) (mScreenHeight - mTouchY); - } else { - dy = -(int) mTouchY; // 防止mTouchY最终变为0 - } - } else { - if (mCornerX > 0 && mDirection.equals(Direction.NEXT)) { - dx = -(int) (mScreenWidth + mTouchX); - } else { - dx = (int) (mScreenWidth - mTouchX + mScreenWidth); - } - if (mCornerY > 0) { - dy = (int) (mScreenHeight - mTouchY); - } else { - dy = (int) (1 - mTouchY); // 防止mTouchY最终变为0 - } - } - mScroller.startScroll((int) mTouchX, (int) mTouchY, dx, dy, animationSpeed); - super.startAnim(); - } - - @Override - public void drawMove(Canvas canvas) { - if (mDirection == Direction.NEXT) { - calcPoints(); - drawCurrentPageArea(canvas, bitmapList.get(1));//绘制翻页时的正面页 - drawNextPageAreaAndShadow(canvas, bitmapList.get(2)); - drawCurrentPageShadow(canvas); - drawCurrentBackArea(canvas, bitmapList.get(1)); - } else { - calcPoints(); - drawCurrentPageArea(canvas, bitmapList.get(0)); - drawNextPageAreaAndShadow(canvas, bitmapList.get(1)); - drawCurrentPageShadow(canvas); - drawCurrentBackArea(canvas, bitmapList.get(0)); - } - } - - /** - * 创建阴影的GradientDrawable - */ - private void createDrawable() { - int[] color = {0x333333, 0xb0333333}; - mFolderShadowDrawableRL = new GradientDrawable( - GradientDrawable.Orientation.RIGHT_LEFT, color); - mFolderShadowDrawableRL - .setGradientType(GradientDrawable.LINEAR_GRADIENT); - - mFolderShadowDrawableLR = new GradientDrawable( - GradientDrawable.Orientation.LEFT_RIGHT, color); - mFolderShadowDrawableLR - .setGradientType(GradientDrawable.LINEAR_GRADIENT); - - mBackShadowColors = new int[]{0xff111111, 0x111111}; - mBackShadowDrawableRL = new GradientDrawable( - GradientDrawable.Orientation.RIGHT_LEFT, mBackShadowColors); - mBackShadowDrawableRL.setGradientType(GradientDrawable.LINEAR_GRADIENT); - - mBackShadowDrawableLR = new GradientDrawable( - GradientDrawable.Orientation.LEFT_RIGHT, mBackShadowColors); - mBackShadowDrawableLR.setGradientType(GradientDrawable.LINEAR_GRADIENT); - - mFrontShadowColors = new int[]{0x80111111, 0x111111}; - mFrontShadowDrawableVLR = new GradientDrawable( - GradientDrawable.Orientation.LEFT_RIGHT, mFrontShadowColors); - mFrontShadowDrawableVLR - .setGradientType(GradientDrawable.LINEAR_GRADIENT); - mFrontShadowDrawableVRL = new GradientDrawable( - GradientDrawable.Orientation.RIGHT_LEFT, mFrontShadowColors); - mFrontShadowDrawableVRL - .setGradientType(GradientDrawable.LINEAR_GRADIENT); - - mFrontShadowDrawableHTB = new GradientDrawable( - GradientDrawable.Orientation.TOP_BOTTOM, mFrontShadowColors); - mFrontShadowDrawableHTB - .setGradientType(GradientDrawable.LINEAR_GRADIENT); - - mFrontShadowDrawableHBT = new GradientDrawable( - GradientDrawable.Orientation.BOTTOM_TOP, mFrontShadowColors); - mFrontShadowDrawableHBT - .setGradientType(GradientDrawable.LINEAR_GRADIENT); - } - - /** - * 绘制翻起页背面 - */ - private void drawCurrentBackArea(Canvas canvas, Bitmap bitmap) { - int i = (int) (mBezierStart1.x + mBezierControl1.x) / 2; - float f1 = Math.abs(i - mBezierControl1.x); - int i1 = (int) (mBezierStart2.y + mBezierControl2.y) / 2; - float f2 = Math.abs(i1 - mBezierControl2.y); - float f3 = Math.min(f1, f2); - mPath1.reset(); - mPath1.moveTo(mBezierVertex2.x, mBezierVertex2.y); - mPath1.lineTo(mBezierVertex1.x, mBezierVertex1.y); - mPath1.lineTo(mBezierEnd1.x, mBezierEnd1.y); - mPath1.lineTo(mTouchX, mTouchY); - mPath1.lineTo(mBezierEnd2.x, mBezierEnd2.y); - mPath1.close(); - GradientDrawable mFolderShadowDrawable; - int left; - int right; - if (mIsRT_LB) { - left = (int) (mBezierStart1.x - 1); - right = (int) (mBezierStart1.x + f3 + 1); - mFolderShadowDrawable = mFolderShadowDrawableLR; - } else { - left = (int) (mBezierStart1.x - f3 - 1); - right = (int) (mBezierStart1.x + 1); - mFolderShadowDrawable = mFolderShadowDrawableRL; - } - canvas.save(); - try { - canvas.clipPath(mPath0); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - canvas.clipPath(mPath1); - } else { - canvas.clipPath(mPath1, Region.Op.INTERSECT); - } - } catch (Exception ignored) { - } - - mPaint.setColorFilter(mColorMatrixFilter); - - float dis = (float) Math.hypot(mCornerX - mBezierControl1.x, - mBezierControl2.y - mCornerY); - float f8 = (mCornerX - mBezierControl1.x) / dis; - float f9 = (mBezierControl2.y - mCornerY) / dis; - mMatrixArray[0] = 1 - 2 * f9 * f9; - mMatrixArray[1] = 2 * f8 * f9; - mMatrixArray[3] = mMatrixArray[1]; - mMatrixArray[4] = 1 - 2 * f8 * f8; - mMatrix.reset(); - mMatrix.setValues(mMatrixArray); - mMatrix.preTranslate(-mBezierControl1.x, -mBezierControl1.y); - mMatrix.postTranslate(mBezierControl1.x, mBezierControl1.y); - canvas.drawBitmap(bitmap, mMatrix, mPaint); - - mPaint.setColorFilter(null); - - canvas.rotate(mDegrees, mBezierStart1.x, mBezierStart1.y); - mFolderShadowDrawable.setBounds( - left, (int) mBezierStart1.y, - right, (int) (mBezierStart1.y + mMaxLength) - ); - mFolderShadowDrawable.draw(canvas); - canvas.restore(); - } - - /** - * 绘制翻起页的阴影 - */ - private void drawCurrentPageShadow(Canvas canvas) { - double degree; - if (mIsRT_LB) { - degree = Math.PI / 4 - Math.atan2(mBezierControl1.y - mTouchY, mTouchX - mBezierControl1.x); - } else { - degree = Math.PI / 4 - Math.atan2(mTouchY - mBezierControl1.y, mTouchX - mBezierControl1.x); - } - // 翻起页阴影顶点与touch点的距离 - double d1 = (float) 25 * 1.414 * Math.cos(degree); - double d2 = (float) 25 * 1.414 * Math.sin(degree); - float x = (float) (mTouchX + d1); - float y; - if (mIsRT_LB) { - y = (float) (mTouchY + d2); - } else { - y = (float) (mTouchY - d2); - } - mPath1.reset(); - mPath1.moveTo(x, y); - mPath1.lineTo(mTouchX, mTouchY); - mPath1.lineTo(mBezierControl1.x, mBezierControl1.y); - mPath1.lineTo(mBezierStart1.x, mBezierStart1.y); - mPath1.close(); - canvas.save(); - try { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - canvas.clipOutPath(mPath0); - } else { - canvas.clipPath(mPath0, Region.Op.XOR); - } - - canvas.clipPath(mPath1, Region.Op.INTERSECT); - } catch (Exception ignored) { - } - - int leftx; - int rightx; - GradientDrawable mCurrentPageShadow; - if (mIsRT_LB) { - leftx = (int) (mBezierControl1.x); - rightx = (int) mBezierControl1.x + 25; - mCurrentPageShadow = mFrontShadowDrawableVLR; - } else { - leftx = (int) (mBezierControl1.x - 25); - rightx = (int) mBezierControl1.x + 1; - mCurrentPageShadow = mFrontShadowDrawableVRL; - } - - float rotateDegrees; - rotateDegrees = (float) Math.toDegrees(Math.atan2(mTouchX - mBezierControl1.x, mBezierControl1.y - mTouchY)); - canvas.rotate(rotateDegrees, mBezierControl1.x, mBezierControl1.y); - mCurrentPageShadow.setBounds( - leftx, (int) (mBezierControl1.y - mMaxLength), - rightx, (int) (mBezierControl1.y)); - mCurrentPageShadow.draw(canvas); - canvas.restore(); - - mPath1.reset(); - mPath1.moveTo(x, y); - mPath1.lineTo(mTouchX, mTouchY); - mPath1.lineTo(mBezierControl2.x, mBezierControl2.y); - mPath1.lineTo(mBezierStart2.x, mBezierStart2.y); - mPath1.close(); - canvas.save(); - try { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - canvas.clipOutPath(mPath0); - } else { - canvas.clipPath(mPath0, Region.Op.XOR); - } - - canvas.clipPath(mPath1); - } catch (Exception ignored) { - } - - if (mIsRT_LB) { - leftx = (int) (mBezierControl2.y); - rightx = (int) (mBezierControl2.y + 25); - mCurrentPageShadow = mFrontShadowDrawableHTB; - } else { - leftx = (int) (mBezierControl2.y - 25); - rightx = (int) (mBezierControl2.y + 1); - mCurrentPageShadow = mFrontShadowDrawableHBT; - } - rotateDegrees = (float) Math.toDegrees(Math.atan2(mBezierControl2.y - mTouchY, mBezierControl2.x - mTouchX)); - canvas.rotate(rotateDegrees, mBezierControl2.x, mBezierControl2.y); - float temp; - if (mBezierControl2.y < 0) temp = mBezierControl2.y - mScreenHeight; - else temp = mBezierControl2.y; - - int hmg = (int) Math.hypot(mBezierControl2.x, temp); - if (hmg > mMaxLength) - mCurrentPageShadow.setBounds( - (int) (mBezierControl2.x - 25) - hmg, leftx, - (int) (mBezierControl2.x + mMaxLength) - hmg, rightx - ); - else - mCurrentPageShadow.setBounds( - (int) (mBezierControl2.x - mMaxLength), leftx, - (int) (mBezierControl2.x), rightx); - - mCurrentPageShadow.draw(canvas); - canvas.restore(); - } - - private void drawNextPageAreaAndShadow(Canvas canvas, Bitmap bitmap) { - mPath1.reset(); - mPath1.moveTo(mBezierStart1.x, mBezierStart1.y); - mPath1.lineTo(mBezierVertex1.x, mBezierVertex1.y); - mPath1.lineTo(mBezierVertex2.x, mBezierVertex2.y); - mPath1.lineTo(mBezierStart2.x, mBezierStart2.y); - mPath1.lineTo(mCornerX, mCornerY); - mPath1.close(); - - mDegrees = (float) Math.toDegrees(Math.atan2(mBezierControl1.x - mCornerX, - mBezierControl2.y - mCornerY)); - int leftx; - int rightx; - GradientDrawable mBackShadowDrawable; - if (mIsRT_LB) { //左下及右上 - leftx = (int) (mBezierStart1.x); - rightx = (int) (mBezierStart1.x + mTouchToCornerDis / 4); - mBackShadowDrawable = mBackShadowDrawableLR; - } else { - leftx = (int) (mBezierStart1.x - mTouchToCornerDis / 4); - rightx = (int) mBezierStart1.x; - mBackShadowDrawable = mBackShadowDrawableRL; - } - canvas.save(); - try { - canvas.clipPath(mPath0); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - canvas.clipPath(mPath1); - } else { - canvas.clipPath(mPath1, Region.Op.INTERSECT); - } - //canvas.clipPath(mPath1, Region.Op.INTERSECT); - } catch (Exception ignored) { - } - - canvas.drawBitmap(bitmap, 0, 0, null); - canvas.rotate(mDegrees, mBezierStart1.x, mBezierStart1.y); - mBackShadowDrawable.setBounds( - leftx, (int) mBezierStart1.y, - rightx, (int) (mMaxLength + mBezierStart1.y));//左上及右下角的xy坐标值,构成一个矩形 - mBackShadowDrawable.draw(canvas); - canvas.restore(); - } - - private void drawCurrentPageArea(Canvas canvas, Bitmap bitmap) { - mPath0.reset(); - mPath0.moveTo(mBezierStart1.x, mBezierStart1.y); - mPath0.quadTo(mBezierControl1.x, mBezierControl1.y, mBezierEnd1.x, mBezierEnd1.y); - mPath0.lineTo(mTouchX, mTouchY); - mPath0.lineTo(mBezierEnd2.x, mBezierEnd2.y); - mPath0.quadTo(mBezierControl2.x, mBezierControl2.y, mBezierStart2.x, mBezierStart2.y); - mPath0.lineTo(mCornerX, mCornerY); - mPath0.close(); - - canvas.save(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - canvas.clipOutPath(mPath0); - } else { - canvas.clipPath(mPath0, Region.Op.XOR); - } - canvas.drawBitmap(bitmap, 0, 0, null); - try { - canvas.restore(); - } catch (Exception e) { - e.printStackTrace(); - } - } - - /** - * 计算拖拽点对应的拖拽脚 - */ - private void calcCornerXY(float x, float y) { - if (x <= mScreenWidth / 2.0) { - mCornerX = 0; - } else { - mCornerX = mScreenWidth; - } - if (y <= mScreenHeight / 2.0) { - mCornerY = 0; - } else { - mCornerY = mScreenHeight; - } - - mIsRT_LB = (mCornerX == 0 && mCornerY == mScreenHeight) - || (mCornerX == mScreenWidth && mCornerY == 0); - - } - - private void calcPoints() { - mMiddleX = (mTouchX + mCornerX) / 2; - mMiddleY = (mTouchY + mCornerY) / 2; - mBezierControl1.x = - mMiddleX - (mCornerY - mMiddleY) * (mCornerY - mMiddleY) / (mCornerX - mMiddleX); - mBezierControl1.y = mCornerY; - - mBezierControl2.x = mCornerX; - if (mCornerY - mMiddleY == 0) { - mBezierControl2.y = mMiddleY - (mCornerX - mMiddleX) * (mCornerX - mMiddleX) / 0.1f; - } else { - mBezierControl2.y = mMiddleY - (mCornerX - mMiddleX) - * (mCornerX - mMiddleX) / (mCornerY - mMiddleY); - } - mBezierStart1.x = mBezierControl1.x - (mCornerX - mBezierControl1.x) / 2; - mBezierStart1.y = mCornerY; - - // 固定左边上下两个点 - if (mTouchX > 0 && mTouchX < mScreenWidth) { - if (mBezierStart1.x < 0 || mBezierStart1.x > mScreenWidth) { - if (mBezierStart1.x < 0) - mBezierStart1.x = mScreenWidth - mBezierStart1.x; - - float f1 = Math.abs(mCornerX - mTouchX); - float f2 = mScreenWidth * f1 / mBezierStart1.x; - mTouchX = Math.abs(mCornerX - f2); - - float f3 = Math.abs(mCornerX - mTouchX) * Math.abs(mCornerY - mTouchY) / f1; - mTouchY = Math.abs(mCornerY - f3); - - mMiddleX = (mTouchX + mCornerX) / 2; - mMiddleY = (mTouchY + mCornerY) / 2; - - mBezierControl1.x = - mMiddleX - (mCornerY - mMiddleY) * (mCornerY - mMiddleY) / (mCornerX - mMiddleX); - mBezierControl1.y = mCornerY; - - mBezierControl2.x = mCornerX; - float f5 = mCornerY - mMiddleY; - if (f5 == 0) { - mBezierControl2.y = mMiddleY - (mCornerX - mMiddleX) - * (mCornerX - mMiddleX) / 0.1f; - } else { - mBezierControl2.y = mMiddleY - (mCornerX - mMiddleX) - * (mCornerX - mMiddleX) / (mCornerY - mMiddleY); - } - - mBezierStart1.x = mBezierControl1.x - (mCornerX - mBezierControl1.x) / 2; - } - } - mBezierStart2.x = mCornerX; - mBezierStart2.y = mBezierControl2.y - (mCornerY - mBezierControl2.y) / 2; - - mTouchToCornerDis = (float) Math.hypot((mTouchX - mCornerX), (mTouchY - mCornerY)); - - mBezierEnd1 = - getCross(new PointF(mTouchX, mTouchY), mBezierControl1, mBezierStart1, mBezierStart2); - mBezierEnd2 = - getCross(new PointF(mTouchX, mTouchY), mBezierControl2, mBezierStart1, mBezierStart2); - - mBezierVertex1.x = (mBezierStart1.x + 2 * mBezierControl1.x + mBezierEnd1.x) / 4; - mBezierVertex1.y = (2 * mBezierControl1.y + mBezierStart1.y + mBezierEnd1.y) / 4; - mBezierVertex2.x = (mBezierStart2.x + 2 * mBezierControl2.x + mBezierEnd2.x) / 4; - mBezierVertex2.y = (2 * mBezierControl2.y + mBezierStart2.y + mBezierEnd2.y) / 4; - } - - /** - * 求解直线P1P2和直线P3P4的交点坐标 - */ - private PointF getCross(PointF P1, PointF P2, PointF P3, PointF P4) { - PointF CrossP = new PointF(); - // 二元函数通式: y=ax+b - float a1 = (P2.y - P1.y) / (P2.x - P1.x); - float b1 = ((P1.x * P2.y) - (P2.x * P1.y)) / (P1.x - P2.x); - - float a2 = (P4.y - P3.y) / (P4.x - P3.x); - float b2 = ((P3.x * P4.y) - (P4.x * P3.y)) / (P3.x - P4.x); - CrossP.x = (b2 - b1) / (a1 - a2); - CrossP.y = a1 * CrossP.x + b1; - return CrossP; - } -} diff --git a/app/src/main/java/xyz/fycz/myreader/widget/page2/animation/SlidePageAnim.java b/app/src/main/java/xyz/fycz/myreader/widget/page2/animation/SlidePageAnim.java deleted file mode 100644 index fba5a4e..0000000 --- a/app/src/main/java/xyz/fycz/myreader/widget/page2/animation/SlidePageAnim.java +++ /dev/null @@ -1,85 +0,0 @@ -package xyz.fycz.myreader.widget.page2.animation; - -import android.graphics.Canvas; -import android.graphics.Rect; -import android.view.View; - -/** - * 滑动翻页 - */ - -public class SlidePageAnim extends HorizonPageAnim { - private Rect mSrcRect, mDestRect, mNextSrcRect, mNextDestRect; - - public SlidePageAnim(int w, int h, View view, OnPageChangeListener listener) { - super(w, h, view, listener); - mSrcRect = new Rect(0, 0, mViewWidth, mViewHeight); - mDestRect = new Rect(0, 0, mViewWidth, mViewHeight); - mNextSrcRect = new Rect(0, 0, mViewWidth, mViewHeight); - mNextDestRect = new Rect(0, 0, mViewWidth, mViewHeight); - } - - @Override - public void drawMove(Canvas canvas) { - int dis; - if (mDirection == Direction.NEXT) {//左半边的剩余区域 - dis = (int) (mScreenWidth - mStartX + mTouchX); - if (dis > mScreenWidth) { - dis = mScreenWidth; - } - //计算bitmap截取的区域 - mSrcRect.left = mScreenWidth - dis; - //计算bitmap在canvas显示的区域 - mDestRect.right = dis; - //计算下一页截取的区域 - mNextSrcRect.right = mScreenWidth - dis; - //计算下一页在canvas显示的区域 - mNextDestRect.left = dis; - - canvas.drawBitmap(bitmapList.get(2), mNextSrcRect, mNextDestRect, null); - canvas.drawBitmap(bitmapList.get(1), mSrcRect, mDestRect, null); - } else { - dis = (int) (mTouchX - mStartX); - if (dis < 0) { - dis = 0; - mStartX = mTouchX; - } - mSrcRect.left = mScreenWidth - dis; - mDestRect.right = dis; - - //计算下一页截取的区域 - mNextSrcRect.right = mScreenWidth - dis; - //计算下一页在canvas显示的区域 - mNextDestRect.left = dis; - - canvas.drawBitmap(bitmapList.get(1), mNextSrcRect, mNextDestRect, null); - canvas.drawBitmap(bitmapList.get(0), mSrcRect, mDestRect, null); - } - } - - @Override - public void startAnim() { - int dx; - if (mDirection == Direction.NEXT) { - if (isCancel) { - int dis = (int) ((mScreenWidth - mStartX) + mTouchX); - if (dis > mScreenWidth) { - dis = mScreenWidth; - } - dx = mScreenWidth - dis; - } else { - dx = (int) -(mTouchX + (mScreenWidth - mStartX)); - } - } else { - if (isCancel) { - dx = (int) -Math.abs(mTouchX - mStartX); - } else { - dx = (int) (mScreenWidth - (mTouchX - mStartX)); - } - } - //滑动速度保持一致 - int duration = (animationSpeed * Math.abs(dx)) / mScreenWidth; - mScroller.startScroll((int) mTouchX, 0, dx, 0, duration); - super.startAnim(); - } -} diff --git a/app/src/main/res/layout/gridview_book_detailed_item.xml b/app/src/main/res/layout/gridview_book_detailed_item.xml index c0b3bcb..a1b7cae 100644 --- a/app/src/main/res/layout/gridview_book_detailed_item.xml +++ b/app/src/main/res/layout/gridview_book_detailed_item.xml @@ -140,18 +140,7 @@ style="?android:attr/progressBarStyleSmall" /> - -