pull/1114/head
gedoor 3 years ago
parent 5283cfa6c0
commit 4adff555b9
  1. 2
      app/build.gradle
  2. 11
      app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt
  3. 83
      app/src/main/java/io/legado/app/ui/book/read/TextActionMenu.kt
  4. 47
      app/src/main/res/layout/popup_action_menu.xml
  5. 12
      app/src/main/res/menu/content_select_action.xml
  6. 2
      build.gradle

@ -123,7 +123,7 @@ dependencies {
//kotlin //kotlin
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
// //
def coroutines_version = '1.5.0' def coroutines_version = '1.5.1'
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"

@ -105,12 +105,7 @@ class ReadBookActivity : ReadBookBaseActivity(),
} }
private var menu: Menu? = null private var menu: Menu? = null
private val textActionMenu: TextActionMenu by lazy { private val textActionMenu: TextActionMenu by lazy {
TextActionMenu(this, this).apply { TextActionMenu(this, this)
contentView.measure(
View.MeasureSpec.UNSPECIFIED,
View.MeasureSpec.UNSPECIFIED
)
}
} }
override val scope: CoroutineScope get() = this override val scope: CoroutineScope get() = this
@ -474,6 +469,10 @@ class ReadBookActivity : ReadBookBaseActivity(),
* 显示文本操作菜单 * 显示文本操作菜单
*/ */
override fun showTextActionMenu() = binding.run { override fun showTextActionMenu() = binding.run {
textActionMenu.contentView.measure(
View.MeasureSpec.UNSPECIFIED,
View.MeasureSpec.UNSPECIFIED
)
val popupHeight = textActionMenu.contentView.measuredHeight val popupHeight = textActionMenu.contentView.measuredHeight
val x = textMenuPosition.x.toInt() val x = textMenuPosition.x.toInt()
var y = textMenuPosition.y.toInt() - popupHeight var y = textMenuPosition.y.toInt() - popupHeight

@ -17,25 +17,24 @@ import androidx.annotation.RequiresApi
import androidx.appcompat.view.SupportMenuInflater import androidx.appcompat.view.SupportMenuInflater
import androidx.appcompat.view.menu.MenuBuilder import androidx.appcompat.view.menu.MenuBuilder
import androidx.appcompat.view.menu.MenuItemImpl import androidx.appcompat.view.menu.MenuItemImpl
import androidx.core.view.isVisible
import io.legado.app.R import io.legado.app.R
import io.legado.app.base.adapter.ItemViewHolder
import io.legado.app.base.adapter.RecyclerAdapter
import io.legado.app.databinding.ItemTextBinding import io.legado.app.databinding.ItemTextBinding
import io.legado.app.databinding.PopupActionMenuBinding import io.legado.app.databinding.PopupActionMenuBinding
import io.legado.app.service.BaseReadAloudService import io.legado.app.service.BaseReadAloudService
import io.legado.app.utils.isAbsUrl import io.legado.app.utils.*
import io.legado.app.utils.sendToClip
import io.legado.app.utils.share
import io.legado.app.utils.toastOnUi
import splitties.views.onClick
import java.util.* import java.util.*
@SuppressLint("RestrictedApi") @SuppressLint("RestrictedApi")
class TextActionMenu(private val context: Context, private val callBack: CallBack) : class TextActionMenu(private val context: Context, private val callBack: CallBack) :
PopupWindow(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT), PopupWindow(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT),
TextToSpeech.OnInitListener { TextToSpeech.OnInitListener {
private val binding = PopupActionMenuBinding.inflate(LayoutInflater.from(context)) private val binding = PopupActionMenuBinding.inflate(LayoutInflater.from(context))
private val menu = MenuBuilder(context) private val adapter = Adapter(context)
private val moreMenu = MenuBuilder(context) private val visibleMenuItems: List<MenuItemImpl>
private val moreMenuItems: List<MenuItemImpl>
private val ttsListener by lazy { private val ttsListener by lazy {
TTSUtteranceListener() TTSUtteranceListener()
} }
@ -48,23 +47,71 @@ class TextActionMenu(private val context: Context, private val callBack: CallBac
isOutsideTouchable = false isOutsideTouchable = false
isFocusable = false isFocusable = false
SupportMenuInflater(context).inflate(R.menu.content_select_action, menu) val myMenu = MenuBuilder(context)
val otherMenu = MenuBuilder(context)
SupportMenuInflater(context).inflate(R.menu.content_select_action, myMenu)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
onInitializeMenu(moreMenu) onInitializeMenu(otherMenu)
}
visibleMenuItems = myMenu.visibleItems.subList(0, 5)
moreMenuItems =
myMenu.visibleItems.subList(5, myMenu.visibleItems.lastIndex) + otherMenu.visibleItems
initRecyclerView()
setOnDismissListener {
binding.ivMenuMore.setImageResource(R.drawable.ic_more_vert)
binding.recyclerViewMore.gone()
adapter.setItems(visibleMenuItems)
binding.recyclerView.visible()
}
}
private fun initRecyclerView() = with(binding) {
recyclerView.adapter = adapter
recyclerViewMore.adapter = adapter
adapter.setItems(visibleMenuItems)
ivMenuMore.visible()
ivMenuMore.setOnClickListener {
if (recyclerView.isVisible) {
ivMenuMore.setImageResource(R.drawable.ic_arrow_back)
adapter.setItems(moreMenuItems)
recyclerView.gone()
recyclerViewMore.visible()
} else {
ivMenuMore.setImageResource(R.drawable.ic_more_vert)
recyclerViewMore.gone()
adapter.setItems(visibleMenuItems)
recyclerView.visible()
}
}
}
inner class Adapter(context: Context) :
RecyclerAdapter<MenuItemImpl, ItemTextBinding>(context) {
override fun getViewBinding(parent: ViewGroup): ItemTextBinding {
return ItemTextBinding.inflate(inflater, parent, false)
} }
val menuItems = menu.visibleItems + moreMenu.visibleItems
menuItems.forEach { override fun convert(
val textView = ItemTextBinding.inflate(LayoutInflater.from(context)).root.apply { holder: ItemViewHolder,
tag = it binding: ItemTextBinding,
text = it.title item: MenuItemImpl,
onClick { payloads: MutableList<Any>
) {
with(binding) {
textView.text = item.title
}
}
override fun registerListener(holder: ItemViewHolder, binding: ItemTextBinding) {
holder.itemView.setOnClickListener {
getItem(holder.layoutPosition)?.let {
if (!callBack.onMenuItemSelected(it.itemId)) { if (!callBack.onMenuItemSelected(it.itemId)) {
onMenuItemSelected(it) onMenuItemSelected(it)
} }
callBack.onMenuActionFinally()
} }
callBack.onMenuActionFinally()
} }
binding.root.addView(textView)
} }
} }

@ -1,9 +1,46 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<com.google.android.flexbox.FlexboxLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="wrap_content"
android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="@drawable/shape_card_view" android:background="@drawable/shape_card_view"
android:padding="5dp" android:padding="5dp"
app:flexDirection="row" android:orientation="vertical">
app:flexWrap="wrap" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="horizontal"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_menu_more"
android:layout_width="24dp"
android:layout_height="24dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:src="@drawable/ic_more_vert"
android:tint="@color/primaryText"
android:visibility="gone"
android:contentDescription="@string/more_menu" />
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view_more"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="gone"
android:orientation="vertical"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
</LinearLayout>

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"> <menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item <item
android:id="@+id/menu_replace" android:id="@+id/menu_replace"
@ -23,13 +24,16 @@
<item <item
android:id="@+id/menu_search_content" android:id="@+id/menu_search_content"
android:title="@string/search_content" /> android:title="@string/search_content"
app:showAsAction="never" />
<item <item
android:id="@+id/menu_browser" android:id="@+id/menu_browser"
android:title="@string/browser" /> android:title="@string/browser"
app:showAsAction="never" />
<item <item
android:id="@+id/menu_share_str" android:id="@+id/menu_share_str"
android:title="@string/share" /> android:title="@string/share"
app:showAsAction="never" />
</menu> </menu>

@ -4,6 +4,7 @@ buildscript {
ext.kotlin_version = '1.5.20' ext.kotlin_version = '1.5.20'
repositories { repositories {
google() google()
mavenCentral()
maven { url 'https://maven.aliyun.com/repository/public' } maven { url 'https://maven.aliyun.com/repository/public' }
maven { url 'https://maven.aliyun.com/repository/gradle-plugin' } maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
maven { url 'https://plugins.gradle.org/m2/' } maven { url 'https://plugins.gradle.org/m2/' }
@ -18,6 +19,7 @@ buildscript {
allprojects { allprojects {
repositories { repositories {
google() google()
mavenCentral()
maven { url 'https://maven.aliyun.com/repository/public' } maven { url 'https://maven.aliyun.com/repository/public' }
maven { url 'https://jitpack.io' } maven { url 'https://jitpack.io' }
} }

Loading…
Cancel
Save