오디션 지원자 콘텐츠 재생/정지 기능 추가
This commit is contained in:
parent
92b201a6fa
commit
b0a97ab941
|
@ -81,6 +81,7 @@ dependencies {
|
|||
implementation "androidx.media:media:1.7.0"
|
||||
implementation 'androidx.core:core-ktx:1.13.1'
|
||||
implementation 'androidx.appcompat:appcompat:1.7.0'
|
||||
implementation 'androidx.recyclerview:recyclerview:1.3.2'
|
||||
implementation 'com.google.android.material:material:1.12.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.2.0'
|
||||
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
|
||||
|
|
|
@ -12,10 +12,11 @@ import kr.co.vividnext.sodalive.databinding.ItemAuditionApplicantBinding
|
|||
|
||||
class AuditionApplicantListAdapter(
|
||||
private val onClickVote: (Int) -> Unit,
|
||||
private val onClickPlayOrPause: (Int) -> Unit
|
||||
private val onClickPlayOrPause: (Int, Long, String) -> Unit
|
||||
) : ListAdapter<GetAuditionRoleApplicantItem, AuditionApplicantListAdapter.ViewHolder>(DiffCallback()) {
|
||||
|
||||
private var currentPlayingIndex: Int = -1
|
||||
private var isPlaying: Boolean = false
|
||||
|
||||
class DiffCallback : DiffUtil.ItemCallback<GetAuditionRoleApplicantItem>() {
|
||||
override fun areItemsTheSame(
|
||||
|
@ -29,16 +30,18 @@ class AuditionApplicantListAdapter(
|
|||
oldItem: GetAuditionRoleApplicantItem,
|
||||
newItem: GetAuditionRoleApplicantItem
|
||||
): Boolean {
|
||||
return oldItem == newItem && oldItem.voteCount == newItem.voteCount
|
||||
return oldItem == newItem
|
||||
}
|
||||
}
|
||||
|
||||
inner class ViewHolder(
|
||||
private val binding: ItemAuditionApplicantBinding
|
||||
) : RecyclerView.ViewHolder(binding.root) {
|
||||
fun bind(item: GetAuditionRoleApplicantItem, position: Int) {
|
||||
binding.ivVote.setOnClickListener { onClickVote(position) }
|
||||
binding.ivPlayOrPause.setOnClickListener { onClickPlayOrPause(position) }
|
||||
fun bind(item: GetAuditionRoleApplicantItem) {
|
||||
binding.ivVote.setOnClickListener { onClickVote(bindingAdapterPosition) }
|
||||
binding.ivPlayOrPause.setOnClickListener {
|
||||
onClickPlayOrPause(bindingAdapterPosition, item.applicantId, item.voiceUrl)
|
||||
}
|
||||
|
||||
binding.tvNickname.text = item.nickname
|
||||
binding.tvCountVote.text = item.voteCount.toString()
|
||||
|
@ -49,7 +52,7 @@ class AuditionApplicantListAdapter(
|
|||
}
|
||||
|
||||
binding.ivPlayOrPause.setImageResource(
|
||||
if (position == currentPlayingIndex) {
|
||||
if (bindingAdapterPosition == currentPlayingIndex && isPlaying) {
|
||||
R.drawable.ic_audition_pause
|
||||
} else {
|
||||
R.drawable.ic_audition_play
|
||||
|
@ -67,10 +70,12 @@ class AuditionApplicantListAdapter(
|
|||
)
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
holder.bind(getItem(position), position)
|
||||
holder.bind(getItem(position))
|
||||
}
|
||||
|
||||
fun updatePlayingIndex(newIndex: Int) {
|
||||
fun updatePlayingIndex(newIndex: Int, isPlaying: Boolean) {
|
||||
this.isPlaying = isPlaying
|
||||
|
||||
val previousIndex = currentPlayingIndex
|
||||
currentPlayingIndex = newIndex
|
||||
notifyItemChanged(previousIndex)
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
package kr.co.vividnext.sodalive.audition.applicant
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.media.AudioAttributes
|
||||
import android.media.MediaPlayer
|
||||
import android.net.Uri
|
||||
import android.widget.Toast
|
||||
import com.orhanobut.logger.Logger
|
||||
import kr.co.vividnext.sodalive.audio_content.AudioContentPlayService
|
||||
import kr.co.vividnext.sodalive.audio_content.player.AudioContentPlayerService
|
||||
import java.io.IOException
|
||||
|
||||
class AuditionApplicantMediaPlayerManager(
|
||||
private val context: Context,
|
||||
private val updateUI: (Int, Boolean) -> Unit
|
||||
) {
|
||||
private var mediaPlayer: MediaPlayer? = null
|
||||
private var currentPlayingApplicantId: Long = -1
|
||||
private var currentPlayingPosition: Int = -1
|
||||
|
||||
fun pauseContent() {
|
||||
mediaPlayer?.pause()
|
||||
updateUI(currentPlayingPosition, false)
|
||||
}
|
||||
|
||||
private fun resumeContent() {
|
||||
pauseAudioContentService()
|
||||
mediaPlayer?.start()
|
||||
updateUI(currentPlayingPosition, true)
|
||||
}
|
||||
|
||||
fun stopContent() {
|
||||
mediaPlayer?.let {
|
||||
it.stop()
|
||||
it.release()
|
||||
mediaPlayer = null
|
||||
}
|
||||
currentPlayingApplicantId = -1
|
||||
currentPlayingPosition = -1
|
||||
updateUI(currentPlayingPosition, false)
|
||||
}
|
||||
|
||||
fun toggleContent(position: Int, applicantId: Long, voiceUrl: String) {
|
||||
if (currentPlayingApplicantId == applicantId && currentPlayingPosition == position) {
|
||||
if (mediaPlayer?.isPlaying == true) {
|
||||
pauseContent()
|
||||
} else {
|
||||
resumeContent()
|
||||
}
|
||||
} else {
|
||||
playContent(position, applicantId, voiceUrl)
|
||||
}
|
||||
}
|
||||
|
||||
private fun playContent(position: Int, applicantId: Long, voiceUrl: String) {
|
||||
pauseAudioContentService()
|
||||
stopContent()
|
||||
|
||||
currentPlayingPosition = position
|
||||
currentPlayingApplicantId = applicantId
|
||||
|
||||
mediaPlayer = MediaPlayer().apply {
|
||||
setAudioAttributes(
|
||||
AudioAttributes.Builder()
|
||||
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
|
||||
.setUsage(AudioAttributes.USAGE_MEDIA)
|
||||
.build()
|
||||
)
|
||||
|
||||
try {
|
||||
setDataSource(context, Uri.parse(voiceUrl))
|
||||
prepareAsync() // 비동기적으로 준비
|
||||
setOnPreparedListener {
|
||||
start()
|
||||
updateUI(currentPlayingPosition, true)
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
Toast.makeText(context, "콘텐츠를 재생하지 못했습니다.\n다시 시도해 주세요", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
setOnCompletionListener {
|
||||
updateUI(currentPlayingPosition, false)
|
||||
currentPlayingApplicantId = -1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun pauseAudioContentService() {
|
||||
context.startService(
|
||||
Intent(
|
||||
context,
|
||||
AudioContentPlayService::class.java
|
||||
).apply {
|
||||
action = AudioContentPlayService.MusicAction.PAUSE.name
|
||||
}
|
||||
)
|
||||
|
||||
context.startService(
|
||||
Intent(context, AudioContentPlayerService::class.java).apply {
|
||||
action = "STOP_SERVICE"
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
|
@ -16,6 +16,7 @@ import coil.transform.RoundedCornersTransformation
|
|||
import kr.co.vividnext.sodalive.R
|
||||
import kr.co.vividnext.sodalive.audition.applicant.ApplicationMethodDialog
|
||||
import kr.co.vividnext.sodalive.audition.applicant.AuditionApplicantListAdapter
|
||||
import kr.co.vividnext.sodalive.audition.applicant.AuditionApplicantMediaPlayerManager
|
||||
import kr.co.vividnext.sodalive.audition.applicant.AuditionApplyDialogFragment
|
||||
import kr.co.vividnext.sodalive.base.BaseActivity
|
||||
import kr.co.vividnext.sodalive.base.SodaDialog
|
||||
|
@ -72,6 +73,8 @@ class AuditionRoleDetailActivity : BaseActivity<ActivityAuditionRoleDetailBindin
|
|||
}
|
||||
}
|
||||
|
||||
private lateinit var mediaPlayerManager: AuditionApplicantMediaPlayerManager
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
auditionRoleId = intent.getLongExtra(Constants.EXTRA_AUDITION_ROLE_ID, 0)
|
||||
|
||||
|
@ -87,10 +90,26 @@ class AuditionRoleDetailActivity : BaseActivity<ActivityAuditionRoleDetailBindin
|
|||
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
mediaPlayerManager = AuditionApplicantMediaPlayerManager(
|
||||
this
|
||||
) { position, isPlaying ->
|
||||
adapter.updatePlayingIndex(position, isPlaying)
|
||||
}
|
||||
|
||||
bindData()
|
||||
viewModel.getAuditionRoleDetail(auditionRoleId = auditionRoleId)
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
mediaPlayerManager.pauseContent()
|
||||
super.onPause()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
mediaPlayerManager.stopContent()
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
override fun setupView() {
|
||||
loadingDialog = LoadingDialog(this, layoutInflater)
|
||||
binding.toolbar.tvBack.setOnClickListener { finish() }
|
||||
|
@ -133,15 +152,19 @@ class AuditionRoleDetailActivity : BaseActivity<ActivityAuditionRoleDetailBindin
|
|||
}
|
||||
|
||||
binding.tvSortNewest.setOnClickListener {
|
||||
mediaPlayerManager.stopContent()
|
||||
viewModel.setSortType(AuditionRoleDetailViewModel.AuditionApplicantSortType.NEWEST)
|
||||
}
|
||||
|
||||
binding.tvSortLikes.setOnClickListener {
|
||||
mediaPlayerManager.stopContent()
|
||||
viewModel.setSortType(AuditionRoleDetailViewModel.AuditionApplicantSortType.LIKES)
|
||||
}
|
||||
|
||||
adapter = AuditionApplicantListAdapter(
|
||||
onClickPlayOrPause = {},
|
||||
onClickPlayOrPause = { position, applicantId, voiceUrl ->
|
||||
mediaPlayerManager.toggleContent(position, applicantId, voiceUrl)
|
||||
},
|
||||
onClickVote = {
|
||||
if (isShowNotifyVote) {
|
||||
SodaDialog(
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingHorizontal="13.3dp"
|
||||
android:paddingTop="18.7dp"
|
||||
tools:background="@color/black">
|
||||
|
||||
<ImageView
|
||||
|
|
Loading…
Reference in New Issue