diff --git a/app/src/main/res/layout/video_trimmer.xml b/app/src/main/res/layout/video_trimmer.xml index 30e2db4..a8218e3 100644 --- a/app/src/main/res/layout/video_trimmer.xml +++ b/app/src/main/res/layout/video_trimmer.xml @@ -31,12 +31,14 @@ android:background="#33ffffff" app:layout_constraintBottom_toBottomOf="parent"/> + android:id="@+id/timeLineView" android:layout_width="match_parent" android:layout_height="40dp" + app:layout_constraintBottom_toBottomOf="parent" /> - + () private var maxWidth: Float = 0.toFloat() @@ -85,14 +84,6 @@ open class RangeSeekBarView @JvmOverloads constructor(context: Context, attrs: A context.resources.displayMetrics ).toInt().coerceAtLeast(1) - private fun initTimeLineHeight(context: Context) = - TypedValue.applyDimension( - TypedValue.COMPLEX_UNIT_DIP, - 40f, - context.resources.displayMetrics - ).toInt().coerceAtLeast(1) - - fun initMaxWidth() { maxWidth = thumbs[ThumbType.RIGHT.index].pos - thumbs[ThumbType.LEFT.index].pos onSeekStop(this, ThumbType.LEFT.index, thumbs[ThumbType.LEFT.index].value) @@ -101,11 +92,7 @@ open class RangeSeekBarView @JvmOverloads constructor(context: Context, attrs: A override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { super.onMeasure(widthMeasureSpec, heightMeasureSpec) - val minW = paddingLeft + paddingRight + suggestedMinimumWidth - viewWidth = View.resolveSizeAndState(minW, widthMeasureSpec, 1) - val minH = paddingBottom + paddingTop + timeLineHeight - val viewHeight = View.resolveSizeAndState(minH, heightMeasureSpec, 1) - setMeasuredDimension(viewWidth, viewHeight) + viewWidth=measuredWidth pixelRangeMin = 0f pixelRangeMax = (viewWidth - thumbWidth).toFloat() if (firstRun) { @@ -128,11 +115,11 @@ open class RangeSeekBarView @JvmOverloads constructor(context: Context, attrs: A if (thumb.index == ThumbType.LEFT.index) { val x = thumb.pos + paddingLeft if (x > pixelRangeMin) - canvas.drawRect(thumbWidth.toFloat(), 0f, (x + thumbWidth), timeLineHeight.toFloat(), shadowPaint) + canvas.drawRect(thumbWidth.toFloat(), 0f, (x + thumbWidth), height.toFloat(), shadowPaint) } else { val x = thumb.pos - paddingRight if (x < pixelRangeMax) - canvas.drawRect(x, 0f, (viewWidth - thumbWidth).toFloat(), timeLineHeight.toFloat(), shadowPaint) + canvas.drawRect(x, 0f, (viewWidth - thumbWidth).toFloat(), height.toFloat(), shadowPaint) } } //draw stroke around selected range @@ -140,20 +127,20 @@ open class RangeSeekBarView @JvmOverloads constructor(context: Context, attrs: A (thumbs[ThumbType.LEFT.index].pos + paddingLeft + thumbWidth), 0f, thumbs[ThumbType.RIGHT.index].pos - paddingRight, - timeLineHeight.toFloat(), + height.toFloat(), strokePaint ) //draw edges val circleRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 6f, context.resources.displayMetrics) canvas.drawCircle( (thumbs[ThumbType.LEFT.index].pos + paddingLeft + thumbWidth), - timeLineHeight.toFloat() / 2f, + height.toFloat() / 2f, circleRadius, edgePaint ) canvas.drawCircle( thumbs[ThumbType.RIGHT.index].pos - paddingRight, - timeLineHeight.toFloat() / 2f, + height.toFloat() / 2f, circleRadius, edgePaint ) diff --git a/video_trimmer_library/src/main/java/com/lb/video_trimmer_library/view/TimeLineView.kt b/video_trimmer_library/src/main/java/com/lb/video_trimmer_library/view/TimeLineView.kt index ea34d0b..b463037 100644 --- a/video_trimmer_library/src/main/java/com/lb/video_trimmer_library/view/TimeLineView.kt +++ b/video_trimmer_library/src/main/java/com/lb/video_trimmer_library/view/TimeLineView.kt @@ -23,8 +23,10 @@ */ package com.lb.video_trimmer_library.view +import android.annotation.SuppressLint import android.content.Context import android.graphics.Bitmap +import android.graphics.BitmapFactory import android.graphics.Canvas import android.media.MediaMetadataRetriever import android.media.ThumbnailUtils @@ -33,34 +35,38 @@ import android.os.Build.VERSION import android.os.Build.VERSION_CODES import android.util.AttributeSet import android.util.LongSparseArray -import android.util.TypedValue import android.view.View import com.lb.video_trimmer_library.utils.BackgroundExecutor import com.lb.video_trimmer_library.utils.UiThreadExecutor -open class TimeLineView @JvmOverloads constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int = 0) : View(context, attrs, defStyleAttr) { +open class TimeLineView @JvmOverloads constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int = 0) : + View(context, attrs, defStyleAttr) { private var videoUri: Uri? = null @Suppress("LeakingThis") - private var heightView: Int = initHeightView() private var bitmapList: LongSparseArray? = null - open fun initHeightView(): Int = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 40f, context.resources.displayMetrics).toInt().coerceAtLeast(1) - - override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { - val minW = paddingLeft + paddingRight + suggestedMinimumWidth - val w = View.resolveSizeAndState(minW, widthMeasureSpec, 1) - val minH = paddingBottom + paddingTop + heightView - val h = View.resolveSizeAndState(minH, heightMeasureSpec, 1) - setMeasuredDimension(w, h) - } - override fun onSizeChanged(w: Int, h: Int, oldW: Int, oldH: Int) { super.onSizeChanged(w, h, oldW, oldH) if (w != oldW) - getBitmap(w) + getBitmap(w, h) } - private fun getBitmap(viewWidth: Int) { + private fun getBitmap(viewWidth: Int, viewHeight: Int) { +// if (isInEditMode) +// return + // Set thumbnail properties (Thumbs are squares) + val thumbSize = viewHeight + val numThumbs = Math.ceil((viewWidth.toFloat() / thumbSize).toDouble()).toInt() + if (isInEditMode) { + val bitmap = ThumbnailUtils.extractThumbnail( + BitmapFactory.decodeResource(resources, android.R.drawable.sym_def_app_icon)!!, thumbSize, thumbSize + ) + bitmapList = LongSparseArray() + for (i in 0 until numThumbs) + bitmapList!!.put(i.toLong(), bitmap) + return + } + BackgroundExecutor.cancelAll("", true) BackgroundExecutor.execute(object : BackgroundExecutor.Task("", 0L, "") { override fun execute() { try { @@ -68,19 +74,20 @@ open class TimeLineView @JvmOverloads constructor(context: Context, attrs: Attri val mediaMetadataRetriever = MediaMetadataRetriever() mediaMetadataRetriever.setDataSource(context, videoUri) // Retrieve media data - val videoLengthInMs = (Integer.parseInt(mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)) * 1000).toLong() - // Set thumbnail properties (Thumbs are squares) - val thumbSize = heightView - val numThumbs = Math.ceil((viewWidth.toFloat() / thumbSize).toDouble()).toInt() + val videoLengthInMs = + mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION).toLong() * 1000L val interval = videoLengthInMs / numThumbs for (i in 0 until numThumbs) { - var bitmap: Bitmap? - bitmap = if (VERSION.SDK_INT >= VERSION_CODES.O_MR1) - mediaMetadataRetriever.getScaledFrameAtTime(i * interval, MediaMetadataRetriever.OPTION_CLOSEST_SYNC, thumbSize, thumbSize) - else - mediaMetadataRetriever.getFrameAtTime(i * interval, MediaMetadataRetriever.OPTION_CLOSEST_SYNC) + var bitmap: Bitmap? = if (VERSION.SDK_INT >= VERSION_CODES.O_MR1) + mediaMetadataRetriever.getScaledFrameAtTime( + i * interval, MediaMetadataRetriever.OPTION_CLOSEST_SYNC, thumbSize, thumbSize + ) + else mediaMetadataRetriever.getFrameAtTime( + i * interval, + MediaMetadataRetriever.OPTION_CLOSEST_SYNC + ) if (bitmap != null) - bitmap = ThumbnailUtils.extractThumbnail(bitmap, thumbSize, thumbSize) //Bitmap.createScaledBitmap(bitmap, thumbSize, thumbSize, false); + bitmap = ThumbnailUtils.extractThumbnail(bitmap, thumbSize, thumbSize) thumbnailList.put(i.toLong(), bitmap) } mediaMetadataRetriever.release() @@ -101,13 +108,14 @@ open class TimeLineView @JvmOverloads constructor(context: Context, attrs: Attri }, 0L) } + @SuppressLint("DrawAllocation") override fun onDraw(canvas: Canvas) { super.onDraw(canvas) if (bitmapList != null) { canvas.save() var x = 0 - for (i in 0 until bitmapList!!.size()) { - val bitmap = bitmapList!!.get(i.toLong()) + for (i in 0L until bitmapList!!.size()) { + val bitmap = bitmapList!!.get(i) if (bitmap != null) { canvas.drawBitmap(bitmap, x.toFloat(), 0f, null) x += bitmap.width