diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 67af4688e..543c13f6c 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -185,6 +185,7 @@
android:launchMode="singleTop" />
【备份与恢复】,选择【导入旧版本数据】。
* 请关注[开源阅读软件]()支持我,同时关注合作公众号[小说拾遗](),阅读公众号小编。
+**2020/03/10**
+* 优化文字选择菜单弹出位置
+* 添加屏幕方向控制
+
+**2020/03/09**
+* 底部文字对齐
+* 主题添加阴影调节 by yangyxd
+
**2020/03/08**
* 订阅长按保存图片
* 订阅全屏播放
diff --git a/app/src/main/java/io/legado/app/constant/PreferKey.kt b/app/src/main/java/io/legado/app/constant/PreferKey.kt
index 1ba9ba6cf..e14ec42f6 100644
--- a/app/src/main/java/io/legado/app/constant/PreferKey.kt
+++ b/app/src/main/java/io/legado/app/constant/PreferKey.kt
@@ -3,7 +3,6 @@ package io.legado.app.constant
object PreferKey {
const val versionCode = "versionCode"
const val themeMode = "themeMode"
- const val downloadPath = "downloadPath"
const val hideStatusBar = "hideStatusBar"
const val clickTurnPage = "clickTurnPage"
const val clickAllNext = "clickAllNext"
diff --git a/app/src/main/java/io/legado/app/help/AppConfig.kt b/app/src/main/java/io/legado/app/help/AppConfig.kt
index 6eef2bfa0..4b768b9e7 100644
--- a/app/src/main/java/io/legado/app/help/AppConfig.kt
+++ b/app/src/main/java/io/legado/app/help/AppConfig.kt
@@ -32,6 +32,9 @@ object AppConfig {
App.INSTANCE.putPrefBoolean("transparentStatusBar", value)
}
+ val requestedDirection: String?
+ get() = App.INSTANCE.getPrefString(R.string.pk_requested_direction)
+
var backupPath: String?
get() = App.INSTANCE.getPrefString(PreferKey.backupPath)
set(value) {
@@ -49,7 +52,7 @@ object AppConfig {
}
val autoRefreshBook: Boolean
- get() = App.INSTANCE.getPrefBoolean(App.INSTANCE.getString(R.string.pk_auto_refresh))
+ get() = App.INSTANCE.getPrefBoolean(R.string.pk_auto_refresh)
var threadCount: Int
get() = App.INSTANCE.getPrefInt(PreferKey.threadCount, 16)
@@ -111,4 +114,9 @@ object AppConfig {
App.INSTANCE.putPrefBoolean("bookGroupAudio", value)
}
+ var elevation: Int
+ get() = App.INSTANCE.getPrefInt("elevation", -1)
+ set(value) {
+ App.INSTANCE.putPrefInt("elevation", value)
+ }
}
diff --git a/app/src/main/java/io/legado/app/help/BookHelp.kt b/app/src/main/java/io/legado/app/help/BookHelp.kt
index 304df9997..b6e3ec000 100644
--- a/app/src/main/java/io/legado/app/help/BookHelp.kt
+++ b/app/src/main/java/io/legado/app/help/BookHelp.kt
@@ -4,8 +4,8 @@ import android.net.Uri
import androidx.documentfile.provider.DocumentFile
import com.github.houbb.opencc4j.core.impl.ZhConvertBootstrap
import io.legado.app.App
+import io.legado.app.R
import io.legado.app.constant.EventBus
-import io.legado.app.constant.PreferKey
import io.legado.app.data.entities.Book
import io.legado.app.data.entities.BookChapter
import io.legado.app.data.entities.ReplaceRule
@@ -21,7 +21,7 @@ import kotlin.math.min
object BookHelp {
private const val cacheFolderName = "book_cache"
val downloadPath: String
- get() = App.INSTANCE.getPrefString(PreferKey.downloadPath)
+ get() = App.INSTANCE.getPrefString(R.string.pk_download_path)
?: App.INSTANCE.getExternalFilesDir(null)?.absolutePath
?: App.INSTANCE.cacheDir.absolutePath
@@ -300,6 +300,8 @@ object BookHelp {
1 -> c = ZhConvertBootstrap.newInstance().toSimple(c)
2 -> c = ZhConvertBootstrap.newInstance().toTraditional(c)
}
- return c.replace("\\s*\\n+\\s*".toRegex(), "\n${ReadBookConfig.bodyIndent}")
+ return c
+ .replace("\\s*\\n+\\s*".toRegex(), "\n${ReadBookConfig.bodyIndent}")
+ .replace("[\\n\\s]+$".toRegex(), "") //移除尾部空行
}
}
\ No newline at end of file
diff --git a/app/src/main/java/io/legado/app/lib/theme/ATHUtils.kt b/app/src/main/java/io/legado/app/lib/theme/ATHUtils.kt
index 73e342713..ddd6fc816 100644
--- a/app/src/main/java/io/legado/app/lib/theme/ATHUtils.kt
+++ b/app/src/main/java/io/legado/app/lib/theme/ATHUtils.kt
@@ -19,4 +19,16 @@ object ATHUtils {
a.recycle()
}
}
+
+ @JvmOverloads
+ fun resolveFloat(context: Context, @AttrRes attr: Int, fallback: Float = 0.0f): Float {
+ val a = context.theme.obtainStyledAttributes(intArrayOf(attr))
+ return try {
+ a.getFloat(0, fallback)
+ } catch (e: Exception) {
+ fallback
+ } finally {
+ a.recycle()
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/io/legado/app/lib/theme/MaterialValueHelper.kt b/app/src/main/java/io/legado/app/lib/theme/MaterialValueHelper.kt
index fab853c6b..bc898d065 100644
--- a/app/src/main/java/io/legado/app/lib/theme/MaterialValueHelper.kt
+++ b/app/src/main/java/io/legado/app/lib/theme/MaterialValueHelper.kt
@@ -107,4 +107,7 @@ val Context.isDarkTheme: Boolean
get() = ColorUtils.isColorLight(ThemeStore.primaryColor(this))
val Fragment.isDarkTheme: Boolean
- get() = requireContext().isDarkTheme
\ No newline at end of file
+ get() = requireContext().isDarkTheme
+
+val Context.elevation: Float
+ get() = ThemeStore.elevation(this)
\ No newline at end of file
diff --git a/app/src/main/java/io/legado/app/lib/theme/ThemeStore.kt b/app/src/main/java/io/legado/app/lib/theme/ThemeStore.kt
index 927fc2fb0..5b3997081 100644
--- a/app/src/main/java/io/legado/app/lib/theme/ThemeStore.kt
+++ b/app/src/main/java/io/legado/app/lib/theme/ThemeStore.kt
@@ -284,6 +284,14 @@ private constructor(private val mContext: Context) : ThemeStoreInterface {
)
}
+ @CheckResult
+ fun elevation(context: Context): Float {
+ return prefs(context).getFloat(
+ ThemeStorePrefKeys.KEY_ELEVATION,
+ ATHUtils.resolveFloat(context, android.R.attr.elevation, context.resources.getDimension(R.dimen.design_appbar_elevation))
+ )
+ }
+
@CheckResult
@ColorInt
fun bottomBackground(context: Context): Int {
diff --git a/app/src/main/java/io/legado/app/lib/theme/ThemeStorePrefKeys.kt b/app/src/main/java/io/legado/app/lib/theme/ThemeStorePrefKeys.kt
index a2ab19d60..ca8e85fc1 100644
--- a/app/src/main/java/io/legado/app/lib/theme/ThemeStorePrefKeys.kt
+++ b/app/src/main/java/io/legado/app/lib/theme/ThemeStorePrefKeys.kt
@@ -27,4 +27,6 @@ object ThemeStorePrefKeys {
const val KEY_APPLY_PRIMARYDARK_STATUSBAR = "apply_primarydark_statusbar"
const val KEY_APPLY_PRIMARY_NAVBAR = "apply_primary_navbar"
const val KEY_AUTO_GENERATE_PRIMARYDARK = "auto_generate_primarydark"
+
+ const val KEY_ELEVATION = "elevation"
}
\ No newline at end of file
diff --git a/app/src/main/java/io/legado/app/model/localBook/LocalBook.kt b/app/src/main/java/io/legado/app/model/localBook/LocalBook.kt
index 9a893b8a3..fc94613d8 100644
--- a/app/src/main/java/io/legado/app/model/localBook/LocalBook.kt
+++ b/app/src/main/java/io/legado/app/model/localBook/LocalBook.kt
@@ -4,6 +4,7 @@ import android.net.Uri
import androidx.documentfile.provider.DocumentFile
import io.legado.app.App
import io.legado.app.data.entities.Book
+import io.legado.app.help.BookHelp
import io.legado.app.utils.FileUtils
@@ -12,8 +13,17 @@ object LocalBook {
fun importFile(doc: DocumentFile) {
doc.name?.let { fileName ->
val str = fileName.substringBeforeLast(".")
- var name = str.substringBefore("作者")
- val author = str.substringAfter("作者", "")
+ val authorIndex = str.indexOf("作者")
+ var name: String
+ var author: String
+ if (authorIndex == -1) {
+ name = str
+ author = ""
+ } else {
+ name = str.substring(0, authorIndex)
+ author = str.substring(authorIndex)
+ author = BookHelp.formatAuthor(author)
+ }
val smhStart = name.indexOf("《")
val smhEnd = name.indexOf("》")
if (smhStart != -1 && smhEnd != -1) {
diff --git a/app/src/main/java/io/legado/app/service/TTSReadAloudService.kt b/app/src/main/java/io/legado/app/service/TTSReadAloudService.kt
index 6fd32219d..e54900db7 100644
--- a/app/src/main/java/io/legado/app/service/TTSReadAloudService.kt
+++ b/app/src/main/java/io/legado/app/service/TTSReadAloudService.kt
@@ -175,9 +175,7 @@ class TTSReadAloudService : BaseReadAloudService(), TextToSpeech.OnInitListener
}
override fun onError(s: String) {
- launch {
- toast(s)
- }
+ pauseReadAloud(true)
}
}
diff --git a/app/src/main/java/io/legado/app/ui/book/info/BookInfoActivity.kt b/app/src/main/java/io/legado/app/ui/book/info/BookInfoActivity.kt
index 769b47b21..42e56f206 100644
--- a/app/src/main/java/io/legado/app/ui/book/info/BookInfoActivity.kt
+++ b/app/src/main/java/io/legado/app/ui/book/info/BookInfoActivity.kt
@@ -207,7 +207,7 @@ class BookInfoActivity :
ChangeSourceDialog.show(supportFragmentManager, it.name, it.author)
}
}
- tv_toc.onClick {
+ tv_toc_view.onClick {
if (!viewModel.inBookshelf) {
viewModel.saveBook {
viewModel.saveChapterList {
@@ -218,7 +218,7 @@ class BookInfoActivity :
openChapterList()
}
}
- tv_group.onClick {
+ tv_change_group.onClick {
viewModel.bookData.value?.let {
GroupSelectDialog.show(supportFragmentManager, it.group)
}
diff --git a/app/src/main/java/io/legado/app/ui/book/read/Help.kt b/app/src/main/java/io/legado/app/ui/book/read/Help.kt
index 549b7b987..f5144977e 100644
--- a/app/src/main/java/io/legado/app/ui/book/read/Help.kt
+++ b/app/src/main/java/io/legado/app/ui/book/read/Help.kt
@@ -3,6 +3,7 @@ package io.legado.app.ui.book.read
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
+import android.content.pm.ActivityInfo
import android.os.AsyncTask
import android.os.Build
import android.view.*
@@ -62,6 +63,18 @@ object Help {
}
}
+
+ @SuppressLint("SourceLockedOrientationActivity")
+ fun setOrientation(activity: Activity) = activity.apply {
+ when (AppConfig.requestedDirection) {
+ "0" -> requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
+ "1" -> requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
+ "2" -> requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
+ "3" -> requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR
+ }
+ }
+
+
/**
* 返回NavigationBar是否存在
* 该方法需要在View完全被绘制出来之后调用,否则判断不了
diff --git a/app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt b/app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt
index 2ca4555a3..3de366ec3 100644
--- a/app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt
+++ b/app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt
@@ -3,6 +3,7 @@ package io.legado.app.ui.book.read
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Intent
+import android.content.res.Configuration
import android.net.Uri
import android.os.Bundle
import android.os.Handler
@@ -13,6 +14,7 @@ import androidx.core.view.isVisible
import androidx.core.view.size
import androidx.lifecycle.Observer
import com.jaredrummler.android.colorpicker.ColorPickerDialogListener
+import io.legado.app.BuildConfig
import io.legado.app.R
import io.legado.app.base.VMBaseActivity
import io.legado.app.constant.EventBus
@@ -88,6 +90,11 @@ class ReadBookActivity : VMBaseActivity(R.layout.activity_boo
override val pageFactory: TextPageFactory get() = page_view.pageFactory
override val headerHeight: Int get() = page_view.curPage.headerHeight
+ override fun onCreate(savedInstanceState: Bundle?) {
+ Help.setOrientation(this)
+ super.onCreate(savedInstanceState)
+ }
+
override fun onActivityCreated(savedInstanceState: Bundle?) {
Help.upLayoutInDisplayCutoutMode(window)
initView()
@@ -106,6 +113,11 @@ class ReadBookActivity : VMBaseActivity(R.layout.activity_boo
upSystemUiVisibility()
}
+ override fun onConfigurationChanged(newConfig: Configuration) {
+ super.onConfigurationChanged(newConfig)
+ ReadBook.loadContent()
+ }
+
override fun onResume() {
super.onResume()
upSystemUiVisibility()
@@ -338,7 +350,8 @@ class ReadBookActivity : VMBaseActivity(R.layout.activity_boo
@SuppressLint("ClickableViewAccessibility")
override fun onTouch(v: View, event: MotionEvent): Boolean {
when (event.action) {
- MotionEvent.ACTION_MOVE, MotionEvent.ACTION_UP -> {
+ MotionEvent.ACTION_DOWN -> textActionMenu?.dismiss()
+ MotionEvent.ACTION_MOVE -> {
when (v.id) {
R.id.cursor_left -> page_view.curPage.selectStartMove(
event.rawX + cursor_left.width,
@@ -350,6 +363,7 @@ class ReadBookActivity : VMBaseActivity(R.layout.activity_boo
)
}
}
+ MotionEvent.ACTION_UP -> showTextActionMenu()
}
return true
}
@@ -357,11 +371,12 @@ class ReadBookActivity : VMBaseActivity(R.layout.activity_boo
/**
* 更新文字选择开始位置
*/
- override fun upSelectedStart(x: Float, y: Float) {
+ override fun upSelectedStart(x: Float, y: Float, top: Float) {
cursor_left.x = x - cursor_left.width
cursor_left.y = y
cursor_left.visible(true)
- showTextActionMenu()
+ text_menu_position.x = x
+ text_menu_position.y = top
}
/**
@@ -371,7 +386,6 @@ class ReadBookActivity : VMBaseActivity(R.layout.activity_boo
cursor_right.x = x
cursor_right.y = y
cursor_right.visible(true)
- showTextActionMenu()
}
/**
@@ -386,19 +400,24 @@ class ReadBookActivity : VMBaseActivity(R.layout.activity_boo
/**
* 显示文本操作菜单
*/
- private fun showTextActionMenu() {
+ override fun showTextActionMenu() {
textActionMenu ?: let {
- textActionMenu = TextActionMenu(this, this)
- }
- val x = cursor_left.x.toInt() + cursor_left.width
- val y = if (cursor_left.y - statusBarHeight > ReadBookConfig.textSize.dp * 1.5 + 20.dp) {
- (page_view.height - cursor_left.y + ReadBookConfig.textSize.dp * 1.5).toInt()
- } else {
- (page_view.height - cursor_left.y - cursor_left.height - 40.dp).toInt()
+ textActionMenu = TextActionMenu(this, this).apply {
+ contentView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED)
+ }
}
textActionMenu?.let { popup ->
+ val popupHeight = popup.contentView.measuredHeight
+ val x = text_menu_position.x.toInt()
+ var y = text_menu_position.y.toInt() - popupHeight
+ if (y < statusBarHeight) {
+ y = (cursor_left.y + cursor_left.height).toInt()
+ }
+ if (cursor_right.y > y && cursor_right.y < y + popupHeight) {
+ y = (cursor_right.y + cursor_right.height).toInt()
+ }
if (!popup.isShowing) {
- popup.showAtLocation(cursor_left, Gravity.BOTTOM or Gravity.START, x, y)
+ popup.showAtLocation(text_menu_position, Gravity.TOP or Gravity.START, x, y)
} else {
popup.update(x, y, WRAP_CONTENT, WRAP_CONTENT)
}
@@ -663,7 +682,9 @@ class ReadBookActivity : VMBaseActivity(R.layout.activity_boo
mHandler.removeCallbacks(keepScreenRunnable)
textActionMenu?.dismiss()
page_view.onDestroy()
- SyncBookProgress.uploadBookProgress()
+ if (!BuildConfig.DEBUG) {
+ SyncBookProgress.uploadBookProgress()
+ }
}
override fun observeLiveBus() {
diff --git a/app/src/main/java/io/legado/app/ui/book/read/TextActionMenu.kt b/app/src/main/java/io/legado/app/ui/book/read/TextActionMenu.kt
index 7e90c7ad1..9d7046f6e 100644
--- a/app/src/main/java/io/legado/app/ui/book/read/TextActionMenu.kt
+++ b/app/src/main/java/io/legado/app/ui/book/read/TextActionMenu.kt
@@ -151,15 +151,16 @@ class TextActionMenu(private val context: Context, private val callBack: CallBac
*/
@RequiresApi(Build.VERSION_CODES.M)
private fun onInitializeMenu(menu: Menu) {
- // Start with a menu Item order value that is high enough
- // so that your "PROCESS_TEXT" menu items appear after the
- // standard selection menu items like Cut, Copy, Paste.
- var menuItemOrder = 100
- for (resolveInfo in getSupportedActivities()) {
- menu.add(
- Menu.NONE, Menu.NONE,
- menuItemOrder++, resolveInfo.loadLabel(context.packageManager)
- ).intent = createProcessTextIntentForResolveInfo(resolveInfo)
+ try {
+ var menuItemOrder = 100
+ for (resolveInfo in getSupportedActivities()) {
+ menu.add(
+ Menu.NONE, Menu.NONE,
+ menuItemOrder++, resolveInfo.loadLabel(context.packageManager)
+ ).intent = createProcessTextIntentForResolveInfo(resolveInfo)
+ }
+ } catch (e: Exception) {
+ context.toast("获取文字操作菜单出错:${e.localizedMessage}")
}
}
diff --git a/app/src/main/java/io/legado/app/ui/book/read/config/MoreConfigDialog.kt b/app/src/main/java/io/legado/app/ui/book/read/config/MoreConfigDialog.kt
index 6f472f270..a23725143 100644
--- a/app/src/main/java/io/legado/app/ui/book/read/config/MoreConfigDialog.kt
+++ b/app/src/main/java/io/legado/app/ui/book/read/config/MoreConfigDialog.kt
@@ -104,6 +104,11 @@ class MoreConfigDialog : DialogFragment() {
}
PreferKey.keepLight -> postEvent(key, true)
PreferKey.textSelectAble -> postEvent(key, getPrefBoolean(key))
+ getString(R.string.pk_requested_direction) -> {
+ activity?.let {
+ Help.setOrientation(it)
+ }
+ }
}
}
diff --git a/app/src/main/java/io/legado/app/ui/book/read/page/ChapterProvider.kt b/app/src/main/java/io/legado/app/ui/book/read/page/ChapterProvider.kt
index 65121906c..b7cf7182e 100644
--- a/app/src/main/java/io/legado/app/ui/book/read/page/ChapterProvider.kt
+++ b/app/src/main/java/io/legado/app/ui/book/read/page/ChapterProvider.kt
@@ -75,6 +75,7 @@ object ChapterProvider {
item.chapterIndex = bookChapter.index
item.chapterSize = chapterSize
item.title = bookChapter.title
+ item.upLinesPosition(visibleHeight)
}
return TextChapter(
bookChapter.index,
diff --git a/app/src/main/java/io/legado/app/ui/book/read/page/ContentTextView.kt b/app/src/main/java/io/legado/app/ui/book/read/page/ContentTextView.kt
index 44baa68f6..53f03462f 100644
--- a/app/src/main/java/io/legado/app/ui/book/read/page/ContentTextView.kt
+++ b/app/src/main/java/io/legado/app/ui/book/read/page/ContentTextView.kt
@@ -31,6 +31,7 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
private val selectStart = arrayOf(0, 0, 0)
private val selectEnd = arrayOf(0, 0, 0)
private var textPage: TextPage = TextPage()
+
//滚动参数
private val pageFactory: TextPageFactory get() = callBack.pageFactory
private val maxScrollOffset = 100f
@@ -210,7 +211,11 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
selectEnd[0] = 0
selectEnd[1] = lineIndex
selectEnd[2] = charIndex
- upSelectedStart(textChar.start, textLine.lineBottom + relativeOffset)
+ upSelectedStart(
+ textChar.start,
+ textLine.lineBottom + relativeOffset,
+ textLine.lineTop + relativeOffset
+ )
upSelectedEnd(textChar.end, textLine.lineBottom + relativeOffset)
select(0, lineIndex, charIndex)
return
@@ -236,7 +241,11 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
selectEnd[0] = 1
selectEnd[1] = lineIndex
selectEnd[2] = charIndex
- upSelectedStart(textChar.start, textLine.lineBottom + relativeOffset)
+ upSelectedStart(
+ textChar.start,
+ textLine.lineBottom + relativeOffset,
+ textLine.lineTop + relativeOffset
+ )
upSelectedEnd(textChar.end, textLine.lineBottom + relativeOffset)
select(1, lineIndex, charIndex)
return
@@ -259,7 +268,11 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
selectEnd[0] = 2
selectEnd[1] = lineIndex
selectEnd[2] = charIndex
- upSelectedStart(textChar.start, textLine.lineBottom + relativeOffset)
+ upSelectedStart(
+ textChar.start,
+ textLine.lineBottom + relativeOffset,
+ textLine.lineTop + relativeOffset
+ )
upSelectedEnd(textChar.end, textLine.lineBottom + relativeOffset)
select(2, lineIndex, charIndex)
return
@@ -287,7 +300,11 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
selectStart[0] = 0
selectStart[1] = lineIndex
selectStart[2] = charIndex
- upSelectedStart(textChar.start, textLine.lineBottom + relativeOffset)
+ upSelectedStart(
+ textChar.start,
+ textLine.lineBottom + relativeOffset,
+ textLine.lineTop + relativeOffset
+ )
upSelectChars()
}
return
@@ -311,7 +328,11 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
selectStart[0] = 1
selectStart[1] = lineIndex
selectStart[2] = charIndex
- upSelectedStart(textChar.start, textLine.lineBottom + relativeOffset)
+ upSelectedStart(
+ textChar.start,
+ textLine.lineBottom + relativeOffset,
+ textLine.lineTop + relativeOffset
+ )
upSelectChars()
}
return
@@ -333,7 +354,11 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
selectStart[0] = 2
selectStart[1] = lineIndex
selectStart[2] = charIndex
- upSelectedStart(textChar.start, textLine.lineBottom + relativeOffset)
+ upSelectedStart(
+ textChar.start,
+ textLine.lineBottom + relativeOffset,
+ textLine.lineTop + relativeOffset
+ )
upSelectChars()
}
return
@@ -427,7 +452,11 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
selectStart[2] = charIndex
val textLine = relativePage(relativePage).textLines[lineIndex]
val textChar = textLine.textChars[charIndex]
- upSelectedStart(textChar.start, textLine.lineBottom + relativeOffset(relativePage))
+ upSelectedStart(
+ textChar.start,
+ textLine.lineBottom + relativeOffset(relativePage),
+ textLine.lineTop
+ )
upSelectChars()
}
@@ -475,12 +504,12 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
invalidate()
}
- private fun upSelectedStart(x: Float, y: Float) {
- callBack.upSelectedStart(x, y + callBack.headerHeight)
+ private fun upSelectedStart(x: Float, y: Float, top: Float) = callBack.apply {
+ upSelectedStart(x, y + headerHeight, top + headerHeight)
}
- private fun upSelectedEnd(x: Float, y: Float) {
- callBack.upSelectedEnd(x, y + callBack.headerHeight)
+ private fun upSelectedEnd(x: Float, y: Float) = callBack.apply {
+ upSelectedEnd(x, y + headerHeight)
}
fun cancelSelect() {
@@ -580,7 +609,7 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
}
interface CallBack {
- fun upSelectedStart(x: Float, y: Float)
+ fun upSelectedStart(x: Float, y: Float, top: Float)
fun upSelectedEnd(x: Float, y: Float)
fun onCancelSelect()
val headerHeight: Int
diff --git a/app/src/main/java/io/legado/app/ui/book/read/page/ContentView.kt b/app/src/main/java/io/legado/app/ui/book/read/page/ContentView.kt
index a9a752303..4e820008e 100644
--- a/app/src/main/java/io/legado/app/ui/book/read/page/ContentView.kt
+++ b/app/src/main/java/io/legado/app/ui/book/read/page/ContentView.kt
@@ -109,7 +109,6 @@ class ContentView(context: Context) : FrameLayout(context) {
fun setContent(textPage: TextPage) {
setProgress(textPage)
- content_text_view.resetPageOffset()
content_text_view.setContent(textPage)
}
diff --git a/app/src/main/java/io/legado/app/ui/book/read/page/PageView.kt b/app/src/main/java/io/legado/app/ui/book/read/page/PageView.kt
index dbde99c7e..1b7b71b07 100644
--- a/app/src/main/java/io/legado/app/ui/book/read/page/PageView.kt
+++ b/app/src/main/java/io/legado/app/ui/book/read/page/PageView.kt
@@ -16,25 +16,20 @@ class PageView(context: Context, attrs: AttributeSet) :
FrameLayout(context, attrs),
DataSource {
- var callBack: CallBack
- var pageFactory: TextPageFactory
+ val callBack: CallBack get() = activity as CallBack
+ var pageFactory: TextPageFactory = TextPageFactory(this)
var pageDelegate: PageDelegate? = null
- var prevPage: ContentView
- var curPage: ContentView
- var nextPage: ContentView
+ var prevPage: ContentView = ContentView(context)
+ var curPage: ContentView = ContentView(context)
+ var nextPage: ContentView = ContentView(context)
init {
- callBack = activity as CallBack
- nextPage = ContentView(context)
addView(nextPage)
- curPage = ContentView(context)
addView(curPage)
- prevPage = ContentView(context)
addView(prevPage)
upBg()
setWillNotDraw(false)
- pageFactory = TextPageFactory(this)
upPageAnim()
}
@@ -170,5 +165,6 @@ class PageView(context: Context, attrs: AttributeSet) :
val isInitFinish: Boolean
fun clickCenter()
fun screenOffTimerStart()
+ fun showTextActionMenu()
}
}
diff --git a/app/src/main/java/io/legado/app/ui/book/read/page/delegate/PageDelegate.kt b/app/src/main/java/io/legado/app/ui/book/read/page/delegate/PageDelegate.kt
index 4173ffb09..d83f60edb 100644
--- a/app/src/main/java/io/legado/app/ui/book/read/page/delegate/PageDelegate.kt
+++ b/app/src/main/java/io/legado/app/ui/book/read/page/delegate/PageDelegate.kt
@@ -200,11 +200,16 @@ abstract class PageDelegate(protected val pageView: PageView) :
//GestureDetector.onFling小幅移动不会触发,所以要自己判断
when (event.action) {
MotionEvent.ACTION_UP,
- MotionEvent.ACTION_CANCEL -> if (isMoved) {
- if (selectedOnDown) {
- selectedOnDown = false
+ MotionEvent.ACTION_CANCEL -> {
+ if (isTextSelected) {
+ pageView.callBack.showTextActionMenu()
+ }
+ if (isMoved) {
+ if (selectedOnDown) {
+ selectedOnDown = false
+ }
+ if (!noNext) onAnimStart()
}
- if (!noNext) onAnimStart()
}
}
}
diff --git a/app/src/main/java/io/legado/app/ui/book/read/page/entities/TextPage.kt b/app/src/main/java/io/legado/app/ui/book/read/page/entities/TextPage.kt
index bfb8e822c..6c4e27073 100644
--- a/app/src/main/java/io/legado/app/ui/book/read/page/entities/TextPage.kt
+++ b/app/src/main/java/io/legado/app/ui/book/read/page/entities/TextPage.kt
@@ -18,6 +18,21 @@ data class TextPage(
var height: Float = 0f
) {
+ fun upLinesPosition(visibleHeight: Int) {
+ if (textLines.size <= 1) return
+ if (visibleHeight - height > with(textLines.last()) { lineBottom - lineTop }) return
+ val surplus = (visibleHeight - textLines.last().lineBottom)
+ if (surplus == 0f) return
+ height += surplus
+ val tj = surplus / (textLines.size - 1)
+ for (i in 1 until textLines.size) {
+ val line = textLines[i]
+ line.lineTop = line.lineTop + tj * i
+ line.lineBase = line.lineBase + tj * i
+ line.lineBottom = line.lineBottom + tj * i
+ }
+ }
+
@Suppress("DEPRECATION")
fun format(): TextPage {
if (textLines.isEmpty() && ChapterProvider.visibleWidth > 0) {
@@ -101,4 +116,5 @@ data class TextPage(
}
return percent
}
+
}
diff --git a/app/src/main/java/io/legado/app/ui/config/OtherConfigFragment.kt b/app/src/main/java/io/legado/app/ui/config/OtherConfigFragment.kt
index 58caa351d..a010428fd 100644
--- a/app/src/main/java/io/legado/app/ui/config/OtherConfigFragment.kt
+++ b/app/src/main/java/io/legado/app/ui/config/OtherConfigFragment.kt
@@ -40,7 +40,7 @@ class OtherConfigFragment : PreferenceFragmentCompat(),
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
putPrefBoolean(PreferKey.processText, isProcessTextEnabled())
addPreferencesFromResource(R.xml.pref_config_other)
- upPreferenceSummary(PreferKey.downloadPath, BookHelp.downloadPath)
+ upPreferenceSummary(getString(R.string.pk_download_path), BookHelp.downloadPath)
upPreferenceSummary(PreferKey.threadCount, AppConfig.threadCount.toString())
upPreferenceSummary(PreferKey.webPort, webPort.toString())
}
@@ -74,7 +74,7 @@ class OtherConfigFragment : PreferenceFragmentCompat(),
.show {
putPrefInt(PreferKey.webPort, it)
}
- PreferKey.downloadPath -> selectDownloadPath()
+ getString(R.string.pk_download_path) -> selectDownloadPath()
PreferKey.cleanCache -> {
BookHelp.clearCache()
toast(R.string.clear_cache_success)
@@ -85,7 +85,7 @@ class OtherConfigFragment : PreferenceFragmentCompat(),
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
when (key) {
- PreferKey.downloadPath -> {
+ getString(R.string.pk_download_path) -> {
upPreferenceSummary(key, BookHelp.downloadPath)
}
PreferKey.threadCount -> upPreferenceSummary(
@@ -141,13 +141,17 @@ class OtherConfigFragment : PreferenceFragmentCompat(),
private fun selectDownloadPath() {
FilePicker.selectFolder(this, requestCodeDownloadPath) {
- removePref(PreferKey.downloadPath)
+ removePref(getString(R.string.pk_download_path))
}
}
+ private fun putDownloadPath(path: String) {
+ putPrefString(getString(R.string.pk_download_path), path)
+ }
+
override fun onFilePicked(requestCode: Int, currentPath: String) {
if (requestCode == requestCodeDownloadPath) {
- putPrefString(PreferKey.downloadPath, currentPath)
+ putDownloadPath(currentPath)
}
}
@@ -160,7 +164,7 @@ class OtherConfigFragment : PreferenceFragmentCompat(),
uri,
Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
)
- putPrefString(PreferKey.downloadPath, uri.toString())
+ putDownloadPath(uri.toString())
}
}
}
diff --git a/app/src/main/java/io/legado/app/ui/config/ThemeConfigFragment.kt b/app/src/main/java/io/legado/app/ui/config/ThemeConfigFragment.kt
index 99d7d1e54..da2672841 100644
--- a/app/src/main/java/io/legado/app/ui/config/ThemeConfigFragment.kt
+++ b/app/src/main/java/io/legado/app/ui/config/ThemeConfigFragment.kt
@@ -1,6 +1,7 @@
package io.legado.app.ui.config
import android.content.SharedPreferences
+import android.os.Build
import android.os.Bundle
import android.view.View
import androidx.preference.Preference
@@ -16,6 +17,8 @@ import io.legado.app.lib.dialogs.noButton
import io.legado.app.lib.dialogs.yesButton
import io.legado.app.lib.theme.ATH
import io.legado.app.lib.theme.ColorUtils
+import io.legado.app.ui.widget.number.NumberPickerDialog
+import io.legado.app.ui.widget.prefs.IconListPreference
import io.legado.app.utils.*
@@ -25,6 +28,12 @@ class ThemeConfigFragment : PreferenceFragmentCompat(), SharedPreferences.OnShar
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
addPreferencesFromResource(R.xml.pref_config_theme)
+ if (Build.VERSION.SDK_INT < 26) {
+ findPreference(PreferKey.launcherIcon)?.let {
+ preferenceScreen.removePreference(it)
+ }
+ }
+ upPreferenceSummary("barElevation", AppConfig.elevation.toString())
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@@ -145,6 +154,19 @@ class ThemeConfigFragment : PreferenceFragmentCompat(), SharedPreferences.OnShar
recreateActivities()
}
}.show().applyTint()
+ "barElevation" -> NumberPickerDialog(requireContext())
+ .setTitle(getString(R.string.bar_elevation))
+ .setMaxValue(32)
+ .setMinValue(0)
+ .setValue(AppConfig.elevation)
+ .setCustomButton((R.string.btn_default_s)) {
+ AppConfig.elevation = App.INSTANCE.resources.getDimension(R.dimen.design_appbar_elevation).toInt()
+ recreateActivities()
+ }
+ .show {
+ AppConfig.elevation = it
+ recreateActivities()
+ }
}
return super.onPreferenceTreeClick(preference)
}
@@ -180,4 +202,10 @@ class ThemeConfigFragment : PreferenceFragmentCompat(), SharedPreferences.OnShar
postEvent(EventBus.RECREATE, "")
}
+ private fun upPreferenceSummary(preferenceKey: String, value: String?) {
+ val preference = findPreference(preferenceKey) ?: return
+ when (preferenceKey) {
+ "barElevation" -> preference.summary = getString(R.string.bar_elevation_s, value)
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/io/legado/app/ui/welcome/WelcomeActivity.kt b/app/src/main/java/io/legado/app/ui/welcome/WelcomeActivity.kt
index 5c84aa679..46e1e446e 100644
--- a/app/src/main/java/io/legado/app/ui/welcome/WelcomeActivity.kt
+++ b/app/src/main/java/io/legado/app/ui/welcome/WelcomeActivity.kt
@@ -48,7 +48,7 @@ open class WelcomeActivity : BaseActivity(R.layout.activity_welcome) {
private fun startMainActivity() {
startActivity()
- if (getPrefBoolean(getString(R.string.pk_default_read))) {
+ if (getPrefBoolean(R.string.pk_default_read)) {
startActivity()
}
finish()
diff --git a/app/src/main/java/io/legado/app/ui/widget/BatteryView.kt b/app/src/main/java/io/legado/app/ui/widget/BatteryView.kt
index 60e781c93..f11db64e8 100644
--- a/app/src/main/java/io/legado/app/ui/widget/BatteryView.kt
+++ b/app/src/main/java/io/legado/app/ui/widget/BatteryView.kt
@@ -1,67 +1,57 @@
package io.legado.app.ui.widget
+import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.Rect
-import android.graphics.Typeface
-import android.text.StaticLayout
-import android.text.TextPaint
import android.util.AttributeSet
-import android.view.View
import androidx.annotation.ColorInt
-import io.legado.app.R
+import androidx.appcompat.widget.AppCompatTextView
import io.legado.app.utils.dp
-import io.legado.app.utils.getCompatColor
-import io.legado.app.utils.sp
-class BatteryView(context: Context, attrs: AttributeSet?) : View(context, attrs) {
- private var battery = 100
- private val textPaint = TextPaint()
- private var batteryHeight: Int = 0
- private var batteryWidth: Int = 0
+class BatteryView(context: Context, attrs: AttributeSet?) : AppCompatTextView(context, attrs) {
+ private val batteryPaint = Paint()
private val outFrame = Rect()
private val polar = Rect()
init {
- textPaint.textSize = 10.sp.toFloat()
- textPaint.strokeWidth = 1.dp.toFloat()
- textPaint.isAntiAlias = true
- textPaint.textAlign = Paint.Align.CENTER
- textPaint.color = context.getCompatColor(R.color.tv_text_default)
- textPaint.typeface = Typeface.createFromAsset(context.assets, "number.ttf")
- batteryHeight = with(textPaint.fontMetrics) { descent - ascent + leading }.toInt()
- batteryWidth = StaticLayout.getDesiredWidth("100", textPaint).toInt() + 10.dp
- outFrame.set(1.dp, 1.dp, batteryWidth - 3.dp, batteryHeight - 1.dp)
- polar.set(outFrame.right, batteryHeight / 3, batteryWidth, batteryHeight * 2 / 3)
- }
-
- override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
- super.onMeasure(
- MeasureSpec.makeMeasureSpec(batteryWidth, MeasureSpec.EXACTLY),
- MeasureSpec.makeMeasureSpec(batteryHeight, MeasureSpec.EXACTLY)
- )
+ setPadding(4.dp, 0, 6.dp, 0)
+ batteryPaint.strokeWidth = 1.dp.toFloat()
+ batteryPaint.isAntiAlias = true
+ batteryPaint.color = paint.color
}
fun setColor(@ColorInt color: Int) {
- textPaint.color = color
+ setTextColor(color)
+ batteryPaint.color = color
invalidate()
}
+ @SuppressLint("SetTextI18n")
fun setBattery(battery: Int) {
- this.battery = battery
- invalidate()
+ text = "$battery"
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
- textPaint.style = Paint.Style.STROKE
- canvas.drawRect(outFrame, textPaint)
- textPaint.style = Paint.Style.FILL
- canvas.drawRect(polar, textPaint)
- val text = battery.toString()
- val baseHeight = batteryHeight - textPaint.fontMetrics.descent
- canvas.drawText(text, outFrame.right / 2.toFloat(), baseHeight, textPaint)
+ outFrame.set(
+ 1.dp,
+ layout.getLineTop(0) + 2.dp,
+ width - 3.dp,
+ layout.getLineBottom(0) - 2.dp
+ )
+ val dj = (outFrame.bottom - outFrame.top) / 3
+ polar.set(
+ outFrame.right,
+ outFrame.top + dj,
+ width - 1.dp,
+ outFrame.bottom - dj
+ )
+ batteryPaint.style = Paint.Style.STROKE
+ canvas.drawRect(outFrame, batteryPaint)
+ batteryPaint.style = Paint.Style.FILL
+ canvas.drawRect(polar, batteryPaint)
}
}
\ No newline at end of file
diff --git a/app/src/main/java/io/legado/app/ui/widget/TitleBar.kt b/app/src/main/java/io/legado/app/ui/widget/TitleBar.kt
index d19c8929f..663bb55a8 100644
--- a/app/src/main/java/io/legado/app/ui/widget/TitleBar.kt
+++ b/app/src/main/java/io/legado/app/ui/widget/TitleBar.kt
@@ -10,6 +10,8 @@ import androidx.annotation.StyleRes
import androidx.appcompat.widget.Toolbar
import com.google.android.material.appbar.AppBarLayout
import io.legado.app.R
+import io.legado.app.help.AppConfig
+import io.legado.app.lib.theme.elevation
import io.legado.app.lib.theme.primaryColor
import io.legado.app.utils.activity
import io.legado.app.utils.navigationBarHeight
@@ -141,6 +143,13 @@ class TitleBar(context: Context, attrs: AttributeSet?) : AppBarLayout(context, a
backgroundColor = context.primaryColor
+ stateListAnimator = null
+ elevation = if (AppConfig.elevation < 0) {
+ context.elevation
+ } else {
+ AppConfig.elevation.toFloat()
+ }
+
a.recycle()
}
diff --git a/app/src/main/java/io/legado/app/ui/widget/number/NumberPickerDialog.kt b/app/src/main/java/io/legado/app/ui/widget/number/NumberPickerDialog.kt
index 17fe9ab53..3b4c8f5db 100644
--- a/app/src/main/java/io/legado/app/ui/widget/number/NumberPickerDialog.kt
+++ b/app/src/main/java/io/legado/app/ui/widget/number/NumberPickerDialog.kt
@@ -40,6 +40,17 @@ class NumberPickerDialog(context: Context) {
return this
}
+ fun setCustomButton(textId: Int, listener: (() -> Unit)?): NumberPickerDialog {
+ builder.setNeutralButton(textId) { _, _ ->
+ numberPicker?.let {
+ it.clearFocus()
+ it.hideSoftInput()
+ listener?.invoke()
+ }
+ }
+ return this;
+ }
+
fun show(callBack: ((value: Int) -> Unit)?) {
builder.setPositiveButton(R.string.ok) { _, _ ->
numberPicker?.let {
diff --git a/app/src/main/java/io/legado/app/utils/ContextExtensions.kt b/app/src/main/java/io/legado/app/utils/ContextExtensions.kt
index 3436c9d94..bc3f6f9fa 100644
--- a/app/src/main/java/io/legado/app/utils/ContextExtensions.kt
+++ b/app/src/main/java/io/legado/app/utils/ContextExtensions.kt
@@ -12,6 +12,7 @@ import android.os.BatteryManager
import android.provider.Settings
import androidx.annotation.ColorRes
import androidx.annotation.DrawableRes
+import androidx.annotation.StringRes
import androidx.core.content.ContextCompat
import androidx.core.content.FileProvider
import androidx.core.content.edit
@@ -28,6 +29,9 @@ import java.io.FileOutputStream
fun Context.getPrefBoolean(key: String, defValue: Boolean = false) =
defaultSharedPreferences.getBoolean(key, defValue)
+fun Context.getPrefBoolean(@StringRes keyId: Int, defValue: Boolean = false) =
+ defaultSharedPreferences.getBoolean(getString(keyId), defValue)
+
fun Context.putPrefBoolean(key: String, value: Boolean = false) =
defaultSharedPreferences.edit { putBoolean(key, value) }
@@ -46,6 +50,9 @@ fun Context.putPrefLong(key: String, value: Long) =
fun Context.getPrefString(key: String, defValue: String? = null) =
defaultSharedPreferences.getString(key, defValue)
+fun Context.getPrefString(@StringRes keyId: Int, defValue: String? = null) =
+ defaultSharedPreferences.getString(getString(keyId), defValue)
+
fun Context.putPrefString(key: String, value: String) =
defaultSharedPreferences.edit { putString(key, value) }
diff --git a/app/src/main/res/layout-land/activity_book_info.xml b/app/src/main/res/layout-land/activity_book_info.xml
new file mode 100644
index 000000000..27e0bec0d
--- /dev/null
+++ b/app/src/main/res/layout-land/activity_book_info.xml
@@ -0,0 +1,419 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_book_info.xml b/app/src/main/res/layout/activity_book_info.xml
index 8e58e34cb..568a4e60a 100644
--- a/app/src/main/res/layout/activity_book_info.xml
+++ b/app/src/main/res/layout/activity_book_info.xml
@@ -64,40 +64,6 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
@@ -241,6 +241,94 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+ android:layout_height="8dp"
+ android:background="@color/background">
+
+
+ android:textSize="10sp"
+ tools:ignore="RtlHardcoded,RtlSymmetry,SmallSp" />
diff --git a/app/src/main/res/values/array_values.xml b/app/src/main/res/values/array_values.xml
index 2aa918837..c517c46ce 100644
--- a/app/src/main/res/values/array_values.xml
+++ b/app/src/main/res/values/array_values.xml
@@ -38,5 +38,11 @@
- 9
+
+ - 0
+ - 1
+ - 2
+ - 3
+
\ No newline at end of file
diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml
index 104febad6..a53546e7f 100644
--- a/app/src/main/res/values/arrays.xml
+++ b/app/src/main/res/values/arrays.xml
@@ -67,7 +67,7 @@
- @string/app_folder_picker
-
+
- @string/screen_unspecified
- @string/screen_portrait
- @string/screen_landscape
diff --git a/app/src/main/res/values/pref_key_value.xml b/app/src/main/res/values/pref_key_value.xml
index 7bcded4da..0c535ad67 100644
--- a/app/src/main/res/values/pref_key_value.xml
+++ b/app/src/main/res/values/pref_key_value.xml
@@ -1,7 +1,7 @@
auto_refresh
- list_screen_direction
+ list_screen_direction
full_screen
threads_num
user_agent
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 2af658b79..84e6e6bb2 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -160,7 +160,7 @@
添加书籍网址
背景
作者
- 作者:%s
+ 作者: %s
朗读停止
清除缓存
成功清理缓存
@@ -641,4 +641,10 @@
加入分组
保存图片
没有默认路径
+ 设置分组
+ 查看目录
+ 导航栏阴影
+ 当前阴影大小(elevation): %s
+ 默认
+
diff --git a/app/src/main/res/xml/pref_config_read.xml b/app/src/main/res/xml/pref_config_read.xml
index a19a8ba4c..ef360b43c 100644
--- a/app/src/main/res/xml/pref_config_read.xml
+++ b/app/src/main/res/xml/pref_config_read.xml
@@ -2,6 +2,14 @@
+
+
+
+