Add header to EpisodeListAdapter
This commit is contained in:
parent
a70d154eca
commit
4bbf40bc22
7 changed files with 249 additions and 162 deletions
|
@ -113,7 +113,7 @@ fun bindPersonImage(imageView: ImageView, person: BaseItemPerson) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@BindingAdapter("episodes")
|
@BindingAdapter("episodes")
|
||||||
fun bindEpisodes(recyclerView: RecyclerView, data: List<BaseItemDto>?) {
|
fun bindEpisodes(recyclerView: RecyclerView, data: List<EpisodeItem>?) {
|
||||||
val adapter = recyclerView.adapter as EpisodeListAdapter
|
val adapter = recyclerView.adapter as EpisodeListAdapter
|
||||||
adapter.submitList(data)
|
adapter.submitList(data)
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,10 +8,37 @@ import androidx.recyclerview.widget.DiffUtil
|
||||||
import androidx.recyclerview.widget.ListAdapter
|
import androidx.recyclerview.widget.ListAdapter
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import dev.jdtech.jellyfin.databinding.EpisodeItemBinding
|
import dev.jdtech.jellyfin.databinding.EpisodeItemBinding
|
||||||
|
import dev.jdtech.jellyfin.databinding.SeasonHeaderBinding
|
||||||
import org.jellyfin.sdk.model.api.BaseItemDto
|
import org.jellyfin.sdk.model.api.BaseItemDto
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
class EpisodeListAdapter(private val onClickListener: OnClickListener) :
|
private const val ITEM_VIEW_TYPE_HEADER = 0
|
||||||
ListAdapter<BaseItemDto, EpisodeListAdapter.EpisodeViewHolder>(DiffCallback) {
|
private const val ITEM_VIEW_TYPE_EPISODE = 1
|
||||||
|
|
||||||
|
class EpisodeListAdapter(
|
||||||
|
private val onClickListener: OnClickListener,
|
||||||
|
private val seriesId: UUID,
|
||||||
|
private val seriesName: String?,
|
||||||
|
private val seasonId: UUID,
|
||||||
|
private val seasonName: String?
|
||||||
|
) :
|
||||||
|
ListAdapter<EpisodeItem, RecyclerView.ViewHolder>(DiffCallback) {
|
||||||
|
|
||||||
|
class HeaderViewHolder(private var binding: SeasonHeaderBinding) :
|
||||||
|
RecyclerView.ViewHolder(binding.root) {
|
||||||
|
fun bind(
|
||||||
|
seriesId: UUID,
|
||||||
|
seriesName: String?,
|
||||||
|
seasonId: UUID,
|
||||||
|
seasonName: String?
|
||||||
|
) {
|
||||||
|
binding.seriesId = seriesId
|
||||||
|
binding.seasonId = seasonId
|
||||||
|
binding.seasonName.text = seasonName
|
||||||
|
binding.seriesName.text = seriesName
|
||||||
|
binding.executePendingBindings()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class EpisodeViewHolder(private var binding: EpisodeItemBinding) :
|
class EpisodeViewHolder(private var binding: EpisodeItemBinding) :
|
||||||
RecyclerView.ViewHolder(binding.root) {
|
RecyclerView.ViewHolder(binding.root) {
|
||||||
|
@ -20,7 +47,9 @@ class EpisodeListAdapter(private val onClickListener: OnClickListener) :
|
||||||
if (episode.userData?.playedPercentage != null) {
|
if (episode.userData?.playedPercentage != null) {
|
||||||
binding.progressBar.layoutParams.width = TypedValue.applyDimension(
|
binding.progressBar.layoutParams.width = TypedValue.applyDimension(
|
||||||
TypedValue.COMPLEX_UNIT_DIP,
|
TypedValue.COMPLEX_UNIT_DIP,
|
||||||
(episode.userData?.playedPercentage?.times(.84))!!.toFloat(), binding.progressBar.context.resources.displayMetrics).toInt()
|
(episode.userData?.playedPercentage?.times(.84))!!.toFloat(),
|
||||||
|
binding.progressBar.context.resources.displayMetrics
|
||||||
|
).toInt()
|
||||||
binding.progressBar.visibility = View.VISIBLE
|
binding.progressBar.visibility = View.VISIBLE
|
||||||
} else {
|
} else {
|
||||||
binding.progressBar.visibility = View.GONE
|
binding.progressBar.visibility = View.GONE
|
||||||
|
@ -29,18 +58,29 @@ class EpisodeListAdapter(private val onClickListener: OnClickListener) :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object DiffCallback : DiffUtil.ItemCallback<BaseItemDto>() {
|
companion object DiffCallback : DiffUtil.ItemCallback<EpisodeItem>() {
|
||||||
override fun areItemsTheSame(oldItem: BaseItemDto, newItem: BaseItemDto): Boolean {
|
override fun areItemsTheSame(oldItem: EpisodeItem, newItem: EpisodeItem): Boolean {
|
||||||
return oldItem.id == newItem.id
|
return oldItem.id == newItem.id
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun areContentsTheSame(oldItem: BaseItemDto, newItem: BaseItemDto): Boolean {
|
override fun areContentsTheSame(oldItem: EpisodeItem, newItem: EpisodeItem): Boolean {
|
||||||
return oldItem == newItem
|
return oldItem == newItem
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): EpisodeViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||||
return EpisodeViewHolder(
|
return when (viewType) {
|
||||||
|
ITEM_VIEW_TYPE_HEADER -> {
|
||||||
|
HeaderViewHolder(
|
||||||
|
SeasonHeaderBinding.inflate(
|
||||||
|
LayoutInflater.from(parent.context),
|
||||||
|
parent,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
ITEM_VIEW_TYPE_EPISODE -> {
|
||||||
|
EpisodeViewHolder(
|
||||||
EpisodeItemBinding.inflate(
|
EpisodeItemBinding.inflate(
|
||||||
LayoutInflater.from(parent.context),
|
LayoutInflater.from(parent.context),
|
||||||
parent,
|
parent,
|
||||||
|
@ -48,16 +88,45 @@ class EpisodeListAdapter(private val onClickListener: OnClickListener) :
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
else -> throw ClassCastException("Unknown viewType $viewType")
|
||||||
override fun onBindViewHolder(holder: EpisodeViewHolder, position: Int) {
|
}
|
||||||
val item = getItem(position)
|
}
|
||||||
holder.itemView.setOnClickListener {
|
|
||||||
onClickListener.onClick(item)
|
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||||
|
when (holder.itemViewType) {
|
||||||
|
ITEM_VIEW_TYPE_HEADER -> {
|
||||||
|
(holder as HeaderViewHolder).bind(seriesId, seriesName, seasonId, seasonName)
|
||||||
|
}
|
||||||
|
ITEM_VIEW_TYPE_EPISODE -> {
|
||||||
|
val item = getItem(position) as EpisodeItem.Episode
|
||||||
|
holder.itemView.setOnClickListener {
|
||||||
|
onClickListener.onClick(item.episode)
|
||||||
|
}
|
||||||
|
(holder as EpisodeViewHolder).bind(item.episode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemViewType(position: Int): Int {
|
||||||
|
return when (getItem(position)) {
|
||||||
|
is EpisodeItem.Header -> ITEM_VIEW_TYPE_HEADER
|
||||||
|
is EpisodeItem.Episode -> ITEM_VIEW_TYPE_EPISODE
|
||||||
}
|
}
|
||||||
holder.bind(item)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class OnClickListener(val clickListener: (item: BaseItemDto) -> Unit) {
|
class OnClickListener(val clickListener: (item: BaseItemDto) -> Unit) {
|
||||||
fun onClick(item: BaseItemDto) = clickListener(item)
|
fun onClick(item: BaseItemDto) = clickListener(item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sealed class EpisodeItem {
|
||||||
|
abstract val id: UUID
|
||||||
|
|
||||||
|
object Header : EpisodeItem() {
|
||||||
|
override val id: UUID = UUID.randomUUID()
|
||||||
|
}
|
||||||
|
|
||||||
|
data class Episode(val episode: BaseItemDto) : EpisodeItem() {
|
||||||
|
override val id = episode.id
|
||||||
|
}
|
||||||
|
}
|
|
@ -37,11 +37,7 @@ class SeasonFragment : Fragment() {
|
||||||
binding.episodesRecyclerView.adapter =
|
binding.episodesRecyclerView.adapter =
|
||||||
EpisodeListAdapter(EpisodeListAdapter.OnClickListener { episode ->
|
EpisodeListAdapter(EpisodeListAdapter.OnClickListener { episode ->
|
||||||
navigateToEpisodeBottomSheetFragment(episode)
|
navigateToEpisodeBottomSheetFragment(episode)
|
||||||
})
|
}, args.seriesId, args.seriesName, args.seasonId, args.seasonName)
|
||||||
binding.seriesName.text = args.seriesName
|
|
||||||
binding.seasonName.text = args.seasonName
|
|
||||||
binding.seriesId = args.seriesId
|
|
||||||
binding.seasonId = args.seasonId
|
|
||||||
|
|
||||||
viewModel.loadEpisodes(args.seriesId, args.seasonId)
|
viewModel.loadEpisodes(args.seriesId, args.seasonId)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
package dev.jdtech.jellyfin.viewmodels
|
package dev.jdtech.jellyfin.viewmodels
|
||||||
|
|
||||||
import androidx.lifecycle.*
|
import androidx.lifecycle.LiveData
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
import dev.jdtech.jellyfin.adapters.EpisodeItem
|
||||||
import dev.jdtech.jellyfin.repository.JellyfinRepository
|
import dev.jdtech.jellyfin.repository.JellyfinRepository
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.jellyfin.sdk.model.api.BaseItemDto
|
|
||||||
import org.jellyfin.sdk.model.api.ItemFields
|
import org.jellyfin.sdk.model.api.ItemFields
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
@ -14,12 +17,17 @@ class SeasonViewModel
|
||||||
@Inject
|
@Inject
|
||||||
constructor(private val jellyfinRepository: JellyfinRepository) : ViewModel() {
|
constructor(private val jellyfinRepository: JellyfinRepository) : ViewModel() {
|
||||||
|
|
||||||
private val _episodes = MutableLiveData<List<BaseItemDto>>()
|
private val _episodes = MutableLiveData<List<EpisodeItem>>()
|
||||||
val episodes: LiveData<List<BaseItemDto>> = _episodes
|
val episodes: LiveData<List<EpisodeItem>> = _episodes
|
||||||
|
|
||||||
fun loadEpisodes(seriesId: UUID, seasonId: UUID) {
|
fun loadEpisodes(seriesId: UUID, seasonId: UUID) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
_episodes.value = jellyfinRepository.getEpisodes(seriesId, seasonId, fields = listOf(ItemFields.OVERVIEW))
|
_episodes.value = getEpisodes(seriesId, seasonId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private suspend fun getEpisodes(seriesId: UUID, seasonId: UUID): List<EpisodeItem> {
|
||||||
|
val episodes = jellyfinRepository.getEpisodes(seriesId, seasonId, fields = listOf(ItemFields.OVERVIEW))
|
||||||
|
return listOf(EpisodeItem.Header) + episodes.map { EpisodeItem.Episode(it) }
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -15,6 +15,7 @@
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="100dp"
|
android:layout_height="100dp"
|
||||||
|
android:layout_marginHorizontal="24dp"
|
||||||
android:layout_marginBottom="24dp"
|
android:layout_marginBottom="24dp"
|
||||||
android:foreground="?android:attr/selectableItemBackground">
|
android:foreground="?android:attr/selectableItemBackground">
|
||||||
|
|
||||||
|
|
|
@ -10,154 +10,23 @@
|
||||||
name="viewModel"
|
name="viewModel"
|
||||||
type="dev.jdtech.jellyfin.viewmodels.SeasonViewModel" />
|
type="dev.jdtech.jellyfin.viewmodels.SeasonViewModel" />
|
||||||
|
|
||||||
<variable
|
|
||||||
name="seriesId"
|
|
||||||
type="java.util.UUID" />
|
|
||||||
|
|
||||||
<variable
|
|
||||||
name="seasonId"
|
|
||||||
type="java.util.UUID" />
|
|
||||||
</data>
|
</data>
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
|
||||||
android:id="@+id/header"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="200dp"
|
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/item_banner"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="200dp"
|
|
||||||
android:scaleType="centerCrop"
|
|
||||||
app:itemBackdropById="@{seriesId}"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
android:contentDescription="@string/series_poster"/>
|
|
||||||
|
|
||||||
<FrameLayout
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:background="@drawable/header_gradient"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
|
||||||
|
|
||||||
<com.google.android.material.imageview.ShapeableImageView
|
|
||||||
android:id="@+id/season_poster"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:layout_marginStart="24dp"
|
|
||||||
android:layout_marginTop="24dp"
|
|
||||||
android:elevation="8dp"
|
|
||||||
android:scaleType="centerCrop"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintDimensionRatio="H,3:2"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
app:seasonPoster="@{seasonId}"
|
|
||||||
app:shapeAppearanceOverlay="@style/roundedImageView" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/series_name"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginHorizontal="24dp"
|
|
||||||
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
|
|
||||||
app:layout_constraintBottom_toTopOf="@id/season_name"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toEndOf="@id/season_poster"
|
|
||||||
tools:text="Attack on Titan" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/season_name"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginHorizontal="24dp"
|
|
||||||
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline5"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toEndOf="@id/season_poster"
|
|
||||||
tools:text="Season 1" />
|
|
||||||
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/buttons"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginHorizontal="24dp"
|
|
||||||
android:layout_marginTop="24dp"
|
|
||||||
android:layout_marginBottom="24dp"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/header">
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/play_button"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginEnd="12dp"
|
|
||||||
android:background="@drawable/button_setup_background"
|
|
||||||
android:contentDescription="@string/play_button_description"
|
|
||||||
android:paddingHorizontal="24dp"
|
|
||||||
android:paddingVertical="12dp"
|
|
||||||
android:src="@drawable/ic_play" />
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/shuffle_button"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginEnd="12dp"
|
|
||||||
android:background="@drawable/button_accent_background"
|
|
||||||
android:contentDescription="@string/shuffle_button_description"
|
|
||||||
android:padding="12dp"
|
|
||||||
android:src="@drawable/ic_shuffle" />
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/check_button"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginEnd="12dp"
|
|
||||||
android:background="@drawable/button_accent_background"
|
|
||||||
android:contentDescription="@string/check_button_description"
|
|
||||||
android:padding="12dp"
|
|
||||||
android:src="@drawable/ic_check" />
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/favorite_button"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:background="@drawable/button_accent_background"
|
|
||||||
android:contentDescription="@string/favorite_button_description"
|
|
||||||
android:padding="12dp"
|
|
||||||
android:src="@drawable/ic_heart" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/episodes_recycler_view"
|
android:id="@+id/episodes_recycler_view"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
android:paddingHorizontal="24dp"
|
|
||||||
android:paddingTop="16dp"
|
|
||||||
app:episodes="@{viewModel.episodes}"
|
app:episodes="@{viewModel.episodes}"
|
||||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/buttons"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
tools:itemCount="4"
|
tools:itemCount="4"
|
||||||
tools:listitem="@layout/episode_item" />
|
tools:listitem="@layout/episode_item" />
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
144
app/src/main/res/layout/season_header.xml
Normal file
144
app/src/main/res/layout/season_header.xml
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
|
<data>
|
||||||
|
|
||||||
|
<variable
|
||||||
|
name="seriesId"
|
||||||
|
type="java.util.UUID" />
|
||||||
|
|
||||||
|
<variable
|
||||||
|
name="seasonId"
|
||||||
|
type="java.util.UUID" />
|
||||||
|
</data>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:id="@+id/header"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="200dp"
|
||||||
|
android:layout_marginBottom="24dp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/item_banner"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="200dp"
|
||||||
|
android:contentDescription="@string/series_poster"
|
||||||
|
android:scaleType="centerCrop"
|
||||||
|
app:itemBackdropById="@{seriesId}"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:background="@drawable/header_gradient"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<com.google.android.material.imageview.ShapeableImageView
|
||||||
|
android:id="@+id/season_poster"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_marginStart="24dp"
|
||||||
|
android:layout_marginTop="24dp"
|
||||||
|
android:elevation="8dp"
|
||||||
|
android:scaleType="centerCrop"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintDimensionRatio="H,3:2"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:seasonPoster="@{seasonId}"
|
||||||
|
app:shapeAppearanceOverlay="@style/roundedImageView" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/series_name"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="24dp"
|
||||||
|
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
|
||||||
|
app:layout_constraintBottom_toTopOf="@id/season_name"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/season_poster"
|
||||||
|
tools:text="Attack on Titan" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/season_name"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="24dp"
|
||||||
|
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline5"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/season_poster"
|
||||||
|
tools:text="Season 1" />
|
||||||
|
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/buttons"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="24dp"
|
||||||
|
android:layout_marginBottom="24dp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/header">
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/play_button"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="12dp"
|
||||||
|
android:background="@drawable/button_setup_background"
|
||||||
|
android:contentDescription="@string/play_button_description"
|
||||||
|
android:paddingHorizontal="24dp"
|
||||||
|
android:paddingVertical="12dp"
|
||||||
|
android:src="@drawable/ic_play" />
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/shuffle_button"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="12dp"
|
||||||
|
android:background="@drawable/button_accent_background"
|
||||||
|
android:contentDescription="@string/shuffle_button_description"
|
||||||
|
android:padding="12dp"
|
||||||
|
android:src="@drawable/ic_shuffle" />
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/check_button"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="12dp"
|
||||||
|
android:background="@drawable/button_accent_background"
|
||||||
|
android:contentDescription="@string/check_button_description"
|
||||||
|
android:padding="12dp"
|
||||||
|
android:src="@drawable/ic_check" />
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/favorite_button"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@drawable/button_accent_background"
|
||||||
|
android:contentDescription="@string/favorite_button_description"
|
||||||
|
android:padding="12dp"
|
||||||
|
android:src="@drawable/ic_heart" />
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</layout>
|
Loading…
Reference in a new issue