From 2b51bc4bfa86863ed14b550fe3281840587ab038 Mon Sep 17 00:00:00 2001 From: Allan Wang Date: Sun, 12 Nov 2017 02:48:36 -0500 Subject: enhancement/video-player (#480) * Add toolbar visibility toggle and draw it over viewer * Set contract bindings once available * Fix video url param error and prepare progressanimator * Add gif support and better transitions * Interface a lot of things * Reorder back press * Clean up files and fix selector * Add gif support * Redraw bounds when necessary --- .../com/pitchedapps/frost/views/FrostVideoView.kt | 63 ++++++++++++++++------ 1 file changed, 46 insertions(+), 17 deletions(-) (limited to 'app/src/main/kotlin/com/pitchedapps/frost/views/FrostVideoView.kt') diff --git a/app/src/main/kotlin/com/pitchedapps/frost/views/FrostVideoView.kt b/app/src/main/kotlin/com/pitchedapps/frost/views/FrostVideoView.kt index c5508a4d..639dc9ba 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/views/FrostVideoView.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/views/FrostVideoView.kt @@ -8,10 +8,12 @@ import android.util.AttributeSet import android.view.GestureDetector import android.view.MotionEvent import android.view.View +import ca.allanwang.kau.utils.AnimHolder import ca.allanwang.kau.utils.dpToPx import ca.allanwang.kau.utils.scaleXY import com.devbrackets.android.exomedia.ui.widget.VideoView import com.pitchedapps.frost.utils.L +import com.pitchedapps.frost.utils.ProgressAnimator /** * Created by Allan Wang on 2017-10-13. @@ -29,10 +31,10 @@ class FrostVideoView @JvmOverloads constructor( private inline val v get() = videoViewImpl - var backgroundView: View? = null var onFinishedListener: () -> Unit = {} - lateinit var viewerContract: FrostVideoViewerContract + private lateinit var viewerContract: FrostVideoViewerContract lateinit var containerContract: FrostVideoContainerContract + var repeat: Boolean = false private val videoDimensions = PointF(0f, 0f) @@ -47,8 +49,8 @@ class FrostVideoView @JvmOverloads constructor( private val SWIPE_TO_CLOSE_HORIZONTAL_THRESHOLD = 2f.dpToPx private val SWIPE_TO_CLOSE_VERTICAL_THRESHOLD = 5f.dpToPx private val SWIPE_TO_CLOSE_OFFSET_THRESHOLD = 75f.dpToPx - val ANIMATION_DURATION = 300L - private val FAST_ANIMATION_DURATION = 100L + const val ANIMATION_DURATION = 200L + private const val FAST_ANIMATION_DURATION = 100L } private var videoBounds = RectF() @@ -59,19 +61,32 @@ class FrostVideoView @JvmOverloads constructor( if (videoDimensions.x <= 0f || videoDimensions.y <= 0f) return L.d("Attempted to toggle video expansion when points have not been finalized") field = value + val origX = translationX + val origY = translationY + val origScale = scaleX if (field) { - animate().scaleXY(1f).translationX(0f).translationY(0f).setDuration(ANIMATION_DURATION).withStartAction { - backgroundView?.animate()?.alpha(1f)?.setDuration(ANIMATION_DURATION) - viewerContract.onFade(1f, ANIMATION_DURATION) - }.withEndAction { - if (!isPlaying) showControls() + ProgressAnimator.ofFloat { + duration = ANIMATION_DURATION + interpolator = AnimHolder.fastOutSlowInInterpolator(context) + withAnimator { viewerContract.onExpand(it) } + withAnimator(origScale, 1f) { scaleXY = it } + withAnimator(origX, 0f) { translationX = it } + withAnimator(origY, 0f) { translationY = it } + withEndAction { + if (!isPlaying) showControls() + else viewerContract.onControlsHidden() + } } } else { hideControls() val (scale, tX, tY) = mapBounds() - animate().scaleXY(scale).translationX(tX).translationY(tY).setDuration(ANIMATION_DURATION).withStartAction { - backgroundView?.animate()?.alpha(0f)?.setDuration(ANIMATION_DURATION) - viewerContract.onFade(0f, ANIMATION_DURATION) + ProgressAnimator.ofFloat { + duration = ANIMATION_DURATION + interpolator = AnimHolder.fastOutSlowInInterpolator(context) + withAnimatorInv { viewerContract.onExpand(it) } + withAnimator(origScale, scale) { scaleXY = it } + withAnimator(origX, tX) { translationX = it } + withAnimator(origY, tY) { translationY = it } } } } @@ -110,16 +125,28 @@ class FrostVideoView @JvmOverloads constructor( if (isExpanded) showControls() } setOnCompletionListener { - viewerContract.onVideoComplete() + if (repeat) restart() + else viewerContract.onVideoComplete() } setOnTouchListener(FrameTouchListener(context)) v.setOnTouchListener(VideoTouchListener(context)) setOnVideoSizedChangedListener { intrinsicWidth, intrinsicHeight -> val ratio = Math.min(width.toFloat() / intrinsicWidth, height.toFloat() / intrinsicHeight.toFloat()) + /** + * Only remap if not expanded and if dimensions have changed + */ + val shouldRemap = !isExpanded + && (videoDimensions.x != ratio * intrinsicWidth || videoDimensions.y != ratio * intrinsicHeight) videoDimensions.set(ratio * intrinsicWidth, ratio * intrinsicHeight) + if (shouldRemap) updateLocation() } } + fun setViewerContract(contract: FrostVideoViewerContract) { + this.viewerContract = contract + videoControls?.setVisibilityListener(viewerContract) + } + fun jumpToStart() { pause() v.seekTo(0) @@ -136,7 +163,7 @@ class FrostVideoView @JvmOverloads constructor( override fun restart(): Boolean { videoUri ?: return false - if (videoViewImpl.restart() && isExpanded) { + if (videoViewImpl.restart() && isExpanded && !repeat) { videoControls?.showLoading(true) return true } @@ -163,9 +190,11 @@ class FrostVideoView @JvmOverloads constructor( fun destroy() { stopPlayback() if (alpha > 0f) - animate().alpha(0f).setDuration(FAST_ANIMATION_DURATION).withEndAction { onFinishedListener() }.withStartAction { - viewerContract.onFade(0f, FAST_ANIMATION_DURATION) - }.start() + ProgressAnimator.ofFloat(alpha, 0f) { + duration = FAST_ANIMATION_DURATION + withAnimator { alpha = it } + withEndAction { onFinishedListener() } + } else onFinishedListener() } -- cgit v1.2.3