Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<activity
android:name="com.banuba.sdk.ve.flow.VideoCreationActivity"
android:screenOrientation="portrait"
android:theme="@style/VideoCreationTheme"
android:theme="@style/CustomIntegrationAppTheme"
android:windowSoftInputMode="adjustResize"
tools:replace="android:theme" />
</application>
Expand Down
Binary file added app/src/main/assets/bnb-resources/luts/C1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/src/main/assets/bnb-resources/luts/C2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package com.banuba.example.integrationapp.videoeditor.custom

import android.content.Context
import android.view.ViewGroup
import com.banuba.example.integrationapp.R
import com.banuba.example.integrationapp.videoeditor.custom.widget.CustomRecordingButtonView
import com.banuba.sdk.cameraui.data.CameraRecordingAnimationProvider
import com.banuba.sdk.core.ui.ext.dimenPx

class CustomRecordingAnimationProvider (context: Context) : CameraRecordingAnimationProvider {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Нужно подумать как избавиться от этого в интеграции


private val animationView = CustomRecordingButtonView(context).apply {
val defaultButtonSize = context.dimenPx(R.dimen.record_button_size)
layoutParams = ViewGroup.LayoutParams(defaultButtonSize, defaultButtonSize)
isFocusable = true
isClickable = true
}

private var onEndTakenPictureAnimationCallback: () -> Unit = {}
private var onStartRecordingAnimationCallback: () -> Unit = {}
private var onEndRecordingAnimationCallback: () -> Unit = {}

override fun provideView() = animationView

override fun setOnStartRecordingAnimationCallback(callback: () -> Unit) {
onStartRecordingAnimationCallback = callback
}

override fun setOnEndRecordingAnimationCallback(callback: () -> Unit) {
onEndRecordingAnimationCallback = callback
}

override fun setOnEndTakenPictureAnimationCallback(callback: () -> Unit) {
onEndTakenPictureAnimationCallback = callback
}

override fun animatePauseRecording() {
animationView.pauseAnimation()
}

override fun animateResumeRecording() {
animationView.resumeAnimation()
}

override fun setRecordingPhotoState(state: CameraRecordingAnimationProvider.PhotoState) {
when (state) {
CameraRecordingAnimationProvider.PhotoState.Idle -> animationView.reset()
CameraRecordingAnimationProvider.PhotoState.Capture -> animationView.animateTakePhoto {
onEndTakenPictureAnimationCallback()
}
}
}

override fun setRecordingVideoState(state: CameraRecordingAnimationProvider.VideoState) {
when (state) {
is CameraRecordingAnimationProvider.VideoState.Idle -> animationView.reset()
is CameraRecordingAnimationProvider.VideoState.StartRecord -> {
if (state.availableDurationMs <= 0) return
animationView.animateStartVideoRecord(
availableDurationMs = state.availableDurationMs,
maxDurationMs = state.maxDurationMs
) {
onStartRecordingAnimationCallback()
}
}
is CameraRecordingAnimationProvider.VideoState.StopRecord -> {
animationView.animateStopVideoRecord {
onEndRecordingAnimationCallback()
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.banuba.example.integrationapp.videoeditor.content
package com.banuba.example.integrationapp.videoeditor.custom

import android.app.Activity
import android.content.Context
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package com.banuba.example.integrationapp.videoeditor.custom.widget

import android.animation.ValueAnimator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Нужно постараться исключить из интеграции

import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.view.View
import android.view.animation.LinearInterpolator
import com.banuba.example.integrationapp.R
import com.banuba.sdk.core.ui.ext.dimen

class CustomRecordingButtonOuterView @JvmOverloads constructor(
context: Context,
attr: AttributeSet? = null,
defStyle: Int = 0
) : View(context, attr, defStyle) {

companion object {
private const val ANGLE_END = 360F
private const val ANGLE_START = 0F
private const val INIT_VIEW_ROTATION = -90F
}

private var circleWidth = context.dimen(R.dimen.record_button_circle_idle_width)
set(value) {
field = value
gradientPaint.strokeWidth = value
whitePaint.strokeWidth = value
isDrawAreaMeasured = false
}
private val circleColors = context.resources.getIntArray(R.array.progress_gradient_colors)
private var circleDrawArea = RectF()

private var isDrawAreaMeasured = false

private val gradientPaint by lazy(LazyThreadSafetyMode.NONE) {
Paint().apply {
isAntiAlias = true
style = Paint.Style.STROKE
strokeWidth = circleWidth
shader = SweepGradient(
measuredWidth.toFloat() / 2,
measuredHeight.toFloat() / 2,
circleColors,
null
)
}
}
private val whitePaint by lazy(LazyThreadSafetyMode.NONE) {
Paint().apply {
color = Color.WHITE
isAntiAlias = true
style = Paint.Style.STROKE
strokeWidth = circleWidth
}
}

private var gradientSweepAngle = 0F

private val animator = ValueAnimator().apply {
repeatCount = 0
setFloatValues(ANGLE_START, ANGLE_END)
interpolator = LinearInterpolator()
addUpdateListener {
gradientSweepAngle = it.animatedValue as Float
invalidate()
}
}

init {
// Because 0 degrees angle correspond to 3 o'clock on a watch
rotation = INIT_VIEW_ROTATION
}

override fun onDraw(canvas: Canvas) {
if (!isDrawAreaMeasured) {
isDrawAreaMeasured = true
circleDrawArea = RectF(
0f + circleWidth,
0f + circleWidth,
measuredWidth.toFloat() - circleWidth,
measuredHeight.toFloat() - circleWidth
)
}
with(canvas) {
save()
rotate(gradientSweepAngle, measuredWidth.toFloat() / 2, measuredHeight.toFloat() / 2)
drawArc(circleDrawArea, ANGLE_START, ANGLE_END, false, gradientPaint)
restore()
drawArc(
circleDrawArea,
gradientSweepAngle,
ANGLE_END - gradientSweepAngle,
false,
whitePaint
)
}
}

fun startAnimation(
availableDurationMs: Long,
maxDurationMs: Long
) {
circleWidth = context.dimen(R.dimen.record_button_circle_progress_width)
animator.duration = maxDurationMs
animator.cancel()
animator.currentPlayTime = maxDurationMs - availableDurationMs
}

fun stopAnimation() {
circleWidth = context.dimen(R.dimen.record_button_circle_idle_width)
animator.cancel()
gradientSweepAngle = 0F
invalidate()
}

fun pauseAnimation() {
animator.pause()
}

fun resumeAnimation() {
animator.start()
}
}
Loading