Reputation: 258
I'm using ListAdapter to show my device music on the screen. From option menu user can change the tracks order. When user changes the track order the recycler view shows updated list but also changes its scroll position.
Can you help me to avoid changing scroll position?
Here is my code:
Fragment with recycler view.
class TabSongsFrg : Fragment() {
private lateinit var binding: FragmentTabSongsBinding
private lateinit var viewModelFactory: TabSongsViewModelFactory
private lateinit var viewModel: TabSongsViewModel
private lateinit var tabSongsRva: TabSongsRva
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
try {
if (!this::binding.isInitialized) {
binding = FragmentTabSongsBinding.inflate(inflater)
val application = requireNotNull(activity).application
viewModelFactory = TabSongsViewModelFactory(application, context)
viewModel =
ViewModelProvider(this, viewModelFactory)[TabSongsViewModel::class.java]
binding.lifecycleOwner = this
binding.viewModel = viewModel
tabSongsRva =
TabSongsRva(context, TabSongsRva.OnClickListener { objects ->
})
binding.tabSongsRecyclerView.adapter = tabSongsRva
}
} catch (e: Exception) {
firebaseCrashlytics.recordException(e)
}
return binding.root
}
private fun prepareToScanMedia() {
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (context.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
context.checkPermission()
return
}
}
val tracksInfo = getAllTracks()
viewModel.setTracksList(tracksInfo)
} catch (e: Exception) {
firebaseCrashlytics.recordException(e)
}
}
fun getAllTracks(): ArrayList<TrackInfo> {
val allTracksInfo: ArrayList<TrackInfo> = ArrayList()
try {
val selection = MediaStore.Audio.Media.IS_MUSIC + " != 0"
val sortOrder = getTracksSortOrder()
val music = context.contentResolver.query(
EXTERNAL_CONTENT_URI,
projectionMedia,
selection,
null,
sortOrder
)
while (music!!.moveToNext()) {
val trackInfo = TrackInfo()
trackInfo.artist = music.getString(0)
trackInfo.title = music.getString(1)
trackInfo.data = music.getString(2)
trackInfo.displayName = music.getString(3)
trackInfo.duration = music.getLong(4)
trackInfo.album = music.getString(5)
trackInfo.size = music.getLong(6)
trackInfo.albumId = music.getInt(7)
trackInfo.artistId = music.getInt(8)
trackInfo.trackId = music.getInt(9)
trackInfo.year = music.getInt(10)
trackInfo.mimeType = music.getString(11)
trackInfo.photoUri = getTrackAlbumArt(trackInfo.albumId)
allTracksInfo.add(trackInfo)
}
} catch (e: Exception) {
firebaseCrashlytics.recordException(e)
}
return allTracksInfo
}
}
ViewModel class
class TabSongsViewModel(app: Application, private val context: PrepareActivity) :
AndroidViewModel(app) {
private val _tracksInfo = MutableLiveData<ArrayList<TrackInfo>>()
val tracksInfo: LiveData<ArrayList<TrackInfo>>
get() = _tracksInfo
fun setTracksList(tracksInfo: ArrayList<TrackInfo>) {
try {
_tracksInfo.value = tracksInfo
} catch (e: Exception) {
firebaseCrashlytics.recordException(e)
}
}
}
Adapter
class TabSongsRva(
private val onClickListener: OnClickListener
) :
ListAdapter<TrackInfo, TabSongsRva.MarsPropertyViewHolder>
(DiffCallback) {
class MarsPropertyViewHolder(
private var bindingGrid: TrackGridCellBinding
) :
RecyclerView.ViewHolder(bindingGrid.root) {
fun bind(trackInfo: TrackInfo) {
bindingGrid.trackInfo = trackInfo
bindingGrid.executePendingBindings()
}
}
companion object DiffCallback : DiffUtil.ItemCallback<TrackInfo>() {
override fun areItemsTheSame(oldItem: TrackInfo, newItem:
TrackInfo): Boolean {
return oldItem.trackId == newItem.trackId
}
override fun areContentsTheSame(oldItem: TrackInfo, newItem:
TrackInfo): Boolean {
return oldItem.trackId == newItem.trackId
}
}
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): MarsPropertyViewHolder {
return MarsPropertyViewHolder(
TrackGridCellBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
)
}
override fun onBindViewHolder(holder: MarsPropertyViewHolder,
position: Int) {
val trackInfo = getItem(position)
holder.itemView.setOnClickListener {
disableView(holder.itemView)
val objects = arrayOf<Any>(position, trackInfo)
onClickListener.onClick(objects)
}
holder.bind(trackInfo)
}
class OnClickListener(val clickListener: (objects: Array<Any>) ->
Unit) {
fun onClick(objects: Array<Any>) = clickListener(objects)
}
}
Layout File
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/tabSongsRecyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layoutAnimation="@anim/layout_fall_down"
android:paddingLeft="3dp"
android:paddingRight="3dp"
android:scrollbarSize="4dp"
android:scrollbarThumbVertical="@drawable/custom_scrollbar"
android:scrollbars="vertical"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
app:tabSongsTracksList="@{viewModel.tracksInfo}"
tools:listitem="@layout/track_list_cell" />
Upvotes: 1
Views: 122