Skip to content
Snippets Groups Projects
Commit 3d5964eb authored by Nicolas Pomepuy's avatar Nicolas Pomepuy Committed by Geoffrey Métais
Browse files

Start of refactor of TV media Adapter

parent 3d77150d
No related branches found
No related tags found
1 merge request!108Tv media browser refactor
Showing with 374 additions and 99 deletions
......@@ -12,10 +12,26 @@
<import type="org.videolan.medialibrary.media.MediaLibraryItem" />
<variable
name="progress"
type="int" />
<variable
name="alignMode"
name="max"
type="int" />
<variable
name="badge"
type="String" />
<variable
name="description"
type="String" />
<variable
name="seen"
type="long" />
<variable
name="item"
......@@ -25,33 +41,45 @@
name="cover"
type="android.graphics.drawable.BitmapDrawable" />
<variable
name="bgColor"
type="int" />
name="isSquare"
type="Boolean" />
<variable
name="holder"
type="org.videolan.vlc.gui.audio.AudioBrowserAdapter.MediaItemTVViewHolder" />
type="org.videolan.vlc.gui.tv.TvItemAdapter.MediaItemTVViewHolder" />
</data>
<org.videolan.vlc.gui.tv.FocusableConstraintLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/tv_card_background"
android:id="@+id/container"
android:clickable="true"
android:focusable="true"
android:longClickable="true"
android:paddingBottom="@dimen/kl_small"
android:minHeight="@dimen/audio_browser_item_size"
android:onClick="@{holder::onClick}"
android:onLongClick="@{holder::onLongClick}"
vlc:elevation="1dp"
android:stateListAnimator="@animator/tv_recyclerview_item_pop">
android:paddingBottom="@dimen/kl_small"
android:stateListAnimator="@animator/tv_recyclerview_item_pop"
vlc:elevation="1dp">
<!-- Image loading is handled by org.videolan.vlc.gui.helpers.ImageLoader.loadImage() -->
<ImageView
android:id="@+id/ml_item_seen"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_seen_normal"
android:visibility="@{seen == 0L ? View.GONE : View.VISIBLE}"
vlc:layout_constraintRight_toRightOf="@+id/ml_item_thumbnail"
vlc:layout_constraintTop_toTopOf="@+id/ml_item_thumbnail" />
<ImageView
android:id="@+id/media_cover"
android:layout_width="match_parent"
......@@ -59,15 +87,43 @@
android:layout_gravity="center"
android:background="@color/lb_details_overview_bg_color"
tools:srcCompat="@drawable/ic_album_big"
vlc:layout_constraintDimensionRatio="1"
vlc:constraintRatio="@{isSquare}"
vlc:layout_constraintEnd_toEndOf="parent"
vlc:layout_constraintStart_toStartOf="parent"
vlc:layout_constraintTop_toTopOf="parent"
vlc:media="@{item}" />
<!-- TextView must be set to singleLine
see https://code.google.com/p/android/issues/detail?id=33868 -->
<TextView
android:id="@+id/badgeTV"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:layout_marginBottom="8dp"
android:padding="@dimen/kl_half"
android:textSize="12sp"
tools:text="4K"
android:text="@{badge}"
android:background="@drawable/rounded_corners"
vlc:layout_constraintBottom_toBottomOf="@id/media_cover"
vlc:layout_constraintEnd_toEndOf="parent" />
<ProgressBar
android:id="@+id/progressBar"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:layout_width="0dp"
android:layout_height="2dp"
android:background="@color/transparent"
android:indeterminate="false"
android:max="@{max}"
android:progress="@{progress}"
android:progressDrawable="@drawable/gridview_progressbar"
android:visibility="@{progress > 0 ? View.VISIBLE : View.GONE}"
vlc:layout_constraintEnd_toEndOf="parent"
vlc:layout_constraintStart_toStartOf="parent"
vlc:layout_constraintTop_toBottomOf="@id/media_cover" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/title"
android:layout_width="0dp"
......@@ -75,15 +131,15 @@
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:ellipsize="end"
android:gravity="center_vertical"
android:maxLines="2"
android:textSize="12sp"
tools:text="Title"
vlc:alignMode="@{alignMode}"
vlc:asyncText="@{item.title}"
android:maxLines="2"
android:ellipsize="end"
vlc:layout_constraintEnd_toEndOf="parent"
vlc:layout_constraintStart_toStartOf="parent"
vlc:layout_constraintTop_toBottomOf="@+id/media_cover"
vlc:layout_constraintTop_toBottomOf="@+id/progressBar"
vlc:placeholder="@{item}" />
<androidx.appcompat.widget.AppCompatTextView
......@@ -92,11 +148,12 @@
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:maxLines="2"
android:ellipsize="end"
android:maxLines="2"
android:textAppearance="@style/VLCImageCardViewContentStyleTextAppearance"
android:textSize="11sp"
tools:text="@string/add_custom_path_description"
vlc:asyncText="@{item.description}"
vlc:asyncText="@{description}"
vlc:layout_constraintBottom_toBottomOf="parent"
vlc:layout_constraintEnd_toEndOf="parent"
vlc:layout_constraintStart_toStartOf="parent"
......
......@@ -75,18 +75,18 @@
<org.videolan.vlc.gui.tv.FocusableRecyclerView
android:id="@+id/list"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_height="0dp"
android:clipToPadding="false"
android:focusable="false"
android:focusableInTouchMode="false"
android:paddingLeft="16dp"
android:paddingTop="62dp"
android:paddingRight="16dp"
android:paddingLeft="@dimen/tv_overscan_horizontal"
android:paddingRight="@dimen/tv_overscan_horizontal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:listitem="@layout/audio_browser_tv_item">
tools:listitem="@layout/media_browser_tv_item">
</org.videolan.vlc.gui.tv.FocusableRecyclerView>
......
<?xml version="1.0" encoding="utf-8"?>
<resources>
<integer name="tv_songs_col_count">5</integer>
<integer name="tv_videos_col_count">2</integer>
</resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<integer name="tv_songs_col_count">6</integer>
<integer name="tv_videos_col_count">3</integer>
</resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<integer name="tv_songs_col_count">7</integer>
<integer name="tv_videos_col_count">4</integer>
</resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<integer name="tv_songs_col_count">4</integer>
<integer name="tv_videos_col_count">2</integer>
</resources>
\ No newline at end of file
......@@ -47,7 +47,6 @@ import org.videolan.tools.MultiSelectHelper
import org.videolan.vlc.R
import org.videolan.vlc.databinding.AudioBrowserCardItemBinding
import org.videolan.vlc.databinding.AudioBrowserItemBinding
import org.videolan.vlc.databinding.AudioBrowserTvItemBinding
import org.videolan.vlc.gui.helpers.SelectorViewHolder
import org.videolan.vlc.gui.helpers.getAudioIconDrawable
import org.videolan.vlc.gui.tv.FocusableRecyclerView
......@@ -64,7 +63,6 @@ class AudioBrowserAdapter @JvmOverloads constructor(private val mType: Int, priv
private var itemSize = -1
val multiSelectHelper: MultiSelectHelper<MediaLibraryItem> = MultiSelectHelper(this, UPDATE_SELECTION)
private val mDefaultCover: BitmapDrawable?
private var isTV = false
var focusNext = -1
private var focusListener: FocusableRecyclerView.FocusListener? = null
......@@ -91,12 +89,9 @@ class AudioBrowserAdapter @JvmOverloads constructor(private val mType: Int, priv
return if (mType == MediaLibraryItem.TYPE_PLAYLIST) {
val binding = AudioBrowserCardItemBinding.inflate(inflater, parent, false)
MediaItemCardViewHolder(binding) as AbstractMediaItemViewHolder<ViewDataBinding>
} else if (!isTV) {
} else {
val binding = AudioBrowserItemBinding.inflate(inflater, parent, false)
MediaItemViewHolder(binding) as AbstractMediaItemViewHolder<ViewDataBinding>
} else {
val binding = AudioBrowserTvItemBinding.inflate(inflater, parent, false)
MediaItemTVViewHolder(binding) as AbstractMediaItemViewHolder<ViewDataBinding>
}
}
......@@ -184,9 +179,6 @@ class AudioBrowserAdapter @JvmOverloads constructor(private val mType: Int, priv
mListEventsHandler!!.onRemove(position, item!!)
}
fun setTV(TV: Boolean) {
isTV = TV
}
fun setOnFocusChangeListener(focusListener: FocusableRecyclerView.FocusListener?) {
this.focusListener = focusListener
......@@ -284,56 +276,6 @@ class AudioBrowserAdapter @JvmOverloads constructor(private val mType: Int, priv
}
inner class MediaItemTVViewHolder @TargetApi(Build.VERSION_CODES.M)
internal constructor(binding: AudioBrowserTvItemBinding) : AbstractMediaItemViewHolder<AudioBrowserTvItemBinding>(binding), View.OnFocusChangeListener {
init {
binding.holder = this
if (mDefaultCover != null) binding.cover = mDefaultCover
if (AndroidUtil.isMarshMallowOrLater)
itemView.setOnContextClickListener { v ->
onMoreClick(v)
true
}
binding.container.layoutParams.width = itemSize
binding.container.onFocusChangeListener = View.OnFocusChangeListener { _, hasFocus ->
if (hasFocus) {
var newWidth = (itemSize * 1.1).toInt()
if (newWidth % 2 == 1) {
newWidth--
}
val scale = newWidth.toFloat() / itemSize
binding.container.animate().scaleX(scale).scaleY(scale).translationZ(scale)
mIEventsHandler.onItemFocused(binding.root, getItem(layoutPosition)!!)
if (focusListener != null) {
focusListener!!.onFocusChanged(layoutPosition)
}
} else {
binding.container.animate().scaleX(1f).scaleY(1f).translationZ(1f)
}
}
binding.container.clipToOutline = true
}
override fun recycle() {
if (mDefaultCover != null) binding.cover = mDefaultCover
binding.title.text = ""
binding.subtitle.text = ""
}
override fun setItem(item: MediaLibraryItem?) {
binding.item = item
}
@ObsoleteCoroutinesApi
override fun setCoverlay(selected: Boolean) {
}
}
abstract inner class AbstractMediaItemViewHolder<T : ViewDataBinding> @TargetApi(Build.VERSION_CODES.M)
internal constructor(binding: T) : SelectorViewHolder<T>(binding), View.OnFocusChangeListener {
......
......@@ -23,7 +23,7 @@ import org.videolan.medialibrary.media.MediaWrapper
import org.videolan.vlc.BR
import org.videolan.vlc.R
import org.videolan.vlc.VLCApplication
import org.videolan.vlc.databinding.AudioBrowserTvItemBinding
import org.videolan.vlc.databinding.MediaBrowserTvItemBinding
import org.videolan.vlc.gui.tv.TvUtil
import org.videolan.vlc.util.AppScope
import org.videolan.vlc.util.HttpImageLoader
......@@ -101,7 +101,7 @@ fun placeHolderView(v: View, item: MediaLibraryItem?) {
}
fun isForTV(binding: ViewDataBinding?) = (binding is AudioBrowserTvItemBinding)
fun isForTV(binding: ViewDataBinding?) = (binding is MediaBrowserTvItemBinding)
@MainThread
@BindingAdapter("placeholderImage")
......
......@@ -4,7 +4,6 @@ import android.app.Activity
import android.content.Context
import android.util.AttributeSet
import androidx.recyclerview.widget.RecyclerView
import org.videolan.vlc.gui.audio.AudioBrowserAdapter
import org.videolan.vlc.util.getScreenHeight
/**
......@@ -52,9 +51,9 @@ class FocusableRecyclerView : RecyclerView {
}
}
override fun setAdapter(adapter: RecyclerView.Adapter<*>?) {
override fun setAdapter(adapter: Adapter<*>?) {
if (adapter is AudioBrowserAdapter) {
if (adapter is TvItemAdapter) {
adapter.setOnFocusChangeListener(focusListener)
}
......
package org.videolan.vlc.gui.tv
import android.annotation.TargetApi
import android.content.Context
import android.graphics.drawable.BitmapDrawable
import android.os.Build
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.ViewDataBinding
import androidx.fragment.app.Fragment
import androidx.paging.PagedListAdapter
import androidx.recyclerview.widget.DiffUtil
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.ObsoleteCoroutinesApi
import org.videolan.libvlc.util.AndroidUtil
import org.videolan.medialibrary.Tools
import org.videolan.medialibrary.media.MediaLibraryItem
import org.videolan.medialibrary.media.MediaWrapper
import org.videolan.vlc.databinding.MediaBrowserTvItemBinding
import org.videolan.vlc.gui.helpers.SelectorViewHolder
import org.videolan.vlc.gui.helpers.getAudioIconDrawable
import org.videolan.vlc.gui.view.FastScroller
import org.videolan.vlc.interfaces.IEventsHandler
import org.videolan.vlc.util.UPDATE_SELECTION
import org.videolan.vlc.util.Util
import org.videolan.vlc.util.generateResolutionClass
@ExperimentalCoroutinesApi
@ObsoleteCoroutinesApi
class TvItemAdapter(type: Int, private val eventsHandler: IEventsHandler, var itemSize: Int) : PagedListAdapter<MediaLibraryItem, TvItemAdapter.AbstractMediaItemViewHolder<ViewDataBinding>>(TvItemAdapter.DIFF_CALLBACK), FastScroller.SeparatedAdapter {
var focusNext = -1
private val mDefaultCover: BitmapDrawable?
private var focusListener: FocusableRecyclerView.FocusListener? = null
init {
var ctx: Context? = null
if (eventsHandler is Context)
ctx = eventsHandler
else if (eventsHandler is Fragment) ctx = (eventsHandler as Fragment).context
mDefaultCover = if (ctx != null) getAudioIconDrawable(ctx, type) else null
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AbstractMediaItemViewHolder<ViewDataBinding> {
val inflater = parent.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
val binding = MediaBrowserTvItemBinding.inflate(inflater, parent, false)
return MediaItemTVViewHolder(binding) as AbstractMediaItemViewHolder<ViewDataBinding>
}
override fun onBindViewHolder(holder: AbstractMediaItemViewHolder<ViewDataBinding>, position: Int) {
if (position >= itemCount) return
val item = getItem(position)
holder.setItem(item)
holder.binding.executePendingBindings()
if (position == focusNext) {
holder.binding.root.requestFocus()
focusNext = -1
}
}
override fun onBindViewHolder(holder: AbstractMediaItemViewHolder<ViewDataBinding>, position: Int, payloads: List<Any>) {
if (Util.isListEmpty(payloads))
onBindViewHolder(holder, position)
else {
val payload = payloads[0]
if (payload is MediaLibraryItem) {
val isSelected = payload.hasStateFlags(MediaLibraryItem.FLAG_SELECTED)
holder.setCoverlay(isSelected)
holder.selectView(isSelected)
} else if (payload is Int) {
if (payload == UPDATE_SELECTION) {
}
}
}
}
override fun hasSections(): Boolean {
return true
}
override fun getItem(position: Int): MediaLibraryItem? {
return super.getItem(position)
}
fun setOnFocusChangeListener(focusListener: FocusableRecyclerView.FocusListener?) {
this.focusListener = focusListener
}
companion object {
private val TAG = "VLC/AudioBrowserAdapter"
private const val UPDATE_PAYLOAD = 1
/**
* Awful hack to workaround the [PagedListAdapter] not keeping track of notifyItemMoved operations
*/
private var preventNextAnim: Boolean = false
private val DIFF_CALLBACK = object : DiffUtil.ItemCallback<MediaLibraryItem>() {
override fun areItemsTheSame(
oldMedia: MediaLibraryItem, newMedia: MediaLibraryItem): Boolean {
return if (preventNextAnim) {
true
} else oldMedia === newMedia || oldMedia.itemType == newMedia.itemType && oldMedia.equals(newMedia)
}
override fun areContentsTheSame(
oldMedia: MediaLibraryItem, newMedia: MediaLibraryItem): Boolean {
return false
}
override fun getChangePayload(oldItem: MediaLibraryItem, newItem: MediaLibraryItem): Any? {
preventNextAnim = false
return UPDATE_PAYLOAD
}
}
}
abstract inner class AbstractMediaItemViewHolder<T : ViewDataBinding> @TargetApi(Build.VERSION_CODES.M)
internal constructor(binding: T) : SelectorViewHolder<T>(binding), View.OnFocusChangeListener {
fun onClick(v: View) {
val item = getItem(layoutPosition)
if (item != null) eventsHandler.onClick(v, layoutPosition, item)
}
fun onMoreClick(v: View) {
val item = getItem(layoutPosition)
if (item != null) eventsHandler.onCtxClick(v, layoutPosition, item)
}
fun onLongClick(view: View): Boolean {
val item = getItem(layoutPosition)
return item != null && eventsHandler.onLongClick(view, layoutPosition, item)
}
fun onImageClick(v: View) {
val item = getItem(layoutPosition)
if (item != null) eventsHandler.onImageClick(v, layoutPosition, item)
}
fun onMainActionClick(v: View) {
val item = getItem(layoutPosition)
if (item != null) eventsHandler.onMainActionClick(v, layoutPosition, item)
}
abstract fun setItem(item: MediaLibraryItem?)
abstract fun recycle()
abstract fun setCoverlay(selected: Boolean)
}
inner class MediaItemTVViewHolder @TargetApi(Build.VERSION_CODES.M)
internal constructor(binding: MediaBrowserTvItemBinding) : AbstractMediaItemViewHolder<MediaBrowserTvItemBinding>(binding), View.OnFocusChangeListener {
init {
binding.holder = this
if (mDefaultCover != null) binding.cover = mDefaultCover
if (AndroidUtil.isMarshMallowOrLater)
itemView.setOnContextClickListener { v ->
onMoreClick(v)
true
}
binding.container.layoutParams.width = itemSize
binding.container.onFocusChangeListener = View.OnFocusChangeListener { _, hasFocus ->
if (hasFocus) {
var newWidth = (itemSize * 1.1).toInt()
if (newWidth % 2 == 1) {
newWidth--
}
val scale = newWidth.toFloat() / itemSize
binding.container.animate().scaleX(scale).scaleY(scale).translationZ(scale)
eventsHandler.onItemFocused(binding.root, getItem(layoutPosition)!!)
if (focusListener != null) {
focusListener!!.onFocusChanged(layoutPosition)
}
} else {
binding.container.animate().scaleX(1f).scaleY(1f).translationZ(1f)
}
}
binding.container.clipToOutline = true
}
override fun recycle() {
if (mDefaultCover != null) binding.cover = mDefaultCover
binding.title.text = ""
binding.subtitle.text = ""
}
override fun setItem(item: MediaLibraryItem?) {
binding.item = item
var isSquare = true
var progress = 0
var seen = 0L
var description = item?.description
if (item is MediaWrapper) {
if (item.type == MediaWrapper.TYPE_VIDEO) {
isSquare = false
description = if (item.time == 0L) Tools.millisToString(item.length) else Tools.getProgressText(item)
}
seen = item.seen
val resolution = generateResolutionClass(item.width, item.height)
var max = 0
if (item.length > 0) {
val lastTime = item.displayTime
if (lastTime > 0) {
max = (item.length / 1000).toInt()
progress = (lastTime / 1000).toInt()
}
}
binding.max = max
binding.badge = resolution
}
binding.progress = progress
binding.isSquare = isSquare
binding.seen = seen
binding.description = description
}
@ObsoleteCoroutinesApi
override fun setCoverlay(selected: Boolean) {
}
}
}
\ No newline at end of file
......@@ -36,7 +36,10 @@ import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.widget.PopupMenu
import androidx.annotation.MainThread
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
import androidx.databinding.BindingAdapter
import androidx.fragment.app.Fragment
import androidx.leanback.app.BackgroundManager
import androidx.lifecycle.Observer
......@@ -49,12 +52,8 @@ import org.videolan.medialibrary.Medialibrary
import org.videolan.medialibrary.media.MediaLibraryItem
import org.videolan.vlc.BuildConfig
import org.videolan.vlc.R
import org.videolan.vlc.gui.audio.AudioBrowserAdapter
import org.videolan.vlc.gui.tv.MediaBrowserAnimatorDelegate
import org.videolan.vlc.gui.tv.MediaHeaderAdapter
import org.videolan.vlc.gui.tv.TvUtil
import org.videolan.vlc.gui.tv.*
import org.videolan.vlc.gui.tv.browser.interfaces.BrowserFragmentInterface
import org.videolan.vlc.gui.tv.setAnimator
import org.videolan.vlc.gui.view.RecyclerSectionItemGridDecoration
import org.videolan.vlc.interfaces.IEventsHandler
import org.videolan.vlc.util.*
......@@ -71,14 +70,15 @@ class MediaBrowserTvFragment : Fragment(), BrowserFragmentInterface, IEventsHand
PopupMenu.OnMenuItemClickListener, MediaHeaderAdapter.OnHeaderSelected,
VerticalGridActivity.OnKeyPressedListener, CoroutineScope by MainScope() {
private var spacing: Int = 0
private lateinit var viewModel: MediaBrowserViewModel
private lateinit var adapter: AudioBrowserAdapter
private lateinit var adapter: TvItemAdapter
// private lateinit var headerList: RecyclerView
private lateinit var headerAdapter: MediaHeaderAdapter
private lateinit var gridLayoutManager: GridLayoutManager
private var currentArt: String? = null
private lateinit var backgroundManager: BackgroundManager
internal lateinit var animationDelegate : MediaBrowserAnimatorDelegate
internal lateinit var animationDelegate: MediaBrowserAnimatorDelegate
companion object {
fun newInstance(type: Long, item: MediaLibraryItem?) =
......@@ -131,7 +131,6 @@ class MediaBrowserTvFragment : Fragment(), BrowserFragmentInterface, IEventsHand
//overscan
val hp = TvUtil.getOverscanHorizontal(requireContext())
val vp = TvUtil.getOverscanVertical(requireContext())
list.setPadding(list.paddingLeft + hp, list.paddingTop + vp, list.paddingRight + hp, list.paddingBottom + vp)
headerList.setPadding(list.paddingLeft + hp, list.paddingTop + vp, list.paddingRight + hp, list.paddingBottom + vp)
......@@ -141,6 +140,10 @@ class MediaBrowserTvFragment : Fragment(), BrowserFragmentInterface, IEventsHand
lp.topMargin += vp
lp.bottomMargin += vp
calculateNbColumns()
if (viewModel.currentItem != null) {
title.text = viewModel.currentItem!!.title
} else when (arguments?.getLong(AUDIO_CATEGORY, CATEGORY_SONGS)) {
......@@ -148,7 +151,7 @@ class MediaBrowserTvFragment : Fragment(), BrowserFragmentInterface, IEventsHand
CATEGORY_ALBUMS -> title.setText(R.string.albums)
CATEGORY_ARTISTS -> title.setText(R.string.artists)
CATEGORY_GENRES -> title.setText(R.string.genres)
CATEGORY_VIDEOS -> title.setText(R.string.videos)
CATEGORY_VIDEOS -> title.setText(R.string.video)
}
val searchHeaderClick: (View) -> Unit = { animationDelegate.hideFAB() }
......@@ -161,16 +164,17 @@ class MediaBrowserTvFragment : Fragment(), BrowserFragmentInterface, IEventsHand
sortButton.setOnClickListener(sortClick)
imageButtonSort.setOnClickListener(sortClick)
gridLayoutManager = object : GridLayoutManager(requireActivity(), viewModel.nbColumns) {
override fun requestChildRectangleOnScreen(parent: RecyclerView, child: View, rect: Rect, immediate: Boolean) = false
override fun requestChildRectangleOnScreen(parent: RecyclerView, child: View, rect: Rect, immediate: Boolean, focusedChildVisible: Boolean) = false
}
val spacing = resources.getDimensionPixelSize(R.dimen.recycler_section_header_spacing)
spacing = resources.getDimensionPixelSize(R.dimen.recycler_section_header_spacing)
//size of an item
val itemSize = requireActivity().getScreenWidth() / viewModel.nbColumns - spacing * 2
val itemSize = (requireActivity().getScreenWidth() - list.paddingLeft - list.paddingRight) / viewModelnbColumns - spacing * 2
gridLayoutManager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
override fun getSpanSize(position: Int): Int {
......@@ -184,7 +188,7 @@ class MediaBrowserTvFragment : Fragment(), BrowserFragmentInterface, IEventsHand
val firstSection = viewModel.provider.getPositionForSection(position)
val nbItems = position - firstSection
if (BuildConfig.DEBUG)
Log.d("SongsBrowserFragment", "Position: " + position + " nb items: " + nbItems + " span: " + nbItems % viewModel.nbColumns)
Log.d("SongsBrowserFragment", "Position: " + position + " nb items: " + nbItems + " span: " + (viewModel.nbColumns - nbItems % nbColumns))
return viewModel.nbColumns - nbItems % viewModel.nbColumns
}
......@@ -194,7 +198,7 @@ class MediaBrowserTvFragment : Fragment(), BrowserFragmentInterface, IEventsHand
list.layoutManager = gridLayoutManager
adapter = AudioBrowserAdapter(MediaLibraryItem.TYPE_MEDIA, this, itemSize).apply { setTV(true) }
adapter = TvItemAdapter(MediaLibraryItem.TYPE_MEDIA, this, itemSize)
list.addItemDecoration(RecyclerSectionItemGridDecoration(resources.getDimensionPixelSize(R.dimen.recycler_section_header_tv_height), spacing, true, viewModel.nbColumns, viewModel.provider))
......@@ -215,10 +219,19 @@ class MediaBrowserTvFragment : Fragment(), BrowserFragmentInterface, IEventsHand
super.onViewCreated(view, savedInstanceState)
}
private fun calculateNbColumns() {
viewModel.nbColumns = when (arguments?.getLong(AUDIO_CATEGORY, CATEGORY_SONGS)) {
CATEGORY_VIDEOS -> resources.getInteger(R.integer.tv_videos_col_count)
else -> resources.getInteger(R.integer.tv_songs_col_count)
}
}
override fun onConfigurationChanged(newConfig: Configuration?) {
super.onConfigurationChanged(newConfig)
calculateNbColumns()
gridLayoutManager.spanCount = viewModel.nbColumns
list.layoutManager = gridLayoutManager
}
......@@ -328,7 +341,7 @@ class MediaBrowserTvFragment : Fragment(), BrowserFragmentInterface, IEventsHand
}
private var lastDpadEventTime = 0L
override fun onKeyPressed(keyCode: Int)= when (keyCode) {
override fun onKeyPressed(keyCode: Int) = when (keyCode) {
KEYCODE_MENU -> {
imageButtonSettings.requestFocusFromTouch()
animationDelegate.expandExtendedFAB()
......@@ -354,3 +367,19 @@ class MediaBrowserTvFragment : Fragment(), BrowserFragmentInterface, IEventsHand
else -> false
}
}
@MainThread
@BindingAdapter("constraintRatio")
fun constraintRatio(v: View, isSquare: Boolean) {
val constraintLayout = v.parent as? ConstraintLayout
constraintLayout?.let {
val constraintSet = ConstraintSet()
constraintSet.clone(constraintLayout)
constraintSet.setDimensionRatio(v.id, if (isSquare) "1" else "16:10")
constraintLayout.setConstraintSet(constraintSet)
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment