弹出menu初步
This commit is contained in:
parent
636375fe15
commit
7459af2f0a
|
|
@ -3,7 +3,9 @@ package com.remax.visualnovel.ui.Chat
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.widget.FrameLayout
|
import android.widget.FrameLayout
|
||||||
|
import android.widget.Toast
|
||||||
import com.dylanc.viewbinding.nonreflection.inflate
|
import com.dylanc.viewbinding.nonreflection.inflate
|
||||||
|
import com.remax.visualnovel.R
|
||||||
import com.remax.visualnovel.databinding.ChatInputpanelBinding
|
import com.remax.visualnovel.databinding.ChatInputpanelBinding
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -16,7 +18,24 @@ class InputPanel @JvmOverloads constructor(context: Context, attrs: AttributeSet
|
||||||
init {
|
init {
|
||||||
binding = inflate(ChatInputpanelBinding::inflate)
|
binding = inflate(ChatInputpanelBinding::inflate)
|
||||||
binding?.run {
|
binding?.run {
|
||||||
|
chatPopMenu.setMenuList(mutableListOf(
|
||||||
|
PopMenuIconView.MenuItem(R.mipmap.ic_launcher) {
|
||||||
|
Toast.makeText(context, "首页", Toast.LENGTH_SHORT).show()
|
||||||
|
},
|
||||||
|
PopMenuIconView.MenuItem(R.mipmap.ic_launcher) {
|
||||||
|
Toast.makeText(context, "设置", Toast.LENGTH_SHORT).show()
|
||||||
|
},
|
||||||
|
PopMenuIconView.MenuItem(R.mipmap.ic_launcher) {
|
||||||
|
Toast.makeText(context, "分享", Toast.LENGTH_SHORT).show()
|
||||||
|
},
|
||||||
|
PopMenuIconView.MenuItem(R.mipmap.ic_launcher) {
|
||||||
|
Toast.makeText(context, "收藏", Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,143 @@
|
||||||
|
package com.remax.visualnovel.ui.Chat
|
||||||
|
|
||||||
|
|
||||||
|
import android.animation.AnimatorSet
|
||||||
|
import android.animation.ValueAnimator
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import com.dylanc.viewbinding.nonreflection.inflate
|
||||||
|
import android.view.View
|
||||||
|
import android.view.animation.DecelerateInterpolator
|
||||||
|
import android.view.animation.OvershootInterpolator
|
||||||
|
import android.widget.FrameLayout
|
||||||
|
import android.widget.ImageView
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import com.remax.visualnovel.R
|
||||||
|
import com.remax.visualnovel.databinding.LayoutPopIconMenuViewBinding
|
||||||
|
import com.remax.visualnovel.utils.spannablex.utils.dp
|
||||||
|
|
||||||
|
|
||||||
|
class PopMenuIconView @JvmOverloads constructor(
|
||||||
|
context: Context,
|
||||||
|
attrs: AttributeSet? = null,
|
||||||
|
defStyleAttr: Int = 0
|
||||||
|
) : FrameLayout(context, attrs, defStyleAttr) {
|
||||||
|
|
||||||
|
data class MenuItem(
|
||||||
|
val iconResId: Int,
|
||||||
|
val onClick: (View) -> Unit
|
||||||
|
)
|
||||||
|
|
||||||
|
private val mMenuItemList = mutableListOf<MenuItem>()
|
||||||
|
private var isMenuShowing = true
|
||||||
|
private var itemSpacing = 0
|
||||||
|
private var itemSize = 0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private var mBinding: LayoutPopIconMenuViewBinding? = null
|
||||||
|
init {
|
||||||
|
itemSize = 30.dp
|
||||||
|
itemSpacing = 20.dp
|
||||||
|
mBinding = inflate(LayoutPopIconMenuViewBinding::inflate)
|
||||||
|
mBinding?.run {
|
||||||
|
ivTrigger.setImageResource(R.mipmap.chat_up)
|
||||||
|
ivTrigger.setOnClickListener { toggleMenu() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun setMenuList(menuList : List<MenuItem>) {
|
||||||
|
mMenuItemList.clear()
|
||||||
|
mMenuItemList.addAll(menuList)
|
||||||
|
updateMenuItems()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun updateMenuItems() {
|
||||||
|
mBinding!!.llMenuContainer.removeAllViews()
|
||||||
|
|
||||||
|
mMenuItemList.forEachIndexed { index, menuItem ->
|
||||||
|
ImageView(context).apply {
|
||||||
|
setImageResource(menuItem.iconResId)
|
||||||
|
|
||||||
|
layoutParams = LinearLayout.LayoutParams(itemSize, itemSize).apply {
|
||||||
|
if (index < mMenuItemList.size - 1) {
|
||||||
|
bottomMargin = itemSpacing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setOnClickListener {
|
||||||
|
menuItem.onClick(this)
|
||||||
|
dismissMenu()
|
||||||
|
}
|
||||||
|
|
||||||
|
mBinding!!.llMenuContainer.addView(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toggleMenu() {
|
||||||
|
if (isMenuShowing) dismissMenu() else showMenu()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showMenu() {
|
||||||
|
if (isMenuShowing) return
|
||||||
|
isMenuShowing = true
|
||||||
|
|
||||||
|
mBinding?.run {
|
||||||
|
llMenuContainer.visibility = VISIBLE
|
||||||
|
ivTrigger.setImageResource(R.mipmap.chat_down)
|
||||||
|
|
||||||
|
val maxWidthSpec = MeasureSpec.makeMeasureSpec(Int.MAX_VALUE/2, MeasureSpec.AT_MOST)
|
||||||
|
val heightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)
|
||||||
|
llMenuContainer.measure(maxWidthSpec, heightSpec)
|
||||||
|
val measureHeight = llMenuContainer.measuredHeight
|
||||||
|
|
||||||
|
val valueYAnim = ValueAnimator.ofInt(0, measureHeight).apply {
|
||||||
|
addUpdateListener {
|
||||||
|
val layoutParam = llMenuContainer.layoutParams
|
||||||
|
layoutParam.height = it.animatedValue as Int
|
||||||
|
llMenuContainer.layoutParams = layoutParam
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AnimatorSet().apply {
|
||||||
|
duration = 300
|
||||||
|
interpolator = OvershootInterpolator(2f)
|
||||||
|
playTogether(valueYAnim)
|
||||||
|
start()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun dismissMenu() {
|
||||||
|
if (!isMenuShowing) return
|
||||||
|
isMenuShowing = false
|
||||||
|
mBinding!!.ivTrigger.setImageResource(R.mipmap.chat_up)
|
||||||
|
|
||||||
|
mBinding?.run {
|
||||||
|
val valueYAnim = ValueAnimator.ofInt(llMenuContainer.measuredHeight, 0).apply {
|
||||||
|
addUpdateListener {
|
||||||
|
var layoutParam = llMenuContainer.layoutParams
|
||||||
|
layoutParam.height = it.animatedValue as Int
|
||||||
|
llMenuContainer.layoutParams = layoutParam
|
||||||
|
}
|
||||||
|
start()
|
||||||
|
}
|
||||||
|
|
||||||
|
AnimatorSet().apply {
|
||||||
|
duration = 300
|
||||||
|
interpolator = DecelerateInterpolator()
|
||||||
|
playTogether(valueYAnim)
|
||||||
|
start()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
package com.remax.visualnovel.utils
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.view.Gravity
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.PopupWindow
|
||||||
|
import androidx.core.widget.PopupWindowCompat
|
||||||
|
|
||||||
|
|
||||||
|
object PopupUtils {
|
||||||
|
fun showPopup(context: Context, anchorView: View, layoutRes: Int) {
|
||||||
|
val contentView = LayoutInflater.from(context).inflate(layoutRes, null)
|
||||||
|
val popupWindow = PopupWindow(
|
||||||
|
contentView,
|
||||||
|
ViewGroup.LayoutParams.WRAP_CONTENT,
|
||||||
|
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||||
|
).apply {
|
||||||
|
isFocusable = true
|
||||||
|
isOutsideTouchable = true
|
||||||
|
elevation = 10f
|
||||||
|
}
|
||||||
|
|
||||||
|
PopupWindowCompat.setOverlapAnchor(popupWindow, true)
|
||||||
|
PopupWindowCompat.showAsDropDown(popupWindow, anchorView, 0, 0, Gravity.START)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createPopup(context: Context, layoutRes: Int) : PopupWindow {
|
||||||
|
val contentView = LayoutInflater.from(context).inflate(layoutRes, null)
|
||||||
|
val popupWindow = PopupWindow(
|
||||||
|
contentView,
|
||||||
|
ViewGroup.LayoutParams.WRAP_CONTENT,
|
||||||
|
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||||
|
).apply {
|
||||||
|
isFocusable = true
|
||||||
|
isOutsideTouchable = true
|
||||||
|
elevation = 10f
|
||||||
|
}
|
||||||
|
|
||||||
|
PopupWindowCompat.setOverlapAnchor(popupWindow, true)
|
||||||
|
return popupWindow
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createPopup(context: Context, contentView: View) : PopupWindow {
|
||||||
|
val popupWindow = PopupWindow(
|
||||||
|
contentView,
|
||||||
|
ViewGroup.LayoutParams.WRAP_CONTENT,
|
||||||
|
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||||
|
).apply {
|
||||||
|
isFocusable = true
|
||||||
|
isOutsideTouchable = true
|
||||||
|
elevation = 10f
|
||||||
|
}
|
||||||
|
|
||||||
|
PopupWindowCompat.setOverlapAnchor(popupWindow, true)
|
||||||
|
return popupWindow
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -6,6 +6,14 @@
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="@mipmap/bg_level_1_page"
|
android:background="@mipmap/bg_level_1_page"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/iv_actor_bg"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:scaleType="centerCrop"
|
||||||
|
android:src="@mipmap/splash_bg"
|
||||||
|
/>
|
||||||
|
|
||||||
<com.remax.visualnovel.widget.uitoken.view.UITokenTextView
|
<com.remax.visualnovel.widget.uitoken.view.UITokenTextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
android:padding="@dimen/dp_20" >
|
android:padding="@dimen/dp_20" >
|
||||||
|
|
||||||
|
|
||||||
<com.remax.visualnovel.widget.uitoken.view.UITokenImageView
|
<!--<com.remax.visualnovel.widget.uitoken.view.UITokenImageView
|
||||||
android:id="@+id/chat_expand"
|
android:id="@+id/chat_expand"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|
@ -18,15 +18,21 @@
|
||||||
android:padding="@dimen/dp_12"
|
android:padding="@dimen/dp_12"
|
||||||
app:radiusToken="@string/radius_pill"
|
app:radiusToken="@string/radius_pill"
|
||||||
app:backgroundColorToken="@string/color_surface_element_normal"
|
app:backgroundColorToken="@string/color_surface_element_normal"
|
||||||
/>
|
/>-->
|
||||||
|
|
||||||
|
<com.remax.visualnovel.ui.Chat.PopMenuIconView
|
||||||
|
android:id="@+id/chat_pop_menu"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
/>
|
||||||
|
|
||||||
<com.remax.visualnovel.widget.uitoken.view.UITokenConstraintLayout
|
<com.remax.visualnovel.widget.uitoken.view.UITokenConstraintLayout
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:layout_constraintStart_toEndOf="@id/chat_expand"
|
app:layout_constraintStart_toEndOf="@id/chat_pop_menu"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
android:layout_marginStart="@dimen/dp_10"
|
android:layout_marginStart="@dimen/dp_10"
|
||||||
app:radiusToken="@string/radius_40"
|
app:radiusToken="@string/radius_40"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<com.remax.visualnovel.widget.uitoken.view.UITokenLinearLayout
|
||||||
|
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_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
app:radiusToken="@string/radius_pill"
|
||||||
|
app:backgroundColorToken="@string/color_surface_element_normal"
|
||||||
|
android:padding="@dimen/dp_14"
|
||||||
|
>
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/ll_menu_container"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
android:layout_gravity="bottom|center_horizontal"
|
||||||
|
android:layout_marginBottom="@dimen/dp_20">
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<com.remax.visualnovel.widget.uitoken.view.UITokenImageView
|
||||||
|
android:id="@+id/iv_trigger"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:src="@mipmap/chat_up"
|
||||||
|
/>
|
||||||
|
</com.remax.visualnovel.widget.uitoken.view.UITokenLinearLayout>
|
||||||
Loading…
Reference in New Issue