【问题标题】:How to make view visible to only the item clicked in recyclerview android如何使视图仅对recyclerview android中单击的项目可见
【发布时间】:2021-04-27 18:05:27
【问题描述】:

我正在构建一个音乐播放器应用程序。

所有歌曲都显示在回收站视图中。

点击任何歌曲时,我想:

  • 显示表示歌曲当前正在播放的视图(频谱/波)。

这应该只对当前播放的歌曲可见。

RcvLayoutAllSongs.xml

 <TextView
    android:id="@+id/txt_artist_name"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_marginTop="2dp"
    android:textColor="@color/artist_name_color"
    android:textSize="15sp"
    app:layout_constraintBottom_toBottomOf="@+id/constraintLayout2"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintHorizontal_bias="0.0"
    android:layout_marginEnd="30dp"
    app:layout_constraintStart_toStartOf="@+id/txt_song_name"
    app:layout_constraintTop_toBottomOf="@+id/txt_song_name"
    app:layout_constraintVertical_bias="0.0" />

<es.claucookie.miniequalizerlibrary.EqualizerView
    android:id="@+id/equalizer_view"
    android:layout_width="30dp"
    android:layout_height="30dp"
    app:animDuration="3500"
    android:visibility="gone"
    app:foregroundColor="@color/bottom_music_stroke"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintHorizontal_bias="0.0"
    app:layout_constraintStart_toEndOf="@+id/txt_song_name"
    app:layout_constraintTop_toTopOf="parent" />

我想做的就是:-

使 equalizer_view 仅对被点击的项目可见,如果可能的话,更改被点击项目的 textview 的颜色

SongsAdapter

 override fun onBindViewHolder(holder: AllSongsViewHolder, position: Int) {
    val song = songs[position]
    with(holder) {
        with(songs[position]) {
            binding.txtSongName.text = song.title
            binding.txtArtistName.text = song.subtitle
            //on click
            binding.rootLyt.setOnClickListener {
                onItemClickListener?.let { click ->
                    click(song)
                    //here I will handle click to display the view on only selected item
                }
            }     
        }
    }
}
private var onItemClickListener: ((Songs) -> Unit)? = null
fun setOnItemClickListener(listener: (Songs) -> Unit) {
    onItemClickListener = listener
}
override fun getItemCount() = songs.size

这种方法的问题是我还想在歌曲暂停时使视图不可见..这是在片段中处理的......不是适配器

歌曲片段

 override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
 super.onViewCreated(view, savedInstanceState)

 binding.pauseView.setOnClickListener {
        //this is where I pause the song when the song is clicked from the adapter, I 
        also want to make the wave/view invisible from the adapter but don't know how
        mainViewModel.pauseSong
    }

  }

【问题讨论】:

  • 点击item时创建界面,然后在recycler视图中调用removeDataSetChanged(position)

标签: android xml android-studio kotlin


【解决方案1】:

onBindViewHolder 中,检查该项目是否是当前正在播放的歌曲,并设置相应的样式(字体颜色、波形图等)。

让您的点击监听器调用一些 setCurrentSong() 函数来更新当前正在播放的歌曲,然后调用 notifyDataSetChanged 以使 RecyclerView 更新项目(这将再次调用 onBindViewHolder)。

这里的好处是你也可以从其他地方调用这个函数,比如在第一次设置片段时,所以你不需要点击来设置当前的歌曲状态。只需保留对您的Adapter 的引用并致电adapter.setCurrentSong - 与ViewModels 等一起玩得很好!将逻辑排除在 UI 之外


您可以在暂停时采用相同的方法 - 在适配器上添加 setPaused(Boolean) 函数。当您暂停或开始播放时,调用该函数,该函数设置paused 状态并调用notifyDataSetChanged()。在决定是否显示图像时,让您的onBindViewHolder 检查是否为paused

如果您愿意,也可以使用带有 setter 的属性:

var paused: Boolean = false
set(value) {
    field = value
    notifyDataSetChanged()
}

Delegates.observable - 基本上你只需要确保RecyclerView 在值发生变化时收到需要更新的通知。


哦,如果 mainViewModel 实际上包含诸如玩家状态之类的东西,并且您有诸如 LiveData 之类的东西,它拥有一个 paused 状态,一个拥有 currentSongId 或其他的东西,那么您通常会连接它像这样:

viewModel.currentSong -> observer -> calls adapter.setCurrentSong
recyclerView.item -> click -> calls viewModel.setCurrentSong

这样,UI (RecyclerView) 会响应虚拟机所描述的状态变化。当它推送一个事件(如歌曲更改)时,它只是在视图模型上设置它,因为那是保存状态的地方。当该状态发生变化时,观察者将运行并更新 UI。这就像一种迂回的做事方式,而不是直接更新自己的RecyclerView,但是一旦你了解它,它就会更干净,更容易推理!您无需担心事件来自何处,因为它始终来自 VM

【讨论】:

  • 谢谢。它工作,但我有一个问题.... 1. 当我点击一个项目时,equalizer_view 对当前正在播放的歌曲可见(因为它应该)但是当我向下滚动时.. 位置 13 的项目也有相同的均衡器视图...例如,我在位置 0 播放歌曲,位置 13 的歌曲也获得相同的均衡器视图(可见)和后续项目..
  • 这里是当前行为的链接ibb.co/dD5YHPL
  • 在没有看到代码的情况下无法确定,但看起来您的 onBindViewHolder 代码设置了当前歌曲的样式,但它没有删除它不是的时候。那些ViewHolders 被重复使用(回收!)来展示项目,所以你需要重新设置每一个。您的代码需要使用textColor = if (isCurrentSong) WHITE else BLUEimageView.visibility = if (isCurrentSong) VISIBLE else INVISIBLE 等,因此它使用一种或另一种样式进行设置。顺便说一句,看起来不错!
  • 天才仙人掌。谢谢你很好用!!我如何通过电子邮件/推特与您联系??
  • 哦,我不提供个人信息,对不起!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多