diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 9d778fbb3..a1b9f1846 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -23,6 +23,7 @@
android:label="@string/app_name"
android:networkSecurityConfig="@xml/network_security_config"
android:supportsRtl="true"
+ android:requestLegacyExternalStorage="true"
android:theme="@style/AppTheme.Light"
tools:ignore="AllowBackup,GoogleAppIndexingWarning,UnusedAttribute">
@@ -91,7 +92,7 @@
+ android:launchMode="singleTop" />
【备份与恢复】,选择【导入旧版本数据】。
* 请关注[开源阅读软件]()支持我,同时关注合作公众号[小说拾遗](),阅读公众号小编。
+**2020/03/13**
+* 更改书架控件,ViewPager2替换回2.0使用的ViewPager,解决下拉不流畅问题
+* 修复点击作者搜索后,打开的详情页还是原来的书籍的bug
+* 修改朗读菜单
+
+**2020/03/12**
+* 导入本地添加需要权限模式
+
**2020/03/11**
* 修复调节上边距时下边距一起动的bug
* 适配沚水的web阅读 by 六月
* 分组管理页面调整 by yangyxd
-* 导入本地添加需要权限模式
**2020/03/10**
* 优化文字选择菜单弹出位置
diff --git a/app/src/main/java/io/legado/app/constant/EventBus.kt b/app/src/main/java/io/legado/app/constant/EventBus.kt
index 88031b4fc..e24ba8000 100644
--- a/app/src/main/java/io/legado/app/constant/EventBus.kt
+++ b/app/src/main/java/io/legado/app/constant/EventBus.kt
@@ -11,7 +11,6 @@ object EventBus {
const val TIME_CHANGED = "timeChanged"
const val UP_CONFIG = "upConfig"
const val OPEN_CHAPTER = "openChapter"
- const val REPLACE = "replace"
const val AUDIO_SUB_TITLE = "audioSubTitle"
const val AUDIO_STATE = "audioState"
const val AUDIO_PROGRESS = "audioProgress"
diff --git a/app/src/main/java/io/legado/app/help/permission/PermissionsCompat.kt b/app/src/main/java/io/legado/app/help/permission/PermissionsCompat.kt
index a5ccdb266..4bbed5991 100644
--- a/app/src/main/java/io/legado/app/help/permission/PermissionsCompat.kt
+++ b/app/src/main/java/io/legado/app/help/permission/PermissionsCompat.kt
@@ -1,8 +1,11 @@
package io.legado.app.help.permission
+import android.os.Build
import androidx.annotation.StringRes
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
+import org.jetbrains.anko.startActivity
+import java.util.ArrayList
class PermissionsCompat private constructor() {
@@ -12,6 +15,17 @@ class PermissionsCompat private constructor() {
RequestManager.pushRequest(request)
}
+ companion object {
+ // 检查权限, 如果已经拥有返回 true
+ fun check(activity: AppCompatActivity, vararg permissions: String): Boolean {
+ var request: Request = Request(activity)
+ var pers = ArrayList()
+ pers.addAll(listOf(*permissions))
+ var data = request.getDeniedPermissions(pers.toTypedArray())
+ return data == null;
+ }
+ }
+
class Builder {
private val request: Request
diff --git a/app/src/main/java/io/legado/app/help/permission/Request.kt b/app/src/main/java/io/legado/app/help/permission/Request.kt
index 600cbe93c..f7ed0293a 100644
--- a/app/src/main/java/io/legado/app/help/permission/Request.kt
+++ b/app/src/main/java/io/legado/app/help/permission/Request.kt
@@ -102,7 +102,7 @@ internal class Request : OnRequestPermissionsResultCallback {
deniedCallback = null
}
- private fun getDeniedPermissions(permissions: Array?): Array? {
+ fun getDeniedPermissions(permissions: Array?): Array? {
if (permissions != null) {
val deniedPermissionList = ArrayList()
for (permission in permissions) {
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 61507bf7c..1f63dac89 100644
--- a/app/src/main/java/io/legado/app/service/TTSReadAloudService.kt
+++ b/app/src/main/java/io/legado/app/service/TTSReadAloudService.kt
@@ -29,7 +29,7 @@ class TTSReadAloudService : BaseReadAloudService(), TextToSpeech.OnInitListener
}
}
- private var ttsIsSuccess: Boolean = false
+ private var ttsInitFinish = false
override fun onCreate() {
super.onCreate()
@@ -42,22 +42,23 @@ class TTSReadAloudService : BaseReadAloudService(), TextToSpeech.OnInitListener
clearTTS()
}
+ @Synchronized
override fun onInit(status: Int) {
- launch {
- if (status == TextToSpeech.SUCCESS) {
- textToSpeech?.language = Locale.CHINA
- textToSpeech?.setOnUtteranceProgressListener(TTSUtteranceListener())
- ttsIsSuccess = true
- play()
- } else {
+ if (status == TextToSpeech.SUCCESS) {
+ textToSpeech?.language = Locale.CHINA
+ textToSpeech?.setOnUtteranceProgressListener(TTSUtteranceListener())
+ ttsInitFinish = true
+ play()
+ } else {
+ launch {
toast(R.string.tts_init_failed)
}
}
}
- @Suppress("DEPRECATION")
+ @Synchronized
override fun play() {
- if (contentList.isEmpty() || !ttsIsSuccess) {
+ if (contentList.isEmpty() || !ttsInitFinish) {
return
}
if (requestFocus()) {
diff --git a/app/src/main/java/io/legado/app/ui/book/arrange/ArrangeBookActivity.kt b/app/src/main/java/io/legado/app/ui/book/arrange/ArrangeBookActivity.kt
index f3b0d5ee5..15217f3bc 100644
--- a/app/src/main/java/io/legado/app/ui/book/arrange/ArrangeBookActivity.kt
+++ b/app/src/main/java/io/legado/app/ui/book/arrange/ArrangeBookActivity.kt
@@ -6,12 +6,14 @@ import android.view.MenuItem
import androidx.appcompat.widget.PopupMenu
import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer
+import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager
import io.legado.app.App
import io.legado.app.R
import io.legado.app.base.VMBaseActivity
import io.legado.app.data.entities.Book
import io.legado.app.data.entities.BookGroup
+import io.legado.app.help.ItemTouchCallback
import io.legado.app.lib.dialogs.alert
import io.legado.app.lib.dialogs.noButton
import io.legado.app.lib.dialogs.okButton
@@ -64,6 +66,10 @@ class ArrangeBookActivity : VMBaseActivity(R.layout.activi
recycler_view.addItemDecoration(VerticalDivider(this))
adapter = ArrangeBookAdapter(this, this)
recycler_view.adapter = adapter
+ val itemTouchCallback = ItemTouchCallback()
+ itemTouchCallback.onItemTouchCallbackListener = adapter
+ itemTouchCallback.isCanDrag = true
+ ItemTouchHelper(itemTouchCallback).attachToRecyclerView(recycler_view)
select_action_bar.setMainActionText(R.string.move_to_group)
select_action_bar.inflateMenu(R.menu.arrange_book_sel)
select_action_bar.setOnMenuItemClickListener(this)
diff --git a/app/src/main/java/io/legado/app/ui/book/arrange/ArrangeBookAdapter.kt b/app/src/main/java/io/legado/app/ui/book/arrange/ArrangeBookAdapter.kt
index fd51e3a3d..abc72b905 100644
--- a/app/src/main/java/io/legado/app/ui/book/arrange/ArrangeBookAdapter.kt
+++ b/app/src/main/java/io/legado/app/ui/book/arrange/ArrangeBookAdapter.kt
@@ -7,14 +7,13 @@ import io.legado.app.base.adapter.ItemViewHolder
import io.legado.app.base.adapter.SimpleRecyclerAdapter
import io.legado.app.data.entities.Book
import io.legado.app.data.entities.BookGroup
-import io.legado.app.utils.gone
-import io.legado.app.utils.visible
+import io.legado.app.help.ItemTouchCallback
import kotlinx.android.synthetic.main.item_arrange_book.view.*
import org.jetbrains.anko.sdk27.listeners.onClick
-
class ArrangeBookAdapter(context: Context, val callBack: CallBack) :
- SimpleRecyclerAdapter(context, R.layout.item_arrange_book) {
+ SimpleRecyclerAdapter(context, R.layout.item_arrange_book),
+ ItemTouchCallback.OnItemTouchCallbackListener {
val groupRequestCode = 12
private val selectedBooks: HashSet = hashSetOf()
var actionItem: Book? = null
@@ -56,12 +55,7 @@ class ArrangeBookAdapter(context: Context, val callBack: CallBack) :
override fun convert(holder: ItemViewHolder, item: Book, payloads: MutableList) {
with(holder.itemView) {
tv_name.text = item.name
-// tv_name.text = if (item.author.isEmpty()) {
-// item.name
-// } else {
-// "${item.name}(${item.author})"
-// }
- tv_author.text = item.author // resources.getString(R.string.author_show, item.author)
+ tv_author.text = item.author
tv_author.visibility = if (item.author.isEmpty()) View.GONE else View.VISIBLE
tv_group_s.text = getGroupName(item.group)
checkbox.isChecked = selectedBooks.contains(item)
@@ -115,7 +109,7 @@ class ArrangeBookAdapter(context: Context, val callBack: CallBack) :
groupNames.add(it.groupName)
}
}
- return groupNames;
+ return groupNames
}
private fun getGroupName(groupId: Int): String {
diff --git a/app/src/main/java/io/legado/app/ui/book/chapterlist/ChapterListFragment.kt b/app/src/main/java/io/legado/app/ui/book/chapterlist/ChapterListFragment.kt
index 51c8b8096..d717cb25f 100644
--- a/app/src/main/java/io/legado/app/ui/book/chapterlist/ChapterListFragment.kt
+++ b/app/src/main/java/io/legado/app/ui/book/chapterlist/ChapterListFragment.kt
@@ -36,6 +36,7 @@ class ChapterListFragment : VMBaseFragment(R.layout.fragme
private var durChapterIndex = 0
private lateinit var mLayoutManager: UpLinearLayoutManager
private var tocLiveData: LiveData>? = null
+ private var scrollToDurChapter = false
override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) {
viewModel.chapterCallBack = this
@@ -74,7 +75,6 @@ class ChapterListFragment : VMBaseFragment(R.layout.fragme
book?.let {
durChapterIndex = it.durChapterIndex
tv_current_chapter_info.text = it.durChapterTitle
- mLayoutManager.scrollToPositionWithOffset(durChapterIndex, 0)
initCacheFileNames(it)
}
}
@@ -85,7 +85,10 @@ class ChapterListFragment : VMBaseFragment(R.layout.fragme
tocLiveData = App.db.bookChapterDao().observeByBook(viewModel.bookUrl)
tocLiveData?.observe(viewLifecycleOwner, Observer {
adapter.setItems(it)
- mLayoutManager.scrollToPositionWithOffset(durChapterIndex, 0)
+ if (!scrollToDurChapter) {
+ mLayoutManager.scrollToPositionWithOffset(durChapterIndex, 0)
+ scrollToDurChapter = true
+ }
})
}
diff --git a/app/src/main/java/io/legado/app/ui/book/local/ImportBookActivity.kt b/app/src/main/java/io/legado/app/ui/book/local/ImportBookActivity.kt
index 2296423b4..3ce47ee99 100644
--- a/app/src/main/java/io/legado/app/ui/book/local/ImportBookActivity.kt
+++ b/app/src/main/java/io/legado/app/ui/book/local/ImportBookActivity.kt
@@ -8,6 +8,7 @@ import android.os.Bundle
import android.provider.DocumentsContract
import android.view.Menu
import android.view.MenuItem
+import android.view.View
import androidx.appcompat.widget.PopupMenu
import androidx.documentfile.provider.DocumentFile
import androidx.lifecycle.LiveData
@@ -17,6 +18,8 @@ import io.legado.app.App
import io.legado.app.R
import io.legado.app.base.VMBaseActivity
import io.legado.app.help.AppConfig
+import io.legado.app.help.permission.Permissions
+import io.legado.app.help.permission.PermissionsCompat
import io.legado.app.ui.filechooser.FileChooserDialog
import io.legado.app.ui.filechooser.FilePicker
import io.legado.app.ui.widget.SelectActionBar
@@ -80,6 +83,7 @@ class ImportBookActivity : VMBaseActivity(R.layout.activity
}
}
})
+
}
private fun initEvent() {
@@ -124,6 +128,24 @@ class ImportBookActivity : VMBaseActivity(R.layout.activity
subDocs.clear()
path = it
}
+ } ?: let {
+ // 没有权限就显示一个授权提示和按钮
+ if (PermissionsCompat.check(this, *Permissions.Group.STORAGE)) {
+ hint_per.visibility = View.GONE
+ } else {
+ hint_per.visibility = View.VISIBLE
+ tv_request_per.onClick {
+ PermissionsCompat.Builder(this)
+ .addPermissions(*Permissions.Group.STORAGE)
+ .rationale(R.string.tip_perm_request_storage)
+ .onGranted {
+ hint_per.visibility = View.GONE
+ initData()
+ upRootDoc()
+ }
+ .request()
+ }
+ }
}
upPath()
}
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 3de366ec3..138d676be 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
@@ -735,9 +735,6 @@ class ReadBookActivity : VMBaseActivity(R.layout.activity_boo
}
}
}
- observeEvent(EventBus.REPLACE) {
- ReplaceEditDialog().show(supportFragmentManager, "replaceEditDialog")
- }
observeEvent(PreferKey.keepLight) {
upScreenTimeOut()
}
diff --git a/app/src/main/java/io/legado/app/ui/book/read/config/ReadAloudDialog.kt b/app/src/main/java/io/legado/app/ui/book/read/config/ReadAloudDialog.kt
index 5540d0386..9c118c068 100644
--- a/app/src/main/java/io/legado/app/ui/book/read/config/ReadAloudDialog.kt
+++ b/app/src/main/java/io/legado/app/ui/book/read/config/ReadAloudDialog.kt
@@ -21,7 +21,6 @@ import io.legado.app.utils.observeEvent
import io.legado.app.utils.putPrefBoolean
import kotlinx.android.synthetic.main.dialog_read_aloud.*
import org.jetbrains.anko.sdk27.listeners.onClick
-import org.jetbrains.anko.sdk27.listeners.onLongClick
class ReadAloudDialog : BaseDialogFragment() {
var callBack: CallBack? = null
@@ -34,7 +33,7 @@ class ReadAloudDialog : BaseDialogFragment() {
it.windowManager?.defaultDisplay?.getMetrics(dm)
}
dialog?.window?.let {
- it.setBackgroundDrawableResource(R.color.transparent)
+ it.setBackgroundDrawableResource(R.color.background)
it.decorView.setPadding(0, 0, 0, 0)
val attr = it.attributes
attr.dimAmount = 0.0f
@@ -54,10 +53,10 @@ class ReadAloudDialog : BaseDialogFragment() {
}
override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) {
- ll_bottom_bg.setBackgroundColor(requireContext().bottomBackground)
+ root_view.setBackgroundColor(requireContext().bottomBackground)
initOnChange()
initData()
- initOnClick()
+ initEvent()
}
private fun initData() {
@@ -101,22 +100,19 @@ class ReadAloudDialog : BaseDialogFragment() {
})
}
- private fun initOnClick() {
- iv_menu.onClick { callBack?.showMenuBar(); dismiss() }
- iv_other_config.onClick {
+ private fun initEvent() {
+ ll_main_menu.onClick { callBack?.showMenuBar(); dismiss() }
+ ll_setting.onClick {
ReadAloudConfigDialog().show(childFragmentManager, "readAloudConfigDialog")
}
+ tv_pre.onClick { ReadBook.moveToPrevChapter(upContent = true, toLast = false) }
+ tv_next.onClick { ReadBook.moveToNextChapter(true) }
iv_stop.onClick { ReadAloud.stop(requireContext()); dismiss() }
iv_play_pause.onClick { callBack?.onClickReadAloud() }
iv_play_prev.onClick { ReadAloud.prevParagraph(requireContext()) }
- iv_play_prev.onLongClick {
- ReadBook.moveToPrevChapter(upContent = true, toLast = false)
- true
- }
iv_play_next.onClick { ReadAloud.nextParagraph(requireContext()) }
- iv_play_next.onLongClick { ReadBook.moveToNextChapter(true); true }
- fabToc.onClick { callBack?.openChapterList() }
- fabBack.onClick { callBack?.finish() }
+ ll_catalog.onClick { callBack?.openChapterList() }
+ ll_to_backstage.onClick { callBack?.finish() }
}
private fun upPlayState() {
diff --git a/app/src/main/java/io/legado/app/ui/filechooser/FilePicker.kt b/app/src/main/java/io/legado/app/ui/filechooser/FilePicker.kt
index 8f5549709..717ad8f11 100644
--- a/app/src/main/java/io/legado/app/ui/filechooser/FilePicker.kt
+++ b/app/src/main/java/io/legado/app/ui/filechooser/FilePicker.kt
@@ -31,7 +31,7 @@ object FilePicker {
0 -> default?.invoke()
1 -> {
try {
- val intent = getSelectDirIntent()
+ val intent = createSelectDirIntent()
activity.startActivityForResult(intent, requestCode)
} catch (e: java.lang.Exception) {
e.printStackTrace()
@@ -68,7 +68,7 @@ object FilePicker {
0 -> default?.invoke()
1 -> {
try {
- val intent = getSelectDirIntent()
+ val intent = createSelectDirIntent()
fragment.startActivityForResult(intent, requestCode)
} catch (e: java.lang.Exception) {
e.printStackTrace()
@@ -106,7 +106,7 @@ object FilePicker {
0 -> default?.invoke()
1 -> {
try {
- val intent = getSelectFileIntent()
+ val intent = createSelectFileIntent()
intent.type = type//设置类型
activity.startActivityForResult(intent, requestCode)
} catch (e: java.lang.Exception) {
@@ -147,7 +147,7 @@ object FilePicker {
0 -> default?.invoke()
1 -> {
try {
- val intent = getSelectFileIntent()
+ val intent = createSelectFileIntent()
intent.type = type//设置类型
fragment.startActivityForResult(intent, requestCode)
} catch (e: java.lang.Exception) {
@@ -168,14 +168,14 @@ object FilePicker {
}.show()
}
- private fun getSelectFileIntent(): Intent {
+ private fun createSelectFileIntent(): Intent {
val intent = Intent(Intent.ACTION_GET_CONTENT)
intent.addCategory(Intent.CATEGORY_OPENABLE)
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
return intent
}
- private fun getSelectDirIntent(): Intent {
+ private fun createSelectDirIntent(): Intent {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
return intent
diff --git a/app/src/main/java/io/legado/app/ui/main/MainActivity.kt b/app/src/main/java/io/legado/app/ui/main/MainActivity.kt
index 0d43b28c2..96424cc9b 100644
--- a/app/src/main/java/io/legado/app/ui/main/MainActivity.kt
+++ b/app/src/main/java/io/legado/app/ui/main/MainActivity.kt
@@ -78,7 +78,7 @@ class MainActivity : VMBaseActivity(R.layout.activity_main),
putPrefInt(PreferKey.versionCode, App.INSTANCE.versionCode)
if (!BuildConfig.DEBUG) {
val log = String(assets.open("updateLog.md").readBytes())
- TextDialog.show(supportFragmentManager, log, TextDialog.MD)
+ TextDialog.show(supportFragmentManager, log, TextDialog.MD, 5000)
}
}
}
diff --git a/app/src/main/java/io/legado/app/ui/main/bookshelf/BookshelfAdapter.kt b/app/src/main/java/io/legado/app/ui/main/bookshelf/BookshelfAdapter.kt
deleted file mode 100644
index 55115ad94..000000000
--- a/app/src/main/java/io/legado/app/ui/main/bookshelf/BookshelfAdapter.kt
+++ /dev/null
@@ -1,36 +0,0 @@
-package io.legado.app.ui.main.bookshelf
-
-import androidx.fragment.app.Fragment
-import androidx.viewpager2.adapter.FragmentStateAdapter
-import io.legado.app.data.entities.BookGroup
-import io.legado.app.ui.main.bookshelf.books.BooksFragment
-
-
-class BookshelfAdapter(fragment: Fragment, val callBack: CallBack) :
- FragmentStateAdapter(fragment) {
-
- private val ids = hashSetOf()
-
- override fun getItemCount(): Int {
- return callBack.groupSize
- }
-
- override fun getItemId(position: Int): Long {
- return callBack.getGroup(position).groupId.toLong()
- }
-
- override fun containsItem(itemId: Long): Boolean {
- return ids.contains(itemId)
- }
-
- override fun createFragment(position: Int): Fragment {
- val groupId = callBack.getGroup(position).groupId
- ids.add(groupId.toLong())
- return BooksFragment.newInstance(position, groupId)
- }
-
- interface CallBack {
- val groupSize: Int
- fun getGroup(position: Int): BookGroup
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/io/legado/app/ui/main/bookshelf/BookshelfFragment.kt b/app/src/main/java/io/legado/app/ui/main/bookshelf/BookshelfFragment.kt
index 3608a79ed..55dca8d77 100644
--- a/app/src/main/java/io/legado/app/ui/main/bookshelf/BookshelfFragment.kt
+++ b/app/src/main/java/io/legado/app/ui/main/bookshelf/BookshelfFragment.kt
@@ -7,10 +7,12 @@ import android.view.Menu
import android.view.MenuItem
import android.view.View
import androidx.appcompat.widget.SearchView
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.FragmentManager
+import androidx.fragment.app.FragmentStatePagerAdapter
import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer
import com.google.android.material.tabs.TabLayout
-import com.google.android.material.tabs.TabLayoutMediator
import io.legado.app.App
import io.legado.app.R
import io.legado.app.base.VMBaseFragment
@@ -29,6 +31,7 @@ import io.legado.app.ui.book.download.DownloadActivity
import io.legado.app.ui.book.group.GroupManageDialog
import io.legado.app.ui.book.local.ImportBookActivity
import io.legado.app.ui.book.search.SearchActivity
+import io.legado.app.ui.main.bookshelf.books.BooksFragment
import io.legado.app.ui.widget.text.AutoCompleteTextView
import io.legado.app.utils.*
import kotlinx.android.synthetic.main.dialog_bookshelf_config.view.*
@@ -42,15 +45,14 @@ import org.jetbrains.anko.startActivity
class BookshelfFragment : VMBaseFragment(R.layout.fragment_bookshelf),
TabLayout.OnTabSelectedListener,
SearchView.OnQueryTextListener,
- GroupManageDialog.CallBack,
- BookshelfAdapter.CallBack {
+ GroupManageDialog.CallBack {
override val viewModel: BookshelfViewModel
get() = getViewModel(BookshelfViewModel::class.java)
- private lateinit var bookshelfAdapter: BookshelfAdapter
private var bookGroupLiveData: LiveData>? = null
private val bookGroups = mutableListOf()
+ private val fragmentMap = hashMapOf()
override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) {
setSupportToolbar(toolbar)
@@ -79,26 +81,17 @@ class BookshelfFragment : VMBaseFragment(R.layout.fragment_b
}
}
- override val groupSize: Int
- get() = bookGroups.size
-
- override fun getGroup(position: Int): BookGroup {
- return bookGroups[position]
- }
-
private val selectedGroup: BookGroup
get() = bookGroups[view_pager_bookshelf.currentItem]
private fun initView() {
+ ATH.applyEdgeEffectColor(view_pager_bookshelf)
tab_layout.isTabIndicatorFullWidth = false
tab_layout.tabMode = TabLayout.MODE_SCROLLABLE
tab_layout.setSelectedTabIndicatorColor(requireContext().accentColor)
- ATH.applyEdgeEffectColor(view_pager_bookshelf)
- bookshelfAdapter = BookshelfAdapter(this, this)
- view_pager_bookshelf.adapter = bookshelfAdapter
- TabLayoutMediator(tab_layout, view_pager_bookshelf) { tab, position ->
- tab.text = bookGroups[position].groupName
- }.attach()
+ tab_layout.setupWithViewPager(view_pager_bookshelf)
+ view_pager_bookshelf.offscreenPageLimit = 1
+ view_pager_bookshelf.adapter = TabFragmentPageAdapter(childFragmentManager)
}
private fun initBookGroupData() {
@@ -119,7 +112,7 @@ class BookshelfFragment : VMBaseFragment(R.layout.fragment_b
bookGroups.add(AppConst.bookGroupAudio)
}
bookGroups.addAll(it)
- bookshelfAdapter.notifyDataSetChanged()
+ view_pager_bookshelf.adapter?.notifyDataSetChanged()
tab_layout.getTabAt(getPrefInt(PreferKey.saveTabPosition, 0))?.select()
tab_layout.addOnTabSelectedListener(this)
}
@@ -149,7 +142,7 @@ class BookshelfFragment : VMBaseFragment(R.layout.fragment_b
if (AppConfig.bookGroupAllShow) {
bookGroups.add(0, AppConst.bookGroupAll)
}
- bookshelfAdapter.notifyDataSetChanged()
+ view_pager_bookshelf.adapter?.notifyDataSetChanged()
}
}
@@ -212,4 +205,31 @@ class BookshelfFragment : VMBaseFragment(R.layout.fragment_b
putPrefInt(PreferKey.saveTabPosition, it)
}
}
+
+ private inner class TabFragmentPageAdapter internal constructor(fm: FragmentManager) :
+ FragmentStatePagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
+
+ override fun getPageTitle(position: Int): CharSequence? {
+ return bookGroups[position].groupName
+ }
+
+ override fun getItemPosition(`object`: Any): Int {
+ return POSITION_NONE
+ }
+
+ override fun getItem(position: Int): Fragment {
+ val group = bookGroups[position]
+ var fragment = fragmentMap[group.groupId]
+ if (fragment == null) {
+ fragment = BooksFragment.newInstance(position, group.groupId)
+ fragmentMap[group.groupId] = fragment
+ }
+ return fragment
+ }
+
+ override fun getCount(): Int {
+ return bookGroups.size
+ }
+
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/io/legado/app/ui/rss/read/ReadRssActivity.kt b/app/src/main/java/io/legado/app/ui/rss/read/ReadRssActivity.kt
index 79ea599d1..c37fb3761 100644
--- a/app/src/main/java/io/legado/app/ui/rss/read/ReadRssActivity.kt
+++ b/app/src/main/java/io/legado/app/ui/rss/read/ReadRssActivity.kt
@@ -246,8 +246,8 @@ class ReadRssActivity : VMBaseActivity(R.layout.activity_rss_r
@SuppressLint("SetJavaScriptEnabled")
private fun readAloud() {
- if (viewModel.textToSpeech.isSpeaking) {
- viewModel.textToSpeech.stop()
+ if (viewModel.textToSpeech?.isSpeaking == true) {
+ viewModel.textToSpeech?.stop()
upTtsMenu(false)
} else {
web_view.settings.javaScriptEnabled = true
diff --git a/app/src/main/java/io/legado/app/ui/rss/read/ReadRssViewModel.kt b/app/src/main/java/io/legado/app/ui/rss/read/ReadRssViewModel.kt
index 6d90fd181..d2aaad80f 100644
--- a/app/src/main/java/io/legado/app/ui/rss/read/ReadRssViewModel.kt
+++ b/app/src/main/java/io/legado/app/ui/rss/read/ReadRssViewModel.kt
@@ -35,7 +35,9 @@ class ReadRssViewModel(application: Application) : BaseViewModel(application),
val contentLiveData = MutableLiveData()
val urlLiveData = MutableLiveData()
var star = false
- var textToSpeech: TextToSpeech = TextToSpeech(context, this)
+ var textToSpeech: TextToSpeech? = null
+ private var ttsInitFinish = false
+ private var ttsText = ""
fun initData(intent: Intent) {
execute {
@@ -143,28 +145,42 @@ class ReadRssViewModel(application: Application) : BaseViewModel(application),
}
}
+ @Synchronized
override fun onInit(status: Int) {
- launch {
- if (status == TextToSpeech.SUCCESS) {
- textToSpeech.language = Locale.CHINA
- textToSpeech.setOnUtteranceProgressListener(TTSUtteranceListener())
- } else {
+ if (status == TextToSpeech.SUCCESS) {
+ textToSpeech?.language = Locale.CHINA
+ textToSpeech?.setOnUtteranceProgressListener(TTSUtteranceListener())
+ ttsInitFinish = true
+ play()
+ } else {
+ launch {
toast(R.string.tts_init_failed)
}
}
}
+ @Synchronized
+ private fun play() {
+ if (!ttsInitFinish) return
+ textToSpeech?.stop()
+ ttsText.split("\n", " ", " ").forEach {
+ textToSpeech?.speak(it, TextToSpeech.QUEUE_ADD, null, "rss")
+ }
+ }
+
fun readAloud(text: String) {
- textToSpeech.stop()
- text.split("\n", " ", " ").forEach {
- textToSpeech.speak(it, TextToSpeech.QUEUE_ADD, null, "rss")
+ ttsText = text
+ textToSpeech?.let {
+ play()
+ } ?: let {
+ textToSpeech = TextToSpeech(context, this)
}
}
override fun onCleared() {
super.onCleared()
- textToSpeech.stop()
- textToSpeech.shutdown()
+ textToSpeech?.stop()
+ textToSpeech?.shutdown()
}
/**
diff --git a/app/src/main/java/io/legado/app/ui/widget/dialog/TextDialog.kt b/app/src/main/java/io/legado/app/ui/widget/dialog/TextDialog.kt
index 01a55f2da..648949abd 100644
--- a/app/src/main/java/io/legado/app/ui/widget/dialog/TextDialog.kt
+++ b/app/src/main/java/io/legado/app/ui/widget/dialog/TextDialog.kt
@@ -5,29 +5,40 @@ import android.util.DisplayMetrics
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
-import androidx.fragment.app.DialogFragment
import androidx.fragment.app.FragmentManager
import io.legado.app.R
+import io.legado.app.base.BaseDialogFragment
import kotlinx.android.synthetic.main.dialog_text_view.*
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
import ru.noties.markwon.Markwon
-class TextDialog : DialogFragment() {
+class TextDialog : BaseDialogFragment() {
companion object {
const val MD = 1
- fun show(fragmentManager: FragmentManager, content: String?, mode: Int = 0) {
+ fun show(
+ fragmentManager: FragmentManager,
+ content: String?,
+ mode: Int = 0,
+ time: Long = 0
+ ) {
TextDialog().apply {
val bundle = Bundle()
bundle.putString("content", content)
bundle.putInt("mode", mode)
+ bundle.putLong("time", time)
arguments = bundle
+ isCancelable = false
}.show(fragmentManager, "textDialog")
}
}
+ private var time = 0L
+
override fun onStart() {
super.onStart()
val dm = DisplayMetrics()
@@ -43,8 +54,7 @@ class TextDialog : DialogFragment() {
return inflater.inflate(R.layout.dialog_text_view, container)
}
- override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- super.onViewCreated(view, savedInstanceState)
+ override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) {
arguments?.let {
val content = it.getString("content") ?: ""
when (it.getInt("mode")) {
@@ -57,8 +67,21 @@ class TextDialog : DialogFragment() {
}
else -> text_view.text = content
}
+ time = it.getLong("time", 0L)
+ }
+ if (time > 0) {
+ badge_view.setBadgeCount((time / 1000).toInt())
+ launch {
+ while (time > 0) {
+ delay(1000)
+ time -= 1000
+ badge_view.setBadgeCount((time / 1000).toInt())
+ if (time <= 0) {
+ dialog?.setCancelable(true)
+ }
+ }
+ }
}
-
}
}
diff --git a/app/src/main/res/layout/activity_import_book.xml b/app/src/main/res/layout/activity_import_book.xml
index e93a5b6c6..38d0b4f55 100644
--- a/app/src/main/res/layout/activity_import_book.xml
+++ b/app/src/main/res/layout/activity_import_book.xml
@@ -1,20 +1,23 @@
-
+ android:layout_height="wrap_content"
+ app:layout_constraintBottom_toBottomOf="parent" />
+
+
+
+
+
+
+
+
+
+
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/dialog_read_aloud.xml b/app/src/main/res/layout/dialog_read_aloud.xml
index 627bd9414..278117426 100644
--- a/app/src/main/res/layout/dialog_read_aloud.xml
+++ b/app/src/main/res/layout/dialog_read_aloud.xml
@@ -1,245 +1,333 @@
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:orientation="horizontal">
-
+
+
-
-
+
+
+
+
+
+
-
+
+
+
+
+
+
-
+ android:layout_weight="1"
+ android:max="60" />
-
+
-
+
-
-
+ android:layout_gravity="center_vertical"
+ android:orientation="horizontal"
+ android:padding="8dp">
-
-
-
-
-
-
-
-
-
-
-
-
-
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:layout_weight="1"
+ android:text="@string/read_aloud_speed"
+ android:textColor="@color/tv_text_default"
+ android:textSize="14sp" />
+
+
-
+ android:layout_marginStart="15dp"
+ android:layout_marginEnd="15dp"
+ android:max="45" />
+
+
+
+
+
+
+
-
-
+ android:contentDescription="@string/chapter_list"
+ android:src="@drawable/ic_toc"
+ app:tint="@color/tv_text_default"
+ tools:ignore="NestedWeights" />
-
+ android:layout_gravity="center_horizontal"
+ android:layout_marginTop="3dp"
+ android:text="@string/chapter_list"
+ android:textColor="@color/tv_text_default"
+ android:textSize="12sp" />
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="2" />
+
+
+
+
+
+
+
+
+
+ android:id="@+id/ll_to_backstage"
+ android:layout_width="50dp"
+ android:layout_height="50dp"
+ android:background="?android:attr/selectableItemBackgroundBorderless"
+ android:clickable="true"
+ android:contentDescription="@string/interface_setting"
+ android:focusable="true"
+ android:orientation="vertical"
+ android:paddingBottom="7dp">
-
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+ android:layout_height="0dp"
+ android:layout_weight="1"
+ android:contentDescription="@string/aloud_config"
+ android:src="@drawable/ic_settings"
+ app:tint="@color/tv_text_default"
+ tools:ignore="NestedWeights" />
+
diff --git a/app/src/main/res/layout/dialog_text_view.xml b/app/src/main/res/layout/dialog_text_view.xml
index 3a2b347c3..c1a1a70a6 100644
--- a/app/src/main/res/layout/dialog_text_view.xml
+++ b/app/src/main/res/layout/dialog_text_view.xml
@@ -1,7 +1,25 @@
-
+ xmlns:app="http://schemas.android.com/apk/res-auto">
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_bookshelf.xml b/app/src/main/res/layout/fragment_bookshelf.xml
index 2eb390c9a..ea0a9ab40 100644
--- a/app/src/main/res/layout/fragment_bookshelf.xml
+++ b/app/src/main/res/layout/fragment_bookshelf.xml
@@ -14,7 +14,7 @@
app:contentLayout="@layout/view_tab_layout_min"
app:layout_constraintTop_toTopOf="parent" />
-
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 9432842a2..63efa5aee 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -628,7 +628,6 @@
更多菜单
减
加
- 其它朗读设置
系统内置字体样式
删除源文件
预设一
@@ -646,5 +645,7 @@
导航栏阴影
当前阴影大小(elevation): %s
默认
-
+ 主菜单
+ 点击授予权限
+ 阅读需要访问存储卡权限,请点击下方的"授予权限"按钮,或前往“设置”—“应用权限”—打开所需权限。如果授予权限后仍然不正常,请点击右上角的“选择文件夹”,使用系统文件夹选择器。