conventionschedule-android/app/src/main/java/com/adlerosn/brasilfurfest/helper/PeekAndPop.kt

207 lines
9.1 KiB
Kotlin
Raw Normal View History

2018-12-12 04:30:34 +00:00
package com.adlerosn.brasilfurfest.helper
import android.app.Activity
import android.graphics.Point
import android.graphics.Rect
import androidx.annotation.IdRes
import androidx.annotation.LayoutRes
import androidx.appcompat.app.AlertDialog
2018-12-12 04:30:34 +00:00
import android.util.DisplayMetrics
import android.util.Log
import android.view.GestureDetector
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import kotlin.math.roundToInt
2019-05-23 14:58:10 +00:00
class PeekAndPop(builder: Builder) {
2018-12-12 04:30:34 +00:00
class Builder private constructor(val activity: Activity, val builderData: BuilderData) {
constructor(activity: Activity) : this(activity, BuilderData(
null,
null,
null,
2018-12-13 02:04:29 +00:00
false,
2018-12-12 04:30:34 +00:00
NullObjects.nullGeneralActionListener,
NullObjects.nullHoldAndReleaseListener
))
2019-05-23 14:58:10 +00:00
class BuilderData(
2018-12-12 04:30:34 +00:00
val peekLayout: Int?,
val longClickViews: View?,
val parentViewGroupToDisallowTouchEvents: ViewGroup?,
2018-12-13 02:04:29 +00:00
val blurs: Boolean,
2018-12-12 04:30:34 +00:00
val onGeneralActionListener: OnGeneralActionListener,
val onHoldAndReleaseListener: OnHoldAndReleaseListener
)
fun peekLayout(@LayoutRes layoutId: Int) = Builder(activity, BuilderData(
layoutId,
builderData.longClickViews,
builderData.parentViewGroupToDisallowTouchEvents,
2018-12-13 02:04:29 +00:00
builderData.blurs,
2018-12-12 04:30:34 +00:00
builderData.onGeneralActionListener,
builderData.onHoldAndReleaseListener
))
fun longClickViews(view: View): Builder = Builder(activity, BuilderData(
builderData.peekLayout,
view,
builderData.parentViewGroupToDisallowTouchEvents,
2018-12-13 02:04:29 +00:00
builderData.blurs,
2018-12-12 04:30:34 +00:00
builderData.onGeneralActionListener,
builderData.onHoldAndReleaseListener
))
fun parentViewGroupToDisallowTouchEvents(viewGroup: ViewGroup) = Builder(activity, BuilderData(
builderData.peekLayout,
builderData.longClickViews,
viewGroup,
2018-12-13 02:04:29 +00:00
builderData.blurs,
2018-12-12 04:30:34 +00:00
builderData.onGeneralActionListener,
builderData.onHoldAndReleaseListener
))
fun onGeneralActionListener(onGeneralActionListener: OnGeneralActionListener) = Builder(activity, BuilderData(
builderData.peekLayout,
builderData.longClickViews,
builderData.parentViewGroupToDisallowTouchEvents,
2018-12-13 02:04:29 +00:00
builderData.blurs,
2018-12-12 04:30:34 +00:00
onGeneralActionListener,
builderData.onHoldAndReleaseListener
))
fun onHoldAndReleaseListener(onHoldAndReleaseListener: PeekAndPop.OnHoldAndReleaseListener) = Builder(activity, BuilderData(
builderData.peekLayout,
builderData.longClickViews,
builderData.parentViewGroupToDisallowTouchEvents,
2018-12-13 02:04:29 +00:00
builderData.blurs,
2018-12-12 04:30:34 +00:00
builderData.onGeneralActionListener,
onHoldAndReleaseListener
))
2018-12-13 02:04:29 +00:00
fun blurBackground(blur: Boolean) = Builder(activity, BuilderData(
builderData.peekLayout,
builderData.longClickViews,
builderData.parentViewGroupToDisallowTouchEvents,
blur,
builderData.onGeneralActionListener,
builderData.onHoldAndReleaseListener
))
2018-12-12 04:30:34 +00:00
fun build(): PeekAndPop = PeekAndPop(this)
}
private val activity = builder.activity
private val peekLayout = builder.builderData.peekLayout!!
private val longClickViews = builder.builderData.longClickViews!!
private val parentViewGroupToDisallowTouchEvents = ( builder.builderData.parentViewGroupToDisallowTouchEvents ?: longClickViews ) as ViewGroup
private val onGeneralActionListener = builder.builderData.onGeneralActionListener
private val onHoldAndReleaseListener = builder.builderData.onHoldAndReleaseListener
val peekView = activity.layoutInflater.inflate(peekLayout)
init {
longClickViews.isLongClickable = true
longClickViews.setOnLongClickListener {
onGeneralActionListener.onPeek(longClickViews, -1)
parentViewGroupToDisallowTouchEvents.requestDisallowInterceptTouchEvent(true)
AlertDialog.Builder(activity)
.setView(peekView)
.setOnDismissListener {
(peekView.parent as ViewGroup).removeView(peekView)
longClickViews.setOnTouchListener(null)
cursorIsOver = null
onGeneralActionListener.onPop(longClickViews, -1)
}
.show()
.apply {
val dialog = this
window?.setBackgroundDrawableResource(android.R.color.transparent)
longClickViews.setOnTouchListener(object : View.OnTouchListener {
override fun onTouch(v: View, event: MotionEvent): Boolean {
when {
event.action == MotionEvent.ACTION_CANCEL -> dialog.dismiss()
event.action == MotionEvent.ACTION_MOVE -> {
val metrics = DisplayMetrics()
activity.windowManager.defaultDisplay.getMetrics(metrics)
val winSize = Point(metrics.widthPixels, metrics.heightPixels+(40*metrics.density).roundToInt())
val peekSize = peekView.let { Point(it.width, it.height) }
val offset = Point(
((winSize.x/2) - (peekSize.x/2)),
((winSize.y/2) - (peekSize.y/2))
)
val newCursorIsOver = holdAndReleaseViews.firstOrNull { view ->
val relativePosition = Rect()
view.getGlobalVisibleRect(relativePosition)
val actualPosition = Rect(
relativePosition.left+offset.x,
relativePosition.top+offset.y,
relativePosition.right+offset.x,
relativePosition.bottom+offset.y
)
2018-12-28 00:28:48 +00:00
Point(event.rawX.roundToInt(), event.rawY.roundToInt()) in actualPosition
2018-12-12 04:30:34 +00:00
}
updateCursorIsOver(newCursorIsOver)
}
event.action == MotionEvent.ACTION_UP -> {
cursorIsOver?.let { releasedView ->
onHoldAndReleaseListener.onRelease(releasedView, -1)
}
dialog.dismiss()
}
else -> dialog.dismiss()
}
return false
}
})
}
true
}
}
private var cursorIsOver: View? = null
private val holdAndReleaseViews = mutableListOf<View>()
private fun updateCursorIsOver(view: View?){
if(view != cursorIsOver){
cursorIsOver?.let {
onHoldAndReleaseListener.onLeave(it, -1)
}
view?.let {
onHoldAndReleaseListener.onHold(it, -1)
}
cursorIsOver = view
}
}
fun addHoldAndReleaseView(@IdRes idRes: Int) {
peekView.findViewById<View?>(idRes)?.let {
holdAndReleaseViews.add(it)
}
}
interface OnGeneralActionListener {
fun onPeek(longClickView: View, position: Int)
fun onPop(longClickView: View, position: Int)
}
interface OnHoldAndReleaseListener {
fun onHold(view: View, position: Int)
fun onLeave(view: View, position: Int)
fun onRelease(view: View, position: Int)
}
private object NullObjects {
val nullGeneralActionListener = object : OnGeneralActionListener{
override fun onPeek(longClickView: View, position: Int) {}
override fun onPop(longClickView: View, position: Int) {}
}
val nullHoldAndReleaseListener = object : OnHoldAndReleaseListener{
override fun onHold(view: View, position: Int) {}
override fun onLeave(view: View, position: Int) {}
override fun onRelease(view: View, position: Int) {}
}
}
2018-12-28 00:28:48 +00:00
}
private operator fun Rect.contains(point: Point): Boolean = contains(point.x, point.y)