blob: a079b06a0b10c614a790e156bd6485a2d4450858 [file] [log] [blame]
package com.android.systemui.media
import android.content.Context
import android.os.SystemClock
import android.util.AttributeSet
import android.view.InputDevice
import android.view.MotionEvent
import android.view.ViewGroup
import android.widget.HorizontalScrollView
import com.android.systemui.Gefingerpoken
import com.android.systemui.util.animation.physicsAnimator
/**
* A ScrollView used in Media that doesn't limit itself to the childs bounds. This is useful
* when only measuring children but not the parent, when trying to apply a new scroll position
*/
class MediaScrollView @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0)
: HorizontalScrollView(context, attrs, defStyleAttr) {
lateinit var contentContainer: ViewGroup
private set
var touchListener: Gefingerpoken? = null
/**
* The target value of the translation X animation. Only valid if the physicsAnimator is running
*/
var animationTargetX = 0.0f
/**
* Get the current content translation. This is usually the normal translationX of the content,
* but when animating, it might differ
*/
fun getContentTranslation() = if (contentContainer.physicsAnimator.isRunning()) {
animationTargetX
} else {
contentContainer.translationX
}
/**
* Allow all scrolls to go through, use base implementation
*/
override fun scrollTo(x: Int, y: Int) {
if (mScrollX != x || mScrollY != y) {
val oldX: Int = mScrollX
val oldY: Int = mScrollY
mScrollX = x
mScrollY = y
invalidateParentCaches()
onScrollChanged(mScrollX, mScrollY, oldX, oldY)
if (!awakenScrollBars()) {
postInvalidateOnAnimation()
}
}
}
override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
var intercept = false;
touchListener?.let {
intercept = it.onInterceptTouchEvent(ev)
}
return super.onInterceptTouchEvent(ev) || intercept;
}
override fun onTouchEvent(ev: MotionEvent?): Boolean {
var touch = false;
touchListener?.let {
touch = it.onTouchEvent(ev)
}
return super.onTouchEvent(ev) || touch
}
override fun onFinishInflate() {
super.onFinishInflate()
contentContainer = getChildAt(0) as ViewGroup
}
override fun overScrollBy(deltaX: Int, deltaY: Int, scrollX: Int, scrollY: Int,
scrollRangeX: Int, scrollRangeY: Int, maxOverScrollX: Int,
maxOverScrollY: Int, isTouchEvent: Boolean): Boolean {
if (getContentTranslation() != 0.0f) {
// When we're dismissing we ignore all the scrolling
return false
}
return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX,
scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent)
}
/**
* Cancel the current touch event going on.
*/
fun cancelCurrentScroll() {
val now = SystemClock.uptimeMillis()
val event = MotionEvent.obtain(now, now,
MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0)
event.source = InputDevice.SOURCE_TOUCHSCREEN
super.onTouchEvent(event)
event.recycle()
}
}