Я создаю экран для своего приложения, где у пользователя будет возможность обрезать видео и выбирать для них миниатюры (фотографии обложек) перед их загрузкой.
Я создал Recycleview с предварительным просмотром изображений каждый раз так часто, а затем ImageView в верхней части списка. Идея состоит в том, чтобы перемещать ImageView пальцами и по мере его загрузки загружать предварительный просмотр изображения внутри этого ImageView
Вот мой код:
video_edit_fragment. xml (часть этого)
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="15dp" >
<androidx.cardview.widget.CardView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:elevation="0dp"
app:cardElevation="0dp"
app:cardCornerRadius="12dp"
android:layout_centerInParent="true">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/coverPicker"
android:layout_width="match_parent"
android:layout_height="75dp"
android:clipToPadding="false"
android:orientation="horizontal"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/epoxy_thumbnail_item"
android:layout_centerInParent="true"/>
</androidx.cardview.widget.CardView>
<RelativeLayout
android:id="@+id/thumb"
android:layout_width="81dp"
android:layout_height="81dp"
android:clickable="true"
android:focusable="true">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/preview"
android:layout_width="75dp"
android:layout_height="75dp"
android:layout_centerInParent="true"
android:scaleType="centerCrop"
tools:src="@tools:sample/backgrounds/scenic"/>
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/shape_selection_box" />
</RelativeLayout>
</RelativeLayout>
Функция, которая загружает изображения для RecycleView:
private var videoUrl = ""
private var options = RequestOptions()
private fun getImages(video: Video) {
imageList.clear()
videoUrl = video.url
val retriever = FFmpegMediaMetadataRetriever()
retriever.setDataSource(video.url)
val videoDuration = retriever.extractMetadata(FFmpegMediaMetadataRetriever.METADATA_KEY_DURATION).toLong()
val step = TimeUnit.MILLISECONDS.toMicros((videoDuration - 1000) / (((videoDuration / 60000) + 1) * 6))
for (i in 0..(((videoDuration / 60000) + 1) * 6)) {
imageList.add(retriever.getFrameAtTime((i * step), FFmpegMediaMetadataRetriever.OPTION_CLOSEST))
}
thumbnailController.images = imageList
val visibleContentLength = getScreenWidth(activity) - dpToPx(30f)
val scrollContentLength = ((((videoDuration / 60000) + 1) * 6) + 1).toInt() * dpToPx(75f)
val videoPercentage = visibleContentLength / scrollContentLength.toFloat()
visibleVideoDuration = videoDuration * videoPercentage
options = RequestOptions()
.diskCacheStrategy(DiskCacheStrategy.ALL)
.skipMemoryCache(true)
.priority(Priority.IMMEDIATE)
.override(databind.preview.width, databind.preview.height)
.dontTransform()
.format(DecodeFormat.PREFER_ARGB_8888)
.signature(ObjectKey(videoUrl))
retriever.release()
}
И функция переопределения onTouch, которая вызывается при перемещении ImageView:
private var _xDelta = 0
private var maxX = 0f
override fun onTouch(v: View?, event: MotionEvent?): Boolean {
val x = event!!.rawX.toInt()
when (event.action) {
MotionEvent.ACTION_DOWN -> {
scrollView.requestDisallowInterceptTouchEvent(true)
val lParams = v!!.layoutParams as RelativeLayout.LayoutParams
_xDelta = x - lParams.leftMargin
}
MotionEvent.ACTION_UP -> {
scrollView.requestDisallowInterceptTouchEvent(false)
}
MotionEvent.ACTION_POINTER_DOWN -> {
}
MotionEvent.ACTION_POINTER_UP -> {
}
MotionEvent.ACTION_MOVE -> {
val layoutParams = v!!.layoutParams as RelativeLayout.LayoutParams
var newX = x - _xDelta
if (newX < 0) {
newX = 0
} else if (newX > maxX) {
newX = maxX.toInt()
}
layoutParams.leftMargin = newX
layoutParams.topMargin = 0
layoutParams.rightMargin = 0
layoutParams.bottomMargin = 0
v.layoutParams = layoutParams
val percentage = newX / maxX //percentage of moved screen
val imageTime = visibleVideoStartTime + (visibleVideoDuration * percentage)
Log.d("XYXYXY", imageTime.toString())
options = options.frame(TimeUnit.MILLISECONDS.toMicros(imageTime.toLong()))
databind.preview.load(videoUrl, options)
}
}
return true
}
Все вычисления еще не сделано, но работает как задумано (в настоящее время не применяется к RecycleView Scroll)
Вот конечный результат моего кода: https://imgur.com/a/HwomAlM
Я пытался это с: FFmpegMediaMetadataRetriever, MediaMetadataRetriever, FFmpeg Android ... Ничто не работает так хорошо, как Glide
Но есть ли способ сделать его еще лучше?
Заранее спасибо
Это мой первый пост здесь, если я могу предоставить более подробную информацию, пожалуйста, дайте мне знать:)