音频播放

This commit is contained in:
litingting 2025-10-23 18:19:17 +08:00
parent 063540eb58
commit 4fa3f505d0
12 changed files with 311 additions and 83 deletions

View File

@ -142,24 +142,19 @@ class PhotoDisplayDateChildAdapter(
item: ResultPhotosFiles, item: ResultPhotosFiles,
viewType: Int viewType: Int
) { ) {
when (holder) { when (holder) {
is TwoHolder -> holder.vb.run { is TwoHolder -> holder.vb.run {
initDateView(rootLayout, imageSelect, textSize, imageThumbnail, item, imageType) initDateView(rootLayout, imageSelect, textSize, imageThumbnail, item, imageType)
} }
is ThreeHolder -> holder.vb.run { is ThreeHolder -> holder.vb.run {
initDateView(rootLayout, imageSelect, textSize, imageThumbnail, item, imageType) initDateView(rootLayout, imageSelect, textSize, imageThumbnail, item, imageType)
} }
is OneHolder -> { is OneHolder -> {
item.run { item.run {
holder.vb.let { holder.vb.let {
it.textName.text = name it.textName.text = name
it.textDuration.text = Common.formatDuration(duration) it.textDuration.text = Common.formatDuration(duration)
it.textSize.text = sizeString it.textSize.text = sizeString
viewModel.checkIsSelect(this).let { isSelected -> viewModel.checkIsSelect(this).let { isSelected ->
it.imageSelect.isSelected = isSelected it.imageSelect.isSelected = isSelected
addOrRemove(this, isSelected) addOrRemove(this, isSelected)
@ -170,6 +165,9 @@ class PhotoDisplayDateChildAdapter(
addOrRemove(this, newStatus) addOrRemove(this, newStatus)
} }
} }
it.constraintLayout.setOnClickListener {
clickItem(this)
}
} }
} }

View File

@ -2,10 +2,16 @@ package com.ux.video.file.filerecovery.photo
import android.content.Intent import android.content.Intent
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.net.Uri
import android.os.Build import android.os.Build
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.ImageView
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.media3.common.MediaItem
import androidx.media3.common.Player
import androidx.media3.exoplayer.ExoPlayer
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.bumptech.glide.load.DataSource import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.engine.GlideException import com.bumptech.glide.load.engine.GlideException
@ -29,7 +35,9 @@ import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_documents
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_photo import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_photo
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_video import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_video
import com.ux.video.file.filerecovery.utils.ExtendFunctions.dpToPx import com.ux.video.file.filerecovery.utils.ExtendFunctions.dpToPx
import com.ux.video.file.filerecovery.video.PlayMediaManager
import com.ux.video.file.filerecovery.video.VideoPlayActivity import com.ux.video.file.filerecovery.video.VideoPlayActivity
import java.io.File
class PhotoInfoActivity : BaseActivity<ActivityPhotoInfoBinding>() { class PhotoInfoActivity : BaseActivity<ActivityPhotoInfoBinding>() {
@ -39,7 +47,7 @@ class PhotoInfoActivity : BaseActivity<ActivityPhotoInfoBinding>() {
private var scanType: Int = VALUE_SCAN_TYPE_photo private var scanType: Int = VALUE_SCAN_TYPE_photo
private var myData: ResultPhotosFiles? = null private var myData: ResultPhotosFiles? = null
private lateinit var player: ExoPlayer
override fun inflateBinding(inflater: LayoutInflater): ActivityPhotoInfoBinding = override fun inflateBinding(inflater: LayoutInflater): ActivityPhotoInfoBinding =
ActivityPhotoInfoBinding.inflate(inflater) ActivityPhotoInfoBinding.inflate(inflater)
@ -65,37 +73,10 @@ class PhotoInfoActivity : BaseActivity<ActivityPhotoInfoBinding>() {
tvName.text = resultPhotosFiles.name tvName.text = resultPhotosFiles.name
tvPath.text = resultPhotosFiles.path tvPath.text = resultPhotosFiles.path
tvSize.text = resultPhotosFiles.sizeString
tvDate.text = Common.getFormatDate(resultPhotosFiles.lastModified) tvDate.text = Common.getFormatDate(resultPhotosFiles.lastModified)
tvResolution.text = resultPhotosFiles.resolution tvResolution.text = resultPhotosFiles.resolution
tvDuration.text = Common.formatDuration(resultPhotosFiles.duration) tvDuration.text = Common.formatDuration(resultPhotosFiles.duration)
Glide.with(this@PhotoInfoActivity)
.load(resultPhotosFiles.targetFile)
.apply(RequestOptions().transform(CenterCrop(), RoundedCorners(8.dpToPx(this@PhotoInfoActivity))))
.listener(object : RequestListener<Drawable> {
override fun onLoadFailed(
e: GlideException?,
model: Any?,
target: Target<Drawable?>,
isFirstResource: Boolean
): Boolean {
return false
}
override fun onResourceReady(
resource: Drawable,
model: Any,
target: Target<Drawable?>?,
dataSource: DataSource,
isFirstResource: Boolean
): Boolean {
return false
}
})
.into(image)
layoutBottom.tvLeft.run { layoutBottom.tvLeft.run {
text = resources.getString(R.string.delete) text = resources.getString(R.string.delete)
setOnClickListener { setOnClickListener {
@ -109,7 +90,6 @@ class PhotoInfoActivity : BaseActivity<ActivityPhotoInfoBinding>() {
} }
} }
} }
layoutBottom.tvRight.run { layoutBottom.tvRight.run {
text = resources.getString(R.string.recover) text = resources.getString(R.string.recover)
setOnClickListener { setOnClickListener {
@ -134,12 +114,17 @@ class PhotoInfoActivity : BaseActivity<ActivityPhotoInfoBinding>() {
layoutPath.isVisible = true layoutPath.isVisible = true
layoutResolution.isVisible = true layoutResolution.isVisible = true
layoutDate.isVisible = true layoutDate.isVisible = true
frameImage.setBackgroundResource(0)
layoutSeekbar.isVisible = false
layoutType.isVisible = false layoutType.isVisible = false
layoutSize.isVisible = false layoutSize.isVisible = false
layoutDuration.isVisible = false layoutDuration.isVisible = false
imPlay.isVisible = false imPlay.isVisible = false
myData?.targetFile?.let { loadImage(image,it) }
} }
VALUE_SCAN_TYPE_video, VALUE_SCAN_TYPE_deleted_video -> { VALUE_SCAN_TYPE_video, VALUE_SCAN_TYPE_deleted_video -> {
@ -148,12 +133,16 @@ class PhotoInfoActivity : BaseActivity<ActivityPhotoInfoBinding>() {
layoutResolution.isVisible = true layoutResolution.isVisible = true
layoutDate.isVisible = true layoutDate.isVisible = true
layoutDuration.isVisible = true layoutDuration.isVisible = true
frameImage.setBackgroundResource(0)
layoutSeekbar.isVisible = false
layoutType.isVisible = false layoutType.isVisible = false
layoutSize.isVisible = false layoutSize.isVisible = false
imPlay.isVisible = true imPlay.isVisible = true
myData?.let { data-> myData?.let { data->
data.targetFile?.let { loadImage(image,it) }
frameImage.setOnClickListener { frameImage.setOnClickListener {
startActivity(Intent(this@PhotoInfoActivity, VideoPlayActivity::class.java).apply { startActivity(Intent(this@PhotoInfoActivity, VideoPlayActivity::class.java).apply {
putExtra(VideoPlayActivity.KEY_DATA, data) putExtra(VideoPlayActivity.KEY_DATA, data)
@ -163,12 +152,25 @@ class PhotoInfoActivity : BaseActivity<ActivityPhotoInfoBinding>() {
} }
VALUE_SCAN_TYPE_audio, VALUE_SCAN_TYPE_deleted_audio -> { VALUE_SCAN_TYPE_audio, VALUE_SCAN_TYPE_deleted_audio -> {
Common.showLog("----------音频")
layoutName.isVisible = true layoutName.isVisible = true
layoutPath.isVisible = true layoutPath.isVisible = true
layoutSize.isVisible = true layoutSize.isVisible = true
layoutDate.isVisible = true layoutDate.isVisible = true
layoutDuration.isVisible = true layoutDuration.isVisible = true
layoutSeekbar.isVisible = true
imPlay.isVisible = true
frameImage.setBackgroundResource(R.drawable.bg_info_music_f2f2f7_8)
image.setImageResource(R.drawable.image_info_music)
val params = image.layoutParams ?: ViewGroup.LayoutParams(
180.dpToPx(this@PhotoInfoActivity),
180.dpToPx(this@PhotoInfoActivity)
)
params.width = 180.dpToPx(this@PhotoInfoActivity)
params.height = 180.dpToPx(this@PhotoInfoActivity)
image.layoutParams = params
initPlayAudio()
layoutResolution.isVisible = false layoutResolution.isVisible = false
layoutType.isVisible = false layoutType.isVisible = false
} }
@ -189,6 +191,49 @@ class PhotoInfoActivity : BaseActivity<ActivityPhotoInfoBinding>() {
} }
private fun loadImage(image: ImageView,file: File){
Glide.with(this@PhotoInfoActivity)
.load(file)
.apply(RequestOptions().transform(CenterCrop(), RoundedCorners(8.dpToPx(this@PhotoInfoActivity))))
.listener(object : RequestListener<Drawable> {
override fun onLoadFailed(
e: GlideException?,
model: Any?,
target: Target<Drawable?>,
isFirstResource: Boolean
): Boolean {
return false
}
override fun onResourceReady(
resource: Drawable,
model: Any,
target: Target<Drawable?>?,
dataSource: DataSource,
isFirstResource: Boolean
): Boolean {
return false
}
})
.into(image)
}
private fun initPlayAudio(){
myData?.targetFile?.let {
binding.run {
PlayMediaManager(context = this@PhotoInfoActivity, mediaFile = it,
seekBar = seekBar, playBtn = imPlay, onUpdateProgress = { current,total->
textTimeCurrent.text = current
textTimeTotal.text = total
} )
}
}
}
private fun complete(number: Int, type: Int) { private fun complete(number: Int, type: Int) {
finish() finish()
startActivity(Intent(this@PhotoInfoActivity, RecoverySuccessActivity::class.java).apply { startActivity(Intent(this@PhotoInfoActivity, RecoverySuccessActivity::class.java).apply {

View File

@ -170,7 +170,7 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
this@PhotoSortingActivity, this@PhotoSortingActivity,
PhotoInfoActivity::class.java PhotoInfoActivity::class.java
).apply { ).apply {
putExtra(KEY_SCAN_TYPE,scanType) putExtra(KEY_SCAN_TYPE, scanType)
putExtra(PhotoInfoActivity.KEY_CLICK_ITEM, item) putExtra(PhotoInfoActivity.KEY_CLICK_ITEM, item)
}) })
@ -189,7 +189,7 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
this@PhotoSortingActivity, this@PhotoSortingActivity,
PhotoInfoActivity::class.java PhotoInfoActivity::class.java
).apply { ).apply {
putExtra(KEY_SCAN_TYPE,scanType) putExtra(KEY_SCAN_TYPE, scanType)
putExtra(PhotoInfoActivity.KEY_CLICK_ITEM, item) putExtra(PhotoInfoActivity.KEY_CLICK_ITEM, item)
}) })
}.apply { }.apply {
@ -477,10 +477,20 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
private fun setSizeAdapter() { private fun setSizeAdapter() {
binding.recyclerView.run { binding.recyclerView.run {
val aPx = 16.dpToPx(context) val aPx = 16.dpToPx(context)
val bottom = 70.dpToPx(context)
when (scanType) {
VALUE_SCAN_TYPE_audio, VALUE_SCAN_TYPE_deleted_audio -> {
layoutManager = LinearLayoutManager(context)
setPadding(aPx, 0, 0, bottom)
}
else -> {
val bPx = 6.dpToPx(context) val bPx = 6.dpToPx(context)
setPadding(aPx, 0, bPx, 70.dpToPx(context)) setPadding(aPx, 0, bPx, bottom)
clipToPadding = false clipToPadding = false
layoutManager = GridLayoutManager(context, columns) layoutManager = GridLayoutManager(context, columns)
}
}
adapter = sizeSortAdapter adapter = sizeSortAdapter
} }
@ -685,6 +695,7 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
VALUE_SCAN_TYPE_photo, VALUE_SCAN_TYPE_deleted_photo, VALUE_SCAN_TYPE_documents, VALUE_SCAN_TYPE_deleted_documents -> { VALUE_SCAN_TYPE_photo, VALUE_SCAN_TYPE_deleted_photo, VALUE_SCAN_TYPE_documents, VALUE_SCAN_TYPE_deleted_documents -> {
filterBySizeList(filterSizeCovert.first, filterSizeCovert.second) filterBySizeList(filterSizeCovert.first, filterSizeCovert.second)
} }
else -> { else -> {
filterByDurationList(filterSizeCovert.first, filterSizeCovert.second) filterByDurationList(filterSizeCovert.first, filterSizeCovert.second)
} }

View File

@ -0,0 +1,110 @@
package com.ux.video.file.filerecovery.video
import android.content.Context
import android.net.Uri
import android.os.Handler
import android.os.Looper
import android.widget.ImageView
import android.widget.SeekBar
import androidx.media3.common.MediaItem
import androidx.media3.common.Player
import androidx.media3.exoplayer.ExoPlayer
import androidx.media3.ui.PlayerView
import com.ux.video.file.filerecovery.utils.Common
import java.io.File
class PlayMediaManager(var context: Context, var mediaFile: File, var playView: PlayerView? = null, var seekBar: SeekBar, var playBtn: ImageView, var onUpdateProgress:(currentStr: String, totalStr: String)-> Unit) {
private lateinit var player: ExoPlayer
private val updateHandler = Handler(Looper.getMainLooper())
init {
initPlayer()
playBtn.setOnClickListener {
if (player.playbackState == Player.STATE_ENDED) {
player.seekTo(0)
}
if (!player.isPlaying) {
player.play()
it.isSelected = true
} else {
player.pause()
it.isSelected = false
}
}
seekBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(
seekBar: SeekBar?,
progress: Int,
fromUser: Boolean
) {
if (fromUser) {
val newPosition = progress * player.duration / 100
player.seekTo(newPosition)
}
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {
}
override fun onStopTrackingTouch(seekBar: SeekBar?) {
}
})
}
private fun initPlayer() {
player = ExoPlayer.Builder(context).build()
playView?.player = player
val mediaItem = MediaItem.fromUri(Uri.fromFile(mediaFile))
player.addListener(object : Player.Listener {
override fun onPlaybackStateChanged(playbackState: Int) {
super.onPlaybackStateChanged(playbackState)
when (playbackState) {
Player.STATE_IDLE -> {
}
Player.STATE_BUFFERING -> {
}
Player.STATE_READY -> {
}
Player.STATE_ENDED -> {
playBtn.isSelected = false
// onPlayEnd()
}
}
}
})
player.setMediaItem(mediaItem)
player.prepare()
startProgressUpdater()
}
private fun startProgressUpdater() {
updateHandler.post(object : Runnable {
override fun run() {
if (player.isPlaying || player.isLoading) {
val pos = player.currentPosition
val dur = player.duration.takeIf { it > 0 } ?: 1L
val progress = (pos * 100 / dur).toInt()
onUpdateProgress(Common.formatDuration(pos),Common.formatDuration(dur))
seekBar.progress = progress
//
// binding.textTimeCurrent.text = Common.formatDuration(pos)
// binding.textTimeTotal.text = Common.formatDuration(dur)
}
updateHandler.postDelayed(this, 500)
}
})
}
}

View File

@ -53,44 +53,52 @@ class VideoPlayActivity : BaseActivity<ActivityVideoPlayBinding>() {
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
intent.getParcelableExtra(KEY_DATA) intent.getParcelableExtra(KEY_DATA)
} }
initPlayer() // initPlayer()
binding.run { binding.run {
myData?.let { resultPhotosFiles-> myData?.let { resultPhotosFiles->
imageBack.setOnClickListener { finish() } imageBack.setOnClickListener { finish() }
playImage.setOnClickListener { resultPhotosFiles.targetFile?.let {
if (player.playbackState == Player.STATE_ENDED) { PlayMediaManager(context = this@VideoPlayActivity, mediaFile = it, playView = playerView,
player.seekTo(0) seekBar = seekBar, playBtn = playImage, onUpdateProgress = { current,total->
} textTimeCurrent.text = current
if (!player.isPlaying) { textTimeTotal.text = total
player.play() } )
it.isSelected = true
} else {
player.pause()
it.isSelected = false
}
}
seekBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(
seekBar: SeekBar?,
progress: Int,
fromUser: Boolean
) {
if (fromUser) {
val newPosition = progress * player.duration / 100
player.seekTo(newPosition)
}
} }
override fun onStartTrackingTouch(seekBar: SeekBar?) { // playImage.setOnClickListener {
// if (player.playbackState == Player.STATE_ENDED) {
} // player.seekTo(0)
// }
override fun onStopTrackingTouch(seekBar: SeekBar?) { // if (!player.isPlaying) {
// player.play()
} // it.isSelected = true
// } else {
}) // player.pause()
startProgressUpdater() // it.isSelected = false
// }
// }
// seekBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
// override fun onProgressChanged(
// seekBar: SeekBar?,
// progress: Int,
// fromUser: Boolean
// ) {
// if (fromUser) {
// val newPosition = progress * player.duration / 100
// player.seekTo(newPosition)
// }
// }
//
// override fun onStartTrackingTouch(seekBar: SeekBar?) {
//
// }
//
// override fun onStopTrackingTouch(seekBar: SeekBar?) {
//
// }
//
// })
// startProgressUpdater()
layoutBottom.tvLeft.run { layoutBottom.tvLeft.run {
text = resources.getString(R.string.delete) text = resources.getString(R.string.delete)
setOnClickListener { setOnClickListener {

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="8dp"/>
<solid android:color="@color/date_dialog_bg_unselected"/>
</shape>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

View File

@ -56,17 +56,57 @@
<ImageView <ImageView
android:id="@+id/image" android:id="@+id/image"
android:layout_gravity="center"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="320dp" /> android:layout_height="match_parent" />
<ImageView <ImageView
android:id="@+id/im_play" android:id="@+id/im_play"
android:layout_width="76dp" android:layout_width="76dp"
android:layout_height="76dp" android:layout_height="76dp"
android:layout_gravity="center" android:layout_gravity="center"
android:src="@drawable/icon_info_play" /> android:src="@drawable/selector_play_button" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="20dp"
android:gravity="center_vertical"
android:orientation="horizontal"
android:id="@+id/layout_seekbar"
android:paddingHorizontal="10dp"
android:layout_gravity="bottom">
<com.ux.video.file.filerecovery.utils.CustomTextView
android:id="@+id/text_time_current"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/main_sub_title"
android:textSize="10sp"
app:fontType="bold"
android:text="00:00" />
<SeekBar
android:id="@+id/seek_bar"
android:layout_width="0dp"
android:layout_height="16dp"
android:layout_weight="1"
android:max="100"
android:progress="0"
android:progressDrawable="@drawable/seekbar_video_play"
android:splitTrack="false"
android:thumb="@drawable/seekbar_thumb" />
<com.ux.video.file.filerecovery.utils.CustomTextView
android:id="@+id/text_time_total"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/main_sub_title"
android:textSize="10sp"
app:fontType="bold"
android:text="00:00" />
</LinearLayout>
</FrameLayout> </FrameLayout>

View File

@ -123,9 +123,8 @@
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
android:src="@drawable/selector_arrow_up_down" /> android:src="@drawable/selector_arrow_up_down" />
</LinearLayout> </LinearLayout>
<ImageView <ImageView
android:id="@+id/im_sort" android:id="@+id/im_search"
android:layout_width="47dp" android:layout_width="47dp"
android:layout_height="16dp" android:layout_height="16dp"
android:layout_alignTop="@id/filter_date_layout" android:layout_alignTop="@id/filter_date_layout"
@ -133,9 +132,17 @@
android:layout_alignParentEnd="true" android:layout_alignParentEnd="true"
android:layout_marginEnd="8dp" android:layout_marginEnd="8dp"
android:paddingHorizontal="16dp" android:paddingHorizontal="16dp"
android:src="@drawable/icon_search" />
<ImageView
android:id="@+id/im_sort"
android:layout_width="47dp"
android:layout_height="16dp"
android:layout_alignTop="@id/filter_date_layout"
android:layout_alignBottom="@id/filter_date_layout"
android:layout_toStartOf="@id/im_search"
android:paddingHorizontal="16dp"
android:src="@drawable/icon_sort" /> android:src="@drawable/icon_sort" />
<RelativeLayout <RelativeLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"

View File

@ -43,7 +43,7 @@
android:textColor="@color/white" android:textColor="@color/white"
android:textSize="10sp" android:textSize="10sp"
app:fontType="bold" app:fontType="bold"
tools:text="00:00" /> android:text="00:00" />
<SeekBar <SeekBar
android:id="@+id/seek_bar" android:id="@+id/seek_bar"
@ -51,7 +51,7 @@
android:layout_height="16dp" android:layout_height="16dp"
android:layout_weight="1" android:layout_weight="1"
android:max="100" android:max="100"
android:progress="30" android:progress="0"
android:progressDrawable="@drawable/seekbar_video_play" android:progressDrawable="@drawable/seekbar_video_play"
android:splitTrack="false" android:splitTrack="false"
android:thumb="@drawable/seekbar_thumb" /> android:thumb="@drawable/seekbar_thumb" />
@ -64,7 +64,7 @@
android:textColor="@color/white" android:textColor="@color/white"
android:textSize="10sp" android:textSize="10sp"
app:fontType="bold" app:fontType="bold"
tools:text="00:00" /> android:text="00:00"/>
</LinearLayout> </LinearLayout>
<include <include

View File

@ -3,6 +3,7 @@
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:id="@+id/constraint_layout"
android:layout_height="64dp"> android:layout_height="64dp">
<ImageView <ImageView