aboutsummaryrefslogtreecommitdiff
path: root/app/src/main/kotlin/com/pitchedapps/frost/views
diff options
context:
space:
mode:
authorAllan Wang <me@allanwang.ca>2017-10-25 17:03:07 -0400
committerGitHub <noreply@github.com>2017-10-25 17:03:07 -0400
commitf3c14a1e5591f9d244c73bc0e53a6e042f5b9a06 (patch)
treedf4dfd3fa4694344cfdfb08a18b119062e1ac781 /app/src/main/kotlin/com/pitchedapps/frost/views
parente04487f5b1a4c6a5999db8d9746a07919ae9a333 (diff)
downloadfrost-f3c14a1e5591f9d244c73bc0e53a6e042f5b9a06.tar.gz
frost-f3c14a1e5591f9d244c73bc0e53a6e042f5b9a06.tar.bz2
frost-f3c14a1e5591f9d244c73bc0e53a6e042f5b9a06.zip
Fix/pip video (#445)v1.6.1
* Test frame wrapper * Update padding bounds * Clear toolbar on hide * Optimize * Update changelog * Disable toolbar rather than remove it * Improve controls and fix toolbar issue * Optimize
Diffstat (limited to 'app/src/main/kotlin/com/pitchedapps/frost/views')
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/views/FrostVideoView.kt55
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/views/FrostVideoViewer.kt78
2 files changed, 92 insertions, 41 deletions
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 eaa4e698..9932abae 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/views/FrostVideoView.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/views/FrostVideoView.kt
@@ -3,6 +3,7 @@ package com.pitchedapps.frost.views
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.PointF
+import android.graphics.RectF
import android.util.AttributeSet
import android.view.GestureDetector
import android.view.MotionEvent
@@ -30,7 +31,8 @@ class FrostVideoView @JvmOverloads constructor(
var backgroundView: View? = null
var onFinishedListener: () -> Unit = {}
- var viewerContract: FrostVideoViewerContract? = null
+ lateinit var viewerContract: FrostVideoViewerContract
+ lateinit var containerContract: FrostVideoContainerContract
private val videoDimensions = PointF(0f, 0f)
@@ -49,8 +51,7 @@ class FrostVideoView @JvmOverloads constructor(
private val FAST_ANIMATION_DURATION = 100L
}
- private var upperMinimizedX = 0f
- private var upperMinimizedY = 0f
+ private var videoBounds = RectF()
var isExpanded: Boolean = true
set(value) {
@@ -61,22 +62,25 @@ class FrostVideoView @JvmOverloads constructor(
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)
+ viewerContract.onFade(1f, ANIMATION_DURATION)
+ }.withEndAction {
+ if (!isPlaying) showControls()
}
} else {
hideControls()
- val height = height
- val width = width
val scale = Math.min(height / 4f / videoDimensions.y, width / 2.3f / videoDimensions.x)
val desiredHeight = scale * videoDimensions.y
val desiredWidth = scale * videoDimensions.x
- val translationX = (width - MINIMIZED_PADDING - desiredWidth) / 2
- val translationY = (height - MINIMIZED_PADDING - desiredHeight) / 2
- upperMinimizedX = width - desiredWidth - MINIMIZED_PADDING
- upperMinimizedY = height - desiredHeight - MINIMIZED_PADDING
+ val padding = containerContract.lowerVideoPadding
+ val offsetX = width - MINIMIZED_PADDING - desiredWidth
+ val offsetY = height - MINIMIZED_PADDING - desiredHeight
+ val translationX = offsetX / 2 - padding.x
+ val translationY = offsetY / 2 - padding.y
+ videoBounds.set(offsetX, offsetY, width.toFloat(), height.toFloat())
+ videoBounds.offset(padding.x, padding.y)
animate().scaleXY(scale).translationX(translationX).translationY(translationY).setDuration(ANIMATION_DURATION).withStartAction {
backgroundView?.animate()?.alpha(0f)?.setDuration(ANIMATION_DURATION)
- viewerContract?.onFade(0f, ANIMATION_DURATION)
+ viewerContract.onFade(0f, ANIMATION_DURATION)
}
}
}
@@ -84,10 +88,10 @@ class FrostVideoView @JvmOverloads constructor(
init {
setOnPreparedListener {
start()
- showControls()
+ if (isExpanded) showControls()
}
setOnCompletionListener {
- viewerContract?.onVideoComplete()
+ viewerContract.onVideoComplete()
}
setOnTouchListener(FrameTouchListener(context))
v.setOnTouchListener(VideoTouchListener(context))
@@ -104,6 +108,23 @@ class FrostVideoView @JvmOverloads constructor(
videoControls?.finishLoading()
}
+ override fun pause() {
+ audioFocusHelper.abandonFocus()
+ videoViewImpl.pause()
+ keepScreenOn = false
+ if (isExpanded)
+ videoControls?.updatePlaybackState(false)
+ }
+
+ override fun restart(): Boolean {
+ videoUri ?: return false
+ if (videoViewImpl.restart() && isExpanded) {
+ videoControls?.showLoading(true)
+ return true
+ }
+ return false
+ }
+
private fun hideControls() {
if (videoControls?.isVisible == true)
videoControls?.hide()
@@ -118,14 +139,14 @@ class FrostVideoView @JvmOverloads constructor(
fun shouldParentAcceptTouch(ev: MotionEvent): Boolean {
if (isExpanded) return true
- return ev.x >= upperMinimizedX && ev.y >= upperMinimizedY
+ return !videoBounds.contains(ev.x, ev.y)
}
fun destroy() {
stopPlayback()
if (alpha > 0f)
animate().alpha(0f).setDuration(FAST_ANIMATION_DURATION).withEndAction { onFinishedListener() }.withStartAction {
- viewerContract?.onFade(0f, FAST_ANIMATION_DURATION)
+ viewerContract.onFade(0f, FAST_ANIMATION_DURATION)
}.start()
else
onFinishedListener()
@@ -154,7 +175,7 @@ class FrostVideoView @JvmOverloads constructor(
}
override fun onSingleTapConfirmed(event: MotionEvent): Boolean {
- if (viewerContract?.onSingleTapConfirmed(event) != true)
+ if (!viewerContract.onSingleTapConfirmed(event))
toggleControls()
return true
}
@@ -217,7 +238,7 @@ class FrostVideoView @JvmOverloads constructor(
}
override fun onSingleTapConfirmed(event: MotionEvent): Boolean {
- if (viewerContract?.onSingleTapConfirmed(event) == true) return true
+ if (viewerContract.onSingleTapConfirmed(event)) return true
if (!isExpanded) {
isExpanded = true
return true
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/views/FrostVideoViewer.kt b/app/src/main/kotlin/com/pitchedapps/frost/views/FrostVideoViewer.kt
index 0f7d49e8..7ba49d3c 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/views/FrostVideoViewer.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/views/FrostVideoViewer.kt
@@ -2,13 +2,14 @@ package com.pitchedapps.frost.views
import android.content.Context
import android.graphics.Color
+import android.graphics.PointF
import android.net.Uri
-import android.support.constraint.ConstraintLayout
import android.support.v7.widget.Toolbar
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
+import android.widget.FrameLayout
import android.widget.ImageView
import ca.allanwang.kau.utils.*
import com.mikepenz.google_material_typeface_library.GoogleMaterial
@@ -23,24 +24,7 @@ import com.pitchedapps.frost.utils.frostDownload
*/
class FrostVideoViewer @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
-) : ConstraintLayout(context, attrs, defStyleAttr), FrostVideoViewerContract {
-
- override fun onFade(alpha: Float, duration: Long) {
- toolbar.animate().alpha(alpha).setDuration(duration)
- }
-
- override fun onSingleTapConfirmed(event: MotionEvent): Boolean {
- if (restarter.isVisible) {
- restarter.performClick()
- return true
- }
- return false
- }
-
- override fun onVideoComplete() {
- video.jumpToStart()
- restarter.fadeIn()
- }
+) : FrameLayout(context, attrs, defStyleAttr), FrostVideoViewerContract {
val container: ViewGroup by bindView(R.id.video_container)
val toolbar: Toolbar by bindView(R.id.video_toolbar)
@@ -48,20 +32,21 @@ class FrostVideoViewer @JvmOverloads constructor(
val video: FrostVideoView by bindView(R.id.video)
val restarter: ImageView by bindView(R.id.video_restart)
-
companion object {
/**
* Simplified binding to add video to layout, and remove it when finished
* This is under the assumption that the container allows for overlays,
* such as a FrameLayout
*/
- inline fun showVideo(container: ViewGroup, url: String, crossinline onFinish: () -> Unit): FrostVideoViewer {
+ fun showVideo(url: String, contract: FrostVideoContainerContract): FrostVideoViewer {
+ val container = contract.videoContainer
val videoViewer = FrostVideoViewer(container.context)
container.addView(videoViewer)
videoViewer.bringToFront()
L.d("Create video view", url)
videoViewer.setVideo(url)
- videoViewer.video.onFinishedListener = { container.removeView(videoViewer); onFinish() }
+ videoViewer.video.containerContract = contract
+ videoViewer.video.onFinishedListener = { container.removeView(videoViewer); contract.onVideoFinished() }
return videoViewer
}
}
@@ -91,6 +76,7 @@ class FrostVideoViewer @JvmOverloads constructor(
video.restart()
restarter.fadeOut { restarter.gone() }
}
+// toolbar.setOnTouchListener { _, event -> video.shouldParentAcceptTouch(event) }
}
fun setVideo(url: String) {
@@ -103,14 +89,40 @@ class FrostVideoViewer @JvmOverloads constructor(
* returns true if consumed, false otherwise
*/
fun onBackPressed(): Boolean {
- if (video.isExpanded) {
+ parent ?: return false
+ if (video.isExpanded)
video.isExpanded = false
+ else
+ video.destroy()
+ return true
+ }
+
+ fun pause() = video.pause()
+
+ /*
+ * -------------------------------------------------------------
+ * FrostVideoViewerContract
+ * -------------------------------------------------------------
+ */
+
+ override fun onFade(alpha: Float, duration: Long) {
+ toolbar.visible().animate().alpha(alpha).setDuration(duration).withEndAction {
+ if (alpha == 0f) toolbar.gone()
+ }
+ }
+
+ override fun onSingleTapConfirmed(event: MotionEvent): Boolean {
+ if (restarter.isVisible) {
+ restarter.performClick()
return true
}
return false
}
- fun pause() = video.pause()
+ override fun onVideoComplete() {
+ video.jumpToStart()
+ restarter.fadeIn()
+ }
}
@@ -118,4 +130,22 @@ interface FrostVideoViewerContract {
fun onSingleTapConfirmed(event: MotionEvent): Boolean
fun onFade(alpha: Float, duration: Long)
fun onVideoComplete()
+}
+
+interface FrostVideoContainerContract {
+ /**
+ * Returns extra padding to be added
+ * from the right and from the bottom respectively
+ */
+ val lowerVideoPadding: PointF
+
+ /**
+ * Get the container which will hold the video viewer
+ */
+ val videoContainer: FrameLayout
+
+ /**
+ * Called once the video has stopped & should be removed
+ */
+ fun onVideoFinished()
} \ No newline at end of file