优化
This commit is contained in:
@@ -2,7 +2,11 @@ package io.legado.app.model
|
|||||||
|
|
||||||
import io.legado.app.constant.AppLog
|
import io.legado.app.constant.AppLog
|
||||||
import io.legado.app.data.appDb
|
import io.legado.app.data.appDb
|
||||||
import io.legado.app.data.entities.*
|
import io.legado.app.data.entities.Book
|
||||||
|
import io.legado.app.data.entities.BookChapter
|
||||||
|
import io.legado.app.data.entities.BookProgress
|
||||||
|
import io.legado.app.data.entities.BookSource
|
||||||
|
import io.legado.app.data.entities.ReadRecord
|
||||||
import io.legado.app.help.AppWebDav
|
import io.legado.app.help.AppWebDav
|
||||||
import io.legado.app.help.book.BookHelp
|
import io.legado.app.help.book.BookHelp
|
||||||
import io.legado.app.help.book.ContentProcessor
|
import io.legado.app.help.book.ContentProcessor
|
||||||
@@ -88,7 +92,7 @@ object ReadBook : CoroutineScope by MainScope() {
|
|||||||
upWebBook(book)
|
upWebBook(book)
|
||||||
lastBookPress = null
|
lastBookPress = null
|
||||||
webBookProgress = null
|
webBookProgress = null
|
||||||
TextFile.txtBuffer = null
|
TextFile.clear()
|
||||||
synchronized(this) {
|
synchronized(this) {
|
||||||
loadingChapters.clear()
|
loadingChapters.clear()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ object LocalBook {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(Exception::class)
|
@Throws(TocEmptyException::class)
|
||||||
fun getChapterList(book: Book): ArrayList<BookChapter> {
|
fun getChapterList(book: Book): ArrayList<BookChapter> {
|
||||||
val chapters = when {
|
val chapters = when {
|
||||||
book.isEpub -> {
|
book.isEpub -> {
|
||||||
|
|||||||
@@ -16,56 +16,37 @@ import java.util.regex.Matcher
|
|||||||
import java.util.regex.Pattern
|
import java.util.regex.Pattern
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
|
|
||||||
class TextFile(private val book: Book) {
|
class TextFile(private var book: Book) {
|
||||||
|
|
||||||
|
@Suppress("ConstPropertyName")
|
||||||
companion object {
|
companion object {
|
||||||
private val padRegex = "^[\\n\\s]+".toRegex()
|
private val padRegex = "^[\\n\\s]+".toRegex()
|
||||||
private const val bufferSize = 8 * 1024 * 1024
|
private const val txtBufferSize = 8 * 1024 * 1024
|
||||||
private var bufferStart = -1
|
private var textFile: TextFile? = null
|
||||||
private var bufferEnd = -1
|
|
||||||
var txtBuffer: ByteArray? = null
|
@Synchronized
|
||||||
var bookUrl = ""
|
private fun getTextFile(book: Book): TextFile {
|
||||||
|
if (textFile == null || textFile?.book?.bookUrl != book.bookUrl) {
|
||||||
|
textFile = TextFile(book)
|
||||||
|
return textFile!!
|
||||||
|
}
|
||||||
|
textFile?.book = book
|
||||||
|
return textFile!!
|
||||||
|
}
|
||||||
|
|
||||||
@Throws(FileNotFoundException::class)
|
@Throws(FileNotFoundException::class)
|
||||||
fun getChapterList(book: Book): ArrayList<BookChapter> {
|
fun getChapterList(book: Book): ArrayList<BookChapter> {
|
||||||
return TextFile(book).getChapterList()
|
return getTextFile(book).getChapterList()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
@Throws(FileNotFoundException::class)
|
@Throws(FileNotFoundException::class)
|
||||||
fun getContent(book: Book, bookChapter: BookChapter): String {
|
fun getContent(book: Book, bookChapter: BookChapter): String {
|
||||||
if (txtBuffer == null || bookUrl != book.bookUrl || bookChapter.start!! > bufferEnd || bookChapter.end!! < bufferStart) {
|
return getTextFile(book).getContent(bookChapter)
|
||||||
bookUrl = book.bookUrl
|
}
|
||||||
LocalBook.getBookInputStream(book).use { bis ->
|
|
||||||
bufferStart = bufferSize * (bookChapter.start!! / bufferSize).toInt()
|
|
||||||
txtBuffer = ByteArray(min(bufferSize, bis.available() - bufferStart))
|
|
||||||
bufferEnd = bufferStart + txtBuffer!!.size
|
|
||||||
bis.skip(bufferStart.toLong())
|
|
||||||
bis.read(txtBuffer)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val count = (bookChapter.end!! - bookChapter.start!!).toInt()
|
fun clear() {
|
||||||
val buffer = ByteArray(count)
|
textFile = null
|
||||||
|
|
||||||
if (bookChapter.start!! < bufferEnd && bookChapter.end!! > bufferEnd || bookChapter.start!! < bufferStart && bookChapter.end!! > bufferStart) {
|
|
||||||
/** 章节内容在缓冲区交界处 */
|
|
||||||
LocalBook.getBookInputStream(book).use { bis ->
|
|
||||||
bis.skip(bookChapter.start!!)
|
|
||||||
bis.read(buffer)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/** 章节内容在缓冲区内 */
|
|
||||||
txtBuffer!!.copyInto(
|
|
||||||
buffer,
|
|
||||||
0,
|
|
||||||
(bookChapter.start!! - bufferStart).toInt(),
|
|
||||||
(bookChapter.end!! - bufferStart).toInt()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return String(buffer, book.fileCharset()).substringAfter(bookChapter.title)
|
|
||||||
.replace(padRegex, " ")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -83,10 +64,14 @@ class TextFile(private val book: Book) {
|
|||||||
|
|
||||||
private var charset: Charset = book.fileCharset()
|
private var charset: Charset = book.fileCharset()
|
||||||
|
|
||||||
|
private var txtBuffer: ByteArray? = null
|
||||||
|
private var bufferStart = -1L
|
||||||
|
private var bufferEnd = -1L
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取目录
|
* 获取目录
|
||||||
*/
|
*/
|
||||||
@Throws(FileNotFoundException::class)
|
@Throws(FileNotFoundException::class, SecurityException::class, EmptyFileException::class)
|
||||||
fun getChapterList(): ArrayList<BookChapter> {
|
fun getChapterList(): ArrayList<BookChapter> {
|
||||||
if (book.charset == null || book.tocUrl.isBlank()) {
|
if (book.charset == null || book.tocUrl.isBlank()) {
|
||||||
LocalBook.getBookInputStream(book).use { bis ->
|
LocalBook.getBookInputStream(book).use { bis ->
|
||||||
@@ -112,6 +97,43 @@ class TextFile(private val book: Book) {
|
|||||||
return toc
|
return toc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getContent(chapter: BookChapter): String {
|
||||||
|
val start = chapter.start!!
|
||||||
|
val end = chapter.end!!
|
||||||
|
if (txtBuffer == null || start > bufferEnd || end < bufferStart) {
|
||||||
|
LocalBook.getBookInputStream(book).use { bis ->
|
||||||
|
bufferStart = txtBufferSize * (start / txtBufferSize)
|
||||||
|
txtBuffer = ByteArray(min(txtBufferSize, bis.available() - bufferStart.toInt()))
|
||||||
|
bufferEnd = bufferStart + txtBuffer!!.size
|
||||||
|
bis.skip(bufferStart)
|
||||||
|
bis.read(txtBuffer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val count = (end - start).toInt()
|
||||||
|
val buffer = ByteArray(count)
|
||||||
|
|
||||||
|
if (bufferEnd in start..end || bufferStart in start..end) {
|
||||||
|
/** 章节内容在缓冲区交界处 */
|
||||||
|
LocalBook.getBookInputStream(book).use { bis ->
|
||||||
|
bis.skip(start)
|
||||||
|
bis.read(buffer)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/** 章节内容在缓冲区内 */
|
||||||
|
txtBuffer!!.copyInto(
|
||||||
|
buffer,
|
||||||
|
0,
|
||||||
|
(start - bufferStart).toInt(),
|
||||||
|
(end - bufferStart).toInt()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return String(buffer, charset)
|
||||||
|
.substringAfter(chapter.title)
|
||||||
|
.replace(padRegex, " ")
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 按规则解析目录
|
* 按规则解析目录
|
||||||
*/
|
*/
|
||||||
@@ -162,7 +184,7 @@ class TextFile(private val book: Book) {
|
|||||||
val chapterStart = matcher.start()
|
val chapterStart = matcher.start()
|
||||||
//获取章节内容
|
//获取章节内容
|
||||||
val chapterContent = blockContent.substring(seekPos, chapterStart)
|
val chapterContent = blockContent.substring(seekPos, chapterStart)
|
||||||
val chapterLength = chapterContent.toByteArray(charset).size
|
val chapterLength = chapterContent.toByteArray(charset).size.toLong()
|
||||||
val lastStart = toc.lastOrNull()?.start ?: curOffset
|
val lastStart = toc.lastOrNull()?.start ?: curOffset
|
||||||
if (book.getSplitLongChapter() && curOffset + chapterLength - lastStart > maxLengthWithToc) {
|
if (book.getSplitLongChapter() && curOffset + chapterLength - lastStart > maxLengthWithToc) {
|
||||||
toc.lastOrNull()?.let {
|
toc.lastOrNull()?.let {
|
||||||
@@ -186,7 +208,7 @@ class TextFile(private val book: Book) {
|
|||||||
curChapter.start = curOffset + chapterLength
|
curChapter.start = curOffset + chapterLength
|
||||||
toc.add(curChapter)
|
toc.add(curChapter)
|
||||||
} else if (seekPos == 0 && chapterStart != 0) {
|
} else if (seekPos == 0 && chapterStart != 0) {
|
||||||
/*
|
/**
|
||||||
* 如果 seekPos == 0 && chapterStart != 0 表示当前block处前面有一段内容
|
* 如果 seekPos == 0 && chapterStart != 0 表示当前block处前面有一段内容
|
||||||
* 第一种情况一定是序章 第二种情况是上一个章节的内容
|
* 第一种情况一定是序章 第二种情况是上一个章节的内容
|
||||||
*/
|
*/
|
||||||
@@ -196,13 +218,18 @@ class TextFile(private val book: Book) {
|
|||||||
val qyChapter = BookChapter()
|
val qyChapter = BookChapter()
|
||||||
qyChapter.title = "前言"
|
qyChapter.title = "前言"
|
||||||
qyChapter.start = curOffset
|
qyChapter.start = curOffset
|
||||||
qyChapter.end = curOffset + chapterLength.toLong()
|
qyChapter.end = curOffset + chapterLength
|
||||||
toc.add(qyChapter)
|
toc.add(qyChapter)
|
||||||
|
book.intro = if (chapterContent.length <= 500) {
|
||||||
|
chapterContent
|
||||||
|
} else {
|
||||||
|
chapterContent.substring(0, 500)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//创建当前章节
|
//创建当前章节
|
||||||
val curChapter = BookChapter()
|
val curChapter = BookChapter()
|
||||||
curChapter.title = matcher.group()
|
curChapter.title = matcher.group()
|
||||||
curChapter.start = curOffset + chapterLength.toLong()
|
curChapter.start = curOffset + chapterLength
|
||||||
toc.add(curChapter)
|
toc.add(curChapter)
|
||||||
} else { //否则就block分割之后,上一个章节的剩余内容
|
} else { //否则就block分割之后,上一个章节的剩余内容
|
||||||
//获取上一章节
|
//获取上一章节
|
||||||
@@ -210,7 +237,7 @@ class TextFile(private val book: Book) {
|
|||||||
lastChapter.isVolume =
|
lastChapter.isVolume =
|
||||||
chapterContent.substringAfter(lastChapter.title).isBlank()
|
chapterContent.substringAfter(lastChapter.title).isBlank()
|
||||||
//将当前段落添加上一章去
|
//将当前段落添加上一章去
|
||||||
lastChapter.end = lastChapter.end!! + chapterLength.toLong()
|
lastChapter.end = lastChapter.end!! + chapterLength
|
||||||
//创建当前章节
|
//创建当前章节
|
||||||
val curChapter = BookChapter()
|
val curChapter = BookChapter()
|
||||||
curChapter.title = matcher.group()
|
curChapter.title = matcher.group()
|
||||||
@@ -224,7 +251,7 @@ class TextFile(private val book: Book) {
|
|||||||
lastChapter.isVolume =
|
lastChapter.isVolume =
|
||||||
chapterContent.substringAfter(lastChapter.title).isBlank()
|
chapterContent.substringAfter(lastChapter.title).isBlank()
|
||||||
lastChapter.end =
|
lastChapter.end =
|
||||||
lastChapter.start!! + chapterContent.toByteArray(charset).size.toLong()
|
lastChapter.start!! + chapterLength
|
||||||
//创建当前章节
|
//创建当前章节
|
||||||
val curChapter = BookChapter()
|
val curChapter = BookChapter()
|
||||||
curChapter.title = matcher.group()
|
curChapter.title = matcher.group()
|
||||||
|
|||||||
@@ -1,45 +1,27 @@
|
|||||||
package io.legado.app.ui.book.explore
|
package io.legado.app.ui.book.explore
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.Menu
|
|
||||||
import android.view.MenuItem
|
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import io.legado.app.R
|
import io.legado.app.R
|
||||||
import io.legado.app.base.VMBaseActivity
|
import io.legado.app.base.VMBaseActivity
|
||||||
import io.legado.app.constant.AppLog
|
|
||||||
import io.legado.app.data.appDb
|
|
||||||
import io.legado.app.data.entities.Book
|
import io.legado.app.data.entities.Book
|
||||||
import io.legado.app.data.entities.SearchBook
|
import io.legado.app.data.entities.SearchBook
|
||||||
import io.legado.app.databinding.ActivityExploreShowBinding
|
import io.legado.app.databinding.ActivityExploreShowBinding
|
||||||
import io.legado.app.databinding.DialogPageChoiceBinding
|
|
||||||
import io.legado.app.databinding.ViewLoadMoreBinding
|
import io.legado.app.databinding.ViewLoadMoreBinding
|
||||||
import io.legado.app.help.coroutine.Coroutine
|
|
||||||
import io.legado.app.lib.dialogs.alert
|
|
||||||
import io.legado.app.lib.theme.backgroundColor
|
|
||||||
import io.legado.app.model.webBook.WebBook
|
|
||||||
import io.legado.app.ui.book.group.GroupSelectDialog
|
|
||||||
import io.legado.app.ui.book.info.BookInfoActivity
|
import io.legado.app.ui.book.info.BookInfoActivity
|
||||||
import io.legado.app.ui.widget.dialog.WaitDialog
|
|
||||||
import io.legado.app.ui.widget.recycler.LoadMoreView
|
import io.legado.app.ui.widget.recycler.LoadMoreView
|
||||||
import io.legado.app.ui.widget.recycler.VerticalDivider
|
import io.legado.app.ui.widget.recycler.VerticalDivider
|
||||||
import io.legado.app.utils.showDialogFragment
|
|
||||||
import io.legado.app.utils.startActivity
|
import io.legado.app.utils.startActivity
|
||||||
import io.legado.app.utils.viewbindingdelegate.viewBinding
|
import io.legado.app.utils.viewbindingdelegate.viewBinding
|
||||||
import kotlinx.coroutines.Dispatchers.Main
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
|
|
||||||
class ExploreShowActivity : VMBaseActivity<ActivityExploreShowBinding, ExploreShowViewModel>(),
|
class ExploreShowActivity : VMBaseActivity<ActivityExploreShowBinding, ExploreShowViewModel>(),
|
||||||
ExploreShowAdapter.CallBack,
|
ExploreShowAdapter.CallBack {
|
||||||
GroupSelectDialog.CallBack {
|
|
||||||
override val binding by viewBinding(ActivityExploreShowBinding::inflate)
|
override val binding by viewBinding(ActivityExploreShowBinding::inflate)
|
||||||
override val viewModel by viewModels<ExploreShowViewModel>()
|
override val viewModel by viewModels<ExploreShowViewModel>()
|
||||||
|
|
||||||
private val adapter by lazy { ExploreShowAdapter(this, this) }
|
private val adapter by lazy { ExploreShowAdapter(this, this) }
|
||||||
private val loadMoreView by lazy { LoadMoreView(this) }
|
private val loadMoreView by lazy { LoadMoreView(this) }
|
||||||
private val waitDialog by lazy {
|
|
||||||
WaitDialog(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||||
binding.titleBar.title = intent.getStringExtra("exploreName")
|
binding.titleBar.title = intent.getStringExtra("exploreName")
|
||||||
@@ -116,84 +98,4 @@ class ExploreShowActivity : VMBaseActivity<ActivityExploreShowBinding, ExploreSh
|
|||||||
putExtra("bookUrl", book.bookUrl)
|
putExtra("bookUrl", book.bookUrl)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCompatCreateOptionsMenu(menu: Menu): Boolean {
|
|
||||||
menuInflater.inflate(R.menu.explore_show, menu)
|
|
||||||
return super.onCompatCreateOptionsMenu(menu)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCompatOptionsItemSelected(item: MenuItem): Boolean {
|
|
||||||
when (item.itemId) {
|
|
||||||
R.id.menu_add_all_to_bookshelf -> addAllToBookshelf()
|
|
||||||
}
|
|
||||||
return super.onCompatOptionsItemSelected(item)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun addAllToBookshelf() {
|
|
||||||
showDialogFragment(GroupSelectDialog(0))
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun upGroup(requestCode: Int, groupId: Long) {
|
|
||||||
|
|
||||||
alert("选择页数范围") {
|
|
||||||
val alertBinding = DialogPageChoiceBinding.inflate(layoutInflater).apply {
|
|
||||||
root.setBackgroundColor(root.context.backgroundColor)
|
|
||||||
}
|
|
||||||
customView { alertBinding.root }
|
|
||||||
yesButton {
|
|
||||||
alertBinding.run {
|
|
||||||
val start = editStart.text
|
|
||||||
.runCatching {
|
|
||||||
toString().toInt()
|
|
||||||
}.getOrDefault(1)
|
|
||||||
val end = editEnd.text
|
|
||||||
.runCatching {
|
|
||||||
toString().toInt()
|
|
||||||
}.getOrDefault(9)
|
|
||||||
addAllToBookshelf(start, end, groupId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
noButton()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun addAllToBookshelf(start: Int, end: Int, groupId: Long) {
|
|
||||||
val job = Coroutine.async {
|
|
||||||
launch(Main) {
|
|
||||||
waitDialog.setText("加载列表中...")
|
|
||||||
waitDialog.show()
|
|
||||||
}
|
|
||||||
val searchBooks = viewModel.loadExploreBooks(start, end)
|
|
||||||
val books = searchBooks.map {
|
|
||||||
it.toBook()
|
|
||||||
}
|
|
||||||
launch(Main) {
|
|
||||||
waitDialog.setText("添加书架中...")
|
|
||||||
}
|
|
||||||
books.forEach {
|
|
||||||
appDb.bookDao.getBook(it.bookUrl)?.let { book ->
|
|
||||||
book.group = book.group or groupId
|
|
||||||
it.order = appDb.bookDao.minOrder - 1
|
|
||||||
book.save()
|
|
||||||
return@forEach
|
|
||||||
}
|
|
||||||
if (it.tocUrl.isEmpty()) {
|
|
||||||
val source = appDb.bookSourceDao.getBookSource(it.origin)!!
|
|
||||||
WebBook.getBookInfoAwait(source, it)
|
|
||||||
}
|
|
||||||
it.order = appDb.bookDao.minOrder - 1
|
|
||||||
it.group = groupId
|
|
||||||
it.save()
|
|
||||||
}
|
|
||||||
}.onError {
|
|
||||||
AppLog.put("添加书架出错\n${it.localizedMessage}", it)
|
|
||||||
}.onFinally {
|
|
||||||
waitDialog.dismiss()
|
|
||||||
}
|
|
||||||
waitDialog.setOnCancelListener {
|
|
||||||
job.cancel()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,18 +70,4 @@ class ExploreShowViewModel(application: Application) : BaseViewModel(application
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun loadExploreBooks(start: Int, end: Int): List<SearchBook> {
|
|
||||||
val source = bookSource
|
|
||||||
val url = exploreUrl
|
|
||||||
if (source == null || url == null) return emptyList()
|
|
||||||
val searchBooks = arrayListOf<SearchBook>()
|
|
||||||
for (page in start..end) {
|
|
||||||
val books = WebBook.exploreBookAwait(source, url, page)
|
|
||||||
if (books.isEmpty()) break
|
|
||||||
searchBooks.addAll(books)
|
|
||||||
}
|
|
||||||
searchBooks.reverse()
|
|
||||||
return searchBooks
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,74 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:id="@+id/ll_content"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:background="@color/background"
|
|
||||||
android:gravity="center"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:padding="16dp">
|
|
||||||
|
|
||||||
<View
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:layout_weight="1" />
|
|
||||||
|
|
||||||
<EditText
|
|
||||||
android:id="@+id/edit_start"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center_vertical"
|
|
||||||
android:background="@drawable/bg_edit"
|
|
||||||
android:hint="@string/start"
|
|
||||||
android:importantForAutofill="no"
|
|
||||||
android:inputType="number"
|
|
||||||
android:lines="1"
|
|
||||||
android:maxLength="5"
|
|
||||||
android:minWidth="60dp"
|
|
||||||
android:paddingLeft="5dp"
|
|
||||||
android:paddingTop="4dp"
|
|
||||||
android:paddingRight="5dp"
|
|
||||||
android:paddingBottom="4dp"
|
|
||||||
android:textColor="@color/primaryText"
|
|
||||||
android:textCursorDrawable="@drawable/shape_text_cursor"
|
|
||||||
android:textSize="14sp"
|
|
||||||
tools:ignore="TouchTargetSizeCheck,TextContrastCheck" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center_vertical"
|
|
||||||
android:layout_marginLeft="5dp"
|
|
||||||
android:layout_marginRight="5dp"
|
|
||||||
android:text="@string/page_to"
|
|
||||||
android:textColor="@color/primaryText"
|
|
||||||
android:textSize="16sp" />
|
|
||||||
|
|
||||||
<EditText
|
|
||||||
android:id="@+id/edit_end"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center_vertical"
|
|
||||||
android:background="@drawable/bg_edit"
|
|
||||||
android:hint="@string/end"
|
|
||||||
android:importantForAutofill="no"
|
|
||||||
android:inputType="number"
|
|
||||||
android:lines="1"
|
|
||||||
android:maxLength="5"
|
|
||||||
android:minWidth="60dp"
|
|
||||||
android:paddingLeft="5dp"
|
|
||||||
android:paddingTop="4dp"
|
|
||||||
android:paddingRight="5dp"
|
|
||||||
android:paddingBottom="4dp"
|
|
||||||
android:textColor="@color/primaryText"
|
|
||||||
android:textCursorDrawable="@drawable/shape_text_cursor"
|
|
||||||
android:textSize="14sp"
|
|
||||||
tools:ignore="TouchTargetSizeCheck,SpeakableTextPresentCheck,TextContrastCheck" />
|
|
||||||
|
|
||||||
<View
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:layout_weight="1" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
|
|
||||||
<item
|
|
||||||
android:id="@+id/menu_add_all_to_bookshelf"
|
|
||||||
android:title="@string/add_all_to_bookshelf" />
|
|
||||||
|
|
||||||
</menu>
|
|
||||||
@@ -1117,8 +1117,6 @@
|
|||||||
<string name="test">测试</string>
|
<string name="test">测试</string>
|
||||||
<string name="show_wait_up_count">显示等待更新数量</string>
|
<string name="show_wait_up_count">显示等待更新数量</string>
|
||||||
<string name="exit_app">退出软件</string>
|
<string name="exit_app">退出软件</string>
|
||||||
<string name="add_all_to_bookshelf">全部加入书架</string>
|
|
||||||
<string name="page_to">页至</string>
|
|
||||||
<string name="result_analyzed">Analyzed</string>
|
<string name="result_analyzed">Analyzed</string>
|
||||||
<string name="bookshelf_px_4">Comprehensive</string>
|
<string name="bookshelf_px_4">Comprehensive</string>
|
||||||
<string name="effective_replaces">起效的替换</string>
|
<string name="effective_replaces">起效的替换</string>
|
||||||
|
|||||||
@@ -1120,8 +1120,6 @@
|
|||||||
<string name="test">测试</string>
|
<string name="test">测试</string>
|
||||||
<string name="show_wait_up_count">显示等待更新数量</string>
|
<string name="show_wait_up_count">显示等待更新数量</string>
|
||||||
<string name="exit_app">退出软件</string>
|
<string name="exit_app">退出软件</string>
|
||||||
<string name="add_all_to_bookshelf">全部加入书架</string>
|
|
||||||
<string name="page_to">页至</string>
|
|
||||||
<string name="result_analyzed">Analyzed</string>
|
<string name="result_analyzed">Analyzed</string>
|
||||||
<string name="bookshelf_px_4">Comprehensive</string>
|
<string name="bookshelf_px_4">Comprehensive</string>
|
||||||
<string name="effective_replaces">起效的替换</string>
|
<string name="effective_replaces">起效的替换</string>
|
||||||
|
|||||||
@@ -1120,8 +1120,6 @@
|
|||||||
<string name="test">测试</string>
|
<string name="test">测试</string>
|
||||||
<string name="show_wait_up_count">显示等待更新数量</string>
|
<string name="show_wait_up_count">显示等待更新数量</string>
|
||||||
<string name="exit_app">退出软件</string>
|
<string name="exit_app">退出软件</string>
|
||||||
<string name="add_all_to_bookshelf">全部加入书架</string>
|
|
||||||
<string name="page_to">页至</string>
|
|
||||||
<string name="result_analyzed">Analyzed</string>
|
<string name="result_analyzed">Analyzed</string>
|
||||||
<string name="bookshelf_px_4">Comprehensive</string>
|
<string name="bookshelf_px_4">Comprehensive</string>
|
||||||
<string name="effective_replaces">起效的替换</string>
|
<string name="effective_replaces">起效的替换</string>
|
||||||
|
|||||||
@@ -1116,8 +1116,6 @@ Còn </string>
|
|||||||
<string name="test">Kiểm tra</string>
|
<string name="test">Kiểm tra</string>
|
||||||
<string name="show_wait_up_count">Hiển thị số bản cập nhật đang đợi</string>
|
<string name="show_wait_up_count">Hiển thị số bản cập nhật đang đợi</string>
|
||||||
<string name="exit_app">Thoát khỏi phần mềm</string>
|
<string name="exit_app">Thoát khỏi phần mềm</string>
|
||||||
<string name="add_all_to_bookshelf">Thêm tất cả vào giá sách</string>
|
|
||||||
<string name="page_to">Trang tới</string>
|
|
||||||
<string name="result_analyzed">Analyzed</string>
|
<string name="result_analyzed">Analyzed</string>
|
||||||
<string name="bookshelf_px_4">Comprehensive</string>
|
<string name="bookshelf_px_4">Comprehensive</string>
|
||||||
<string name="effective_replaces">起效的替换</string>
|
<string name="effective_replaces">起效的替换</string>
|
||||||
|
|||||||
@@ -1117,8 +1117,6 @@
|
|||||||
<string name="test">测试</string>
|
<string name="test">测试</string>
|
||||||
<string name="show_wait_up_count">显示等待更新数量</string>
|
<string name="show_wait_up_count">显示等待更新数量</string>
|
||||||
<string name="exit_app">退出软件</string>
|
<string name="exit_app">退出软件</string>
|
||||||
<string name="add_all_to_bookshelf">全部加入书架</string>
|
|
||||||
<string name="page_to">页至</string>
|
|
||||||
<string name="result_analyzed">解析示例</string>
|
<string name="result_analyzed">解析示例</string>
|
||||||
<string name="bookshelf_px_4">綜合排序</string>
|
<string name="bookshelf_px_4">綜合排序</string>
|
||||||
<string name="effective_replaces">起效的替换</string>
|
<string name="effective_replaces">起效的替换</string>
|
||||||
|
|||||||
@@ -1119,8 +1119,6 @@
|
|||||||
<string name="test">测试</string>
|
<string name="test">测试</string>
|
||||||
<string name="show_wait_up_count">显示等待更新数量</string>
|
<string name="show_wait_up_count">显示等待更新数量</string>
|
||||||
<string name="exit_app">退出软件</string>
|
<string name="exit_app">退出软件</string>
|
||||||
<string name="add_all_to_bookshelf">全部加入书架</string>
|
|
||||||
<string name="page_to">页至</string>
|
|
||||||
<string name="result_analyzed">解析示例</string>
|
<string name="result_analyzed">解析示例</string>
|
||||||
<string name="bookshelf_px_4">綜合排序</string>
|
<string name="bookshelf_px_4">綜合排序</string>
|
||||||
<string name="effective_replaces">起效的替换</string>
|
<string name="effective_replaces">起效的替换</string>
|
||||||
|
|||||||
@@ -1119,8 +1119,6 @@
|
|||||||
<string name="test">测试</string>
|
<string name="test">测试</string>
|
||||||
<string name="show_wait_up_count">显示等待更新数量</string>
|
<string name="show_wait_up_count">显示等待更新数量</string>
|
||||||
<string name="exit_app">退出软件</string>
|
<string name="exit_app">退出软件</string>
|
||||||
<string name="add_all_to_bookshelf">全部加入书架</string>
|
|
||||||
<string name="page_to">页至</string>
|
|
||||||
<string name="result_analyzed">解析示例</string>
|
<string name="result_analyzed">解析示例</string>
|
||||||
<string name="bookshelf_px_4">综合排序</string>
|
<string name="bookshelf_px_4">综合排序</string>
|
||||||
<string name="effective_replaces">起效的替换</string>
|
<string name="effective_replaces">起效的替换</string>
|
||||||
|
|||||||
@@ -1120,8 +1120,6 @@
|
|||||||
<string name="test">Test</string>
|
<string name="test">Test</string>
|
||||||
<string name="show_wait_up_count">Display the number of pending updates</string>
|
<string name="show_wait_up_count">Display the number of pending updates</string>
|
||||||
<string name="exit_app">Exit</string>
|
<string name="exit_app">Exit</string>
|
||||||
<string name="add_all_to_bookshelf">全部加入书架</string>
|
|
||||||
<string name="page_to">页至</string>
|
|
||||||
<string name="result_analyzed">Analyzed</string>
|
<string name="result_analyzed">Analyzed</string>
|
||||||
<string name="bookshelf_px_4">Comprehensive</string>
|
<string name="bookshelf_px_4">Comprehensive</string>
|
||||||
<string name="effective_replaces">Effective replacement</string>
|
<string name="effective_replaces">Effective replacement</string>
|
||||||
|
|||||||
Reference in New Issue
Block a user