Add error handling to all fragments
This commit is contained in:
parent
11793a423b
commit
fe7775329a
14 changed files with 600 additions and 414 deletions
|
@ -8,7 +8,9 @@ import android.view.ViewGroup
|
|||
import androidx.fragment.app.viewModels
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.navigation.fragment.navArgs
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import dev.jdtech.jellyfin.R
|
||||
import dev.jdtech.jellyfin.viewmodels.LibraryViewModel
|
||||
import dev.jdtech.jellyfin.adapters.ViewItemListAdapter
|
||||
import dev.jdtech.jellyfin.databinding.FragmentLibraryBinding
|
||||
|
@ -36,6 +38,27 @@ class LibraryFragment : Fragment() {
|
|||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
binding.viewModel = viewModel
|
||||
|
||||
val snackbar =
|
||||
Snackbar.make(
|
||||
binding.mainLayout,
|
||||
getString(R.string.error_loading_data),
|
||||
Snackbar.LENGTH_INDEFINITE
|
||||
)
|
||||
snackbar.setAction(getString(R.string.retry)) {
|
||||
viewModel.loadItems(args.libraryId)
|
||||
}
|
||||
|
||||
viewModel.error.observe(viewLifecycleOwner, { error ->
|
||||
if (error) {
|
||||
snackbar.show()
|
||||
}
|
||||
})
|
||||
|
||||
viewModel.finishedLoading.observe(viewLifecycleOwner, {
|
||||
binding.loadingIndicator.visibility = if (it) View.GONE else View.VISIBLE
|
||||
})
|
||||
|
||||
binding.itemsRecyclerView.adapter =
|
||||
ViewItemListAdapter(ViewItemListAdapter.OnClickListener { item ->
|
||||
navigateToMediaInfoFragment(item)
|
||||
|
|
|
@ -7,7 +7,9 @@ import android.view.ViewGroup
|
|||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import dev.jdtech.jellyfin.R
|
||||
import dev.jdtech.jellyfin.adapters.CollectionListAdapter
|
||||
import dev.jdtech.jellyfin.databinding.FragmentMediaBinding
|
||||
import dev.jdtech.jellyfin.viewmodels.MediaViewModel
|
||||
|
@ -26,6 +28,16 @@ class MediaFragment : Fragment() {
|
|||
): View {
|
||||
binding = FragmentMediaBinding.inflate(inflater, container, false)
|
||||
|
||||
val snackbar =
|
||||
Snackbar.make(
|
||||
binding.mainLayout,
|
||||
getString(R.string.error_loading_data),
|
||||
Snackbar.LENGTH_INDEFINITE
|
||||
)
|
||||
snackbar.setAction(getString(R.string.retry)) {
|
||||
viewModel.loadData()
|
||||
}
|
||||
|
||||
binding.lifecycleOwner = this
|
||||
binding.viewModel = viewModel
|
||||
binding.viewsRecyclerView.adapter =
|
||||
|
@ -34,8 +46,12 @@ class MediaFragment : Fragment() {
|
|||
})
|
||||
|
||||
viewModel.finishedLoading.observe(viewLifecycleOwner, {
|
||||
if (it) {
|
||||
binding.loadingIndicator.visibility = View.GONE
|
||||
binding.loadingIndicator.visibility = if (it) View.GONE else View.VISIBLE
|
||||
})
|
||||
|
||||
viewModel.error.observe(viewLifecycleOwner, { error ->
|
||||
if (error) {
|
||||
snackbar.show()
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ import androidx.fragment.app.Fragment
|
|||
import androidx.fragment.app.viewModels
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.navigation.fragment.navArgs
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import dev.jdtech.jellyfin.R
|
||||
import dev.jdtech.jellyfin.adapters.PersonListAdapter
|
||||
|
@ -42,8 +43,24 @@ class MediaInfoFragment : Fragment() {
|
|||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
val snackbar =
|
||||
Snackbar.make(
|
||||
binding.mainLayout,
|
||||
getString(R.string.error_loading_data),
|
||||
Snackbar.LENGTH_INDEFINITE
|
||||
)
|
||||
snackbar.setAction(getString(R.string.retry)) {
|
||||
viewModel.loadData(args.itemId, args.itemType)
|
||||
}
|
||||
|
||||
binding.viewModel = viewModel
|
||||
|
||||
viewModel.error.observe(viewLifecycleOwner, { error ->
|
||||
if (error) {
|
||||
snackbar.show()
|
||||
}
|
||||
})
|
||||
|
||||
viewModel.item.observe(viewLifecycleOwner, { item ->
|
||||
if (item.originalTitle != item.name) {
|
||||
binding.originalTitle.visibility = View.VISIBLE
|
||||
|
|
|
@ -8,7 +8,9 @@ import android.view.ViewGroup
|
|||
import androidx.fragment.app.viewModels
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.navigation.fragment.navArgs
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import dev.jdtech.jellyfin.R
|
||||
import dev.jdtech.jellyfin.adapters.EpisodeListAdapter
|
||||
import dev.jdtech.jellyfin.databinding.FragmentSeasonBinding
|
||||
import dev.jdtech.jellyfin.viewmodels.SeasonViewModel
|
||||
|
@ -34,6 +36,27 @@ class SeasonFragment : Fragment() {
|
|||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
binding.viewModel = viewModel
|
||||
|
||||
val snackbar =
|
||||
Snackbar.make(
|
||||
binding.mainLayout,
|
||||
getString(R.string.error_loading_data),
|
||||
Snackbar.LENGTH_INDEFINITE
|
||||
)
|
||||
snackbar.setAction(getString(R.string.retry)) {
|
||||
viewModel.loadEpisodes(args.seriesId, args.seasonId)
|
||||
}
|
||||
|
||||
viewModel.error.observe(viewLifecycleOwner, { error ->
|
||||
if (error) {
|
||||
snackbar.show()
|
||||
}
|
||||
})
|
||||
|
||||
viewModel.finishedLoading.observe(viewLifecycleOwner, {
|
||||
binding.loadingIndicator.visibility = if (it) View.GONE else View.VISIBLE
|
||||
})
|
||||
|
||||
binding.episodesRecyclerView.adapter =
|
||||
EpisodeListAdapter(EpisodeListAdapter.OnClickListener { episode ->
|
||||
navigateToEpisodeBottomSheetFragment(episode)
|
||||
|
|
|
@ -10,6 +10,7 @@ import dev.jdtech.jellyfin.repository.JellyfinRepository
|
|||
import kotlinx.coroutines.launch
|
||||
import org.jellyfin.sdk.model.api.BaseItemDto
|
||||
import org.jellyfin.sdk.model.api.MediaSourceInfo
|
||||
import timber.log.Timber
|
||||
import java.text.DateFormat
|
||||
import java.time.ZoneOffset
|
||||
import java.util.*
|
||||
|
@ -42,12 +43,17 @@ constructor(
|
|||
|
||||
fun loadEpisode(episodeId: UUID) {
|
||||
viewModelScope.launch {
|
||||
_item.value = jellyfinRepository.getItem(episodeId)
|
||||
_runTime.value = "${_item.value?.runTimeTicks?.div(600000000)} min"
|
||||
_dateString.value = getDateString(_item.value!!)
|
||||
_mediaSources.value = jellyfinRepository.getMediaSources(episodeId)
|
||||
_played.value = _item.value?.userData?.played
|
||||
_favorite.value = _item.value?.userData?.isFavorite
|
||||
try {
|
||||
val item = jellyfinRepository.getItem(episodeId)
|
||||
_item.value = item
|
||||
_runTime.value = "${item.runTimeTicks?.div(600000000)} min"
|
||||
_dateString.value = getDateString(item)
|
||||
_mediaSources.value = jellyfinRepository.getMediaSources(episodeId)
|
||||
_played.value = item.userData?.played
|
||||
_favorite.value = item.userData?.isFavorite
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -85,12 +85,11 @@ constructor(
|
|||
|
||||
_views.value = items + views.map { HomeItem.ViewItem(it) }
|
||||
|
||||
_finishedLoading.value = true
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e)
|
||||
_finishedLoading.value = true
|
||||
_error.value = true
|
||||
}
|
||||
_finishedLoading.value = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import dagger.hilt.android.lifecycle.HiltViewModel
|
|||
import dev.jdtech.jellyfin.repository.JellyfinRepository
|
||||
import kotlinx.coroutines.launch
|
||||
import org.jellyfin.sdk.model.api.BaseItemDto
|
||||
import timber.log.Timber
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
|
||||
|
@ -19,9 +20,19 @@ constructor(private val jellyfinRepository: JellyfinRepository) : ViewModel() {
|
|||
private val _finishedLoading = MutableLiveData<Boolean>()
|
||||
val finishedLoading: LiveData<Boolean> = _finishedLoading
|
||||
|
||||
private val _error = MutableLiveData<Boolean>()
|
||||
val error: LiveData<Boolean> = _error
|
||||
|
||||
fun loadItems(parentId: UUID) {
|
||||
_error.value = false
|
||||
_finishedLoading.value = false
|
||||
viewModelScope.launch {
|
||||
_items.value = jellyfinRepository.getItems(parentId)
|
||||
try {
|
||||
_items.value = jellyfinRepository.getItems(parentId)
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e)
|
||||
_error.value = true
|
||||
}
|
||||
_finishedLoading.value = true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import kotlinx.coroutines.withContext
|
|||
import org.jellyfin.sdk.model.api.BaseItemDto
|
||||
import org.jellyfin.sdk.model.api.BaseItemPerson
|
||||
import org.jellyfin.sdk.model.api.MediaSourceInfo
|
||||
import timber.log.Timber
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
|
||||
|
@ -62,25 +63,34 @@ constructor(private val jellyfinRepository: JellyfinRepository) : ViewModel() {
|
|||
private val _favorite = MutableLiveData<Boolean>()
|
||||
val favorite: LiveData<Boolean> = _favorite
|
||||
|
||||
private val _error = MutableLiveData<Boolean>()
|
||||
val error: LiveData<Boolean> = _error
|
||||
|
||||
fun loadData(itemId: UUID, itemType: String) {
|
||||
_error.value = false
|
||||
viewModelScope.launch {
|
||||
_item.value = jellyfinRepository.getItem(itemId)
|
||||
_actors.value = getActors(_item.value!!)
|
||||
_director.value = getDirector(_item.value!!)
|
||||
_writers.value = getWriters(_item.value!!)
|
||||
_writersString.value =
|
||||
_writers.value?.joinToString(separator = ", ") { it.name.toString() }
|
||||
_genresString.value = _item.value?.genres?.joinToString(separator = ", ")
|
||||
_runTime.value = "${_item.value?.runTimeTicks?.div(600000000)} min"
|
||||
_dateString.value = getDateString(_item.value!!)
|
||||
_played.value = _item.value?.userData?.played
|
||||
_favorite.value = _item.value?.userData?.isFavorite
|
||||
if (itemType == "Series") {
|
||||
_nextUp.value = getNextUp(itemId)
|
||||
_seasons.value = jellyfinRepository.getSeasons(itemId)
|
||||
}
|
||||
if (itemType == "Movie") {
|
||||
_mediaSources.value = jellyfinRepository.getMediaSources(itemId)
|
||||
try {
|
||||
_item.value = jellyfinRepository.getItem(itemId)
|
||||
_actors.value = getActors(_item.value!!)
|
||||
_director.value = getDirector(_item.value!!)
|
||||
_writers.value = getWriters(_item.value!!)
|
||||
_writersString.value =
|
||||
_writers.value?.joinToString(separator = ", ") { it.name.toString() }
|
||||
_genresString.value = _item.value?.genres?.joinToString(separator = ", ")
|
||||
_runTime.value = "${_item.value?.runTimeTicks?.div(600000000)} min"
|
||||
_dateString.value = getDateString(_item.value!!)
|
||||
_played.value = _item.value?.userData?.played
|
||||
_favorite.value = _item.value?.userData?.isFavorite
|
||||
if (itemType == "Series") {
|
||||
_nextUp.value = getNextUp(itemId)
|
||||
_seasons.value = jellyfinRepository.getSeasons(itemId)
|
||||
}
|
||||
if (itemType == "Movie") {
|
||||
_mediaSources.value = jellyfinRepository.getMediaSources(itemId)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e)
|
||||
_error.value = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import dagger.hilt.android.lifecycle.HiltViewModel
|
|||
import dev.jdtech.jellyfin.repository.JellyfinRepository
|
||||
import kotlinx.coroutines.launch
|
||||
import org.jellyfin.sdk.model.api.BaseItemDto
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
|
@ -20,16 +21,30 @@ constructor(
|
|||
private val _finishedLoading = MutableLiveData<Boolean>()
|
||||
val finishedLoading: LiveData<Boolean> = _finishedLoading
|
||||
|
||||
private val _error = MutableLiveData<Boolean>()
|
||||
val error: LiveData<Boolean> = _error
|
||||
|
||||
init {
|
||||
loadData()
|
||||
}
|
||||
|
||||
fun loadData() {
|
||||
_finishedLoading.value = false
|
||||
_error.value = false
|
||||
viewModelScope.launch {
|
||||
val items = jellyfinRepository.getItems()
|
||||
_collections.value =
|
||||
items.filter {
|
||||
it.collectionType != "homevideos" &&
|
||||
it.collectionType != "music" &&
|
||||
it.collectionType != "playlists" &&
|
||||
it.collectionType != "boxsets"
|
||||
}
|
||||
try {
|
||||
val items = jellyfinRepository.getItems()
|
||||
_collections.value =
|
||||
items.filter {
|
||||
it.collectionType != "homevideos" &&
|
||||
it.collectionType != "music" &&
|
||||
it.collectionType != "playlists" &&
|
||||
it.collectionType != "boxsets"
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e)
|
||||
_error.value = true
|
||||
}
|
||||
_finishedLoading.value = true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import dev.jdtech.jellyfin.adapters.EpisodeItem
|
|||
import dev.jdtech.jellyfin.repository.JellyfinRepository
|
||||
import kotlinx.coroutines.launch
|
||||
import org.jellyfin.sdk.model.api.ItemFields
|
||||
import timber.log.Timber
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
|
||||
|
@ -20,9 +21,23 @@ constructor(private val jellyfinRepository: JellyfinRepository) : ViewModel() {
|
|||
private val _episodes = MutableLiveData<List<EpisodeItem>>()
|
||||
val episodes: LiveData<List<EpisodeItem>> = _episodes
|
||||
|
||||
private val _finishedLoading = MutableLiveData<Boolean>()
|
||||
val finishedLoading: LiveData<Boolean> = _finishedLoading
|
||||
|
||||
private val _error = MutableLiveData<Boolean>()
|
||||
val error: LiveData<Boolean> = _error
|
||||
|
||||
fun loadEpisodes(seriesId: UUID, seasonId: UUID) {
|
||||
_error.value = false
|
||||
_finishedLoading.value = false
|
||||
viewModelScope.launch {
|
||||
_episodes.value = getEpisodes(seriesId, seasonId)
|
||||
try {
|
||||
_episodes.value = getEpisodes(seriesId, seasonId)
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e)
|
||||
_error.value = true
|
||||
}
|
||||
_finishedLoading.value = true
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,34 +2,54 @@
|
|||
<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="viewModel"
|
||||
type="dev.jdtech.jellyfin.viewmodels.LibraryViewModel" />
|
||||
</data>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
android:id="@+id/main_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".fragments.LibraryFragment">
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/items_recycler_view"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:clipToPadding="false"
|
||||
android:paddingHorizontal="12dp"
|
||||
android:paddingTop="16dp"
|
||||
app:items="@{viewModel.items}"
|
||||
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:spanCount="@integer/library_columns"
|
||||
tools:itemCount="6"
|
||||
tools:listitem="@layout/base_item" />
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".fragments.LibraryFragment">
|
||||
|
||||
<com.google.android.material.progressindicator.CircularProgressIndicator
|
||||
android:id="@+id/loading_indicator"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:indeterminate="true"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:trackCornerRadius="10dp" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/items_recycler_view"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:clipToPadding="false"
|
||||
android:paddingHorizontal="12dp"
|
||||
android:paddingTop="16dp"
|
||||
app:items="@{viewModel.items}"
|
||||
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:spanCount="@integer/library_columns"
|
||||
tools:itemCount="6"
|
||||
tools:listitem="@layout/base_item" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
||||
|
||||
|
|
|
@ -10,39 +10,45 @@
|
|||
type="dev.jdtech.jellyfin.viewmodels.MediaViewModel" />
|
||||
</data>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
android:id="@+id/main_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:animateLayoutChanges="true"
|
||||
tools:context=".fragments.MediaFragment">
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.google.android.material.progressindicator.CircularProgressIndicator
|
||||
android:id="@+id/loading_indicator"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:indeterminate="true"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:trackCornerRadius="10dp" />
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:animateLayoutChanges="true"
|
||||
tools:context=".fragments.MediaFragment">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/views_recycler_view"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:clipToPadding="false"
|
||||
android:paddingHorizontal="12dp"
|
||||
android:paddingTop="16dp"
|
||||
app:collections="@{viewModel.collections}"
|
||||
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:spanCount="@integer/collection_columns"
|
||||
tools:itemCount="4"
|
||||
tools:listitem="@layout/collection_item" />
|
||||
<com.google.android.material.progressindicator.CircularProgressIndicator
|
||||
android:id="@+id/loading_indicator"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:indeterminate="true"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:trackCornerRadius="10dp" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/views_recycler_view"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:clipToPadding="false"
|
||||
android:paddingHorizontal="12dp"
|
||||
android:paddingTop="16dp"
|
||||
app:collections="@{viewModel.collections}"
|
||||
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:spanCount="@integer/collection_columns"
|
||||
tools:itemCount="4"
|
||||
tools:listitem="@layout/collection_item" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
</layout>
|
||||
|
|
|
@ -12,366 +12,373 @@
|
|||
type="dev.jdtech.jellyfin.viewmodels.MediaInfoViewModel" />
|
||||
</data>
|
||||
|
||||
<ScrollView
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
android:id="@+id/main_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
tools:context=".fragments.MediaInfoFragment">
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="200dp"
|
||||
android:layout_marginBottom="8dp">
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
tools:context=".fragments.MediaInfoFragment">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/item_banner"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="200dp"
|
||||
android:scaleType="centerCrop"
|
||||
app:itemBackdropImage="@{viewModel.item}"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:ignore="ContentDescription" />
|
||||
android:layout_marginBottom="8dp">
|
||||
|
||||
<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" />
|
||||
<ImageView
|
||||
android:id="@+id/item_banner"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="200dp"
|
||||
android:scaleType="centerCrop"
|
||||
app:itemBackdropImage="@{viewModel.item}"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="24dp"
|
||||
android:text="@{viewModel.item.name}"
|
||||
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline5"
|
||||
app:layout_constraintBottom_toTopOf="@id/original_title"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:text="Alita: Battle Angel" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/original_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="24dp"
|
||||
android:text="@{viewModel.item.originalTitle}"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="24dp"
|
||||
android:layout_marginBottom="16dp">
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/year"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:text="@{viewModel.dateString}"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
tools:text="2019" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/playtime"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:text="@{viewModel.runTime}"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
tools:text="122 min" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/official_rating"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:text="@{viewModel.item.officialRating}"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
tools:text="PG-13" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/community_rating"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawablePadding="4dp"
|
||||
android:gravity="bottom"
|
||||
android:text="@{viewModel.item.communityRating.toString()}"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
app:drawableStartCompat="@drawable/ic_star"
|
||||
app:drawableTint="@color/yellow"
|
||||
tools:text="7.3" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="24dp"
|
||||
android:layout_marginBottom="24dp">
|
||||
|
||||
<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/trailer_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:background="@drawable/button_accent_background"
|
||||
android:contentDescription="@string/trailer_button_description"
|
||||
android:padding="12dp"
|
||||
android:src="@drawable/ic_film" />
|
||||
|
||||
<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
|
||||
android:id="@+id/info"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="24dp"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/genres_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:visibility="@{viewModel.item.genres.size() < 1 ? View.GONE : View.VISIBLE}">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/genres_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/genres"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
<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" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/genres"
|
||||
android:layout_width="0dp"
|
||||
android:id="@+id/name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="64dp"
|
||||
android:text="@{viewModel.genresString}"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:layout_marginHorizontal="24dp"
|
||||
android:text="@{viewModel.item.name}"
|
||||
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline5"
|
||||
app:layout_constraintBottom_toTopOf="@id/original_title"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="Action, Science Fiction, Adventure" />
|
||||
tools:text="Alita: Battle Angel" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/original_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="24dp"
|
||||
android:text="@{viewModel.item.originalTitle}"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/director_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:visibility="@{viewModel.director == null ? View.GONE : View.VISIBLE}">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/director_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/director"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/director"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="64dp"
|
||||
android:text="@{viewModel.director.name}"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="Robert Rodriguez" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/writers_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:visibility="@{viewModel.writers.size() < 1 ? View.GONE : View.VISIBLE}">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/writers_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/writers"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/writers"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="64dp"
|
||||
android:text="@{viewModel.writersString}"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="James Cameron, Laeta Kalogridis, Yukito Kishiro" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="24dp"
|
||||
android:layout_marginBottom="24dp"
|
||||
android:text="@{viewModel.item.overview}"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
tools:text="An angel falls. A warrior rises. When Alita awakens with no memory of who she is in a future world she does not recognize, she is taken in by Ido, a compassionate doctor who realizes that somewhere in this abandoned cyborg shell is the heart and soul of a young woman with an extraordinary past." />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="24dp"
|
||||
android:orientation="vertical"
|
||||
android:visibility="@{viewModel.nextUp != null ? View.VISIBLE : View.GONE}">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="24dp"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:text="@string/next_up"
|
||||
android:textAppearance="@style/TextAppearance.MaterialComponents.Subtitle1"
|
||||
android:textSize="18sp" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/next_up"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="24dp"
|
||||
android:foreground="?attr/selectableItemBackground"
|
||||
android:layout_marginBottom="16dp">
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/year"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:text="@{viewModel.dateString}"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
tools:text="2019" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/playtime"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:text="@{viewModel.runTime}"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
tools:text="122 min" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/official_rating"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:text="@{viewModel.item.officialRating}"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
tools:text="PG-13" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/community_rating"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawablePadding="4dp"
|
||||
android:gravity="bottom"
|
||||
android:text="@{viewModel.item.communityRating.toString()}"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
app:drawableStartCompat="@drawable/ic_star"
|
||||
app:drawableTint="@color/yellow"
|
||||
tools:text="7.3" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="24dp"
|
||||
android:layout_marginBottom="24dp">
|
||||
|
||||
<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/trailer_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:background="@drawable/button_accent_background"
|
||||
android:contentDescription="@string/trailer_button_description"
|
||||
android:padding="12dp"
|
||||
android:src="@drawable/ic_film" />
|
||||
|
||||
<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
|
||||
android:id="@+id/info"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="24dp"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.google.android.material.imageview.ShapeableImageView
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/genres_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:adjustViewBounds="true"
|
||||
app:itemPrimaryImage="@{viewModel.nextUp}"
|
||||
app:shapeAppearance="@style/roundedImageView" />
|
||||
android:layout_marginBottom="12dp"
|
||||
android:visibility="@{viewModel.item.genres.size() < 1 ? View.GONE : View.VISIBLE}">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/genres_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/genres"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/genres"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="64dp"
|
||||
android:text="@{viewModel.genresString}"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="Action, Science Fiction, Adventure" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/director_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:visibility="@{viewModel.director == null ? View.GONE : View.VISIBLE}">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/director_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/director"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/director"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="64dp"
|
||||
android:text="@{viewModel.director.name}"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="Robert Rodriguez" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/writers_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:visibility="@{viewModel.writers.size() < 1 ? View.GONE : View.VISIBLE}">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/writers_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/writers"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/writers"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="64dp"
|
||||
android:text="@{viewModel.writersString}"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="James Cameron, Laeta Kalogridis, Yukito Kishiro" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="24dp"
|
||||
android:layout_marginBottom="24dp"
|
||||
android:text="@{viewModel.item.overview}"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
tools:text="An angel falls. A warrior rises. When Alita awakens with no memory of who she is in a future world she does not recognize, she is taken in by Ido, a compassionate doctor who realizes that somewhere in this abandoned cyborg shell is the heart and soul of a young woman with an extraordinary past." />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="24dp"
|
||||
android:orientation="vertical"
|
||||
android:visibility="@{viewModel.nextUp != null ? View.VISIBLE : View.GONE}">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@{String.format(@string/episode_name_extended, viewModel.nextUp.parentIndexNumber, viewModel.nextUp.indexNumber, viewModel.nextUp.name)}"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
tools:text="The Girl Flautist" />
|
||||
android:layout_marginHorizontal="24dp"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:text="@string/next_up"
|
||||
android:textAppearance="@style/TextAppearance.MaterialComponents.Subtitle1"
|
||||
android:textSize="18sp" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/next_up"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="24dp"
|
||||
android:foreground="?attr/selectableItemBackground"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.google.android.material.imageview.ShapeableImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:adjustViewBounds="true"
|
||||
app:itemPrimaryImage="@{viewModel.nextUp}"
|
||||
app:shapeAppearance="@style/roundedImageView" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@{String.format(@string/episode_name_extended, viewModel.nextUp.parentIndexNumber, viewModel.nextUp.indexNumber, viewModel.nextUp.name)}"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
tools:text="The Girl Flautist" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="24dp"
|
||||
android:orientation="vertical"
|
||||
android:visibility="@{viewModel.seasons != null ? View.VISIBLE : View.GONE}">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="24dp"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:text="@string/seasons"
|
||||
android:textAppearance="@style/TextAppearance.MaterialComponents.Subtitle1"
|
||||
android:textSize="18sp" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/seasons_recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:clipToPadding="false"
|
||||
android:orientation="horizontal"
|
||||
android:paddingHorizontal="12dp"
|
||||
app:items="@{viewModel.seasons}"
|
||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||
tools:itemCount="3"
|
||||
tools:listitem="@layout/base_item" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/actors"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="24dp"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:text="@string/cast_amp_crew"
|
||||
android:textAppearance="@style/TextAppearance.MaterialComponents.Subtitle1"
|
||||
android:textSize="18sp" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/people_recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:clipToPadding="false"
|
||||
android:orientation="horizontal"
|
||||
android:paddingHorizontal="16dp"
|
||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||
app:people="@{viewModel.actors}"
|
||||
tools:itemCount="3"
|
||||
tools:listitem="@layout/person_item" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="24dp"
|
||||
android:orientation="vertical"
|
||||
android:visibility="@{viewModel.seasons != null ? View.VISIBLE : View.GONE}">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="24dp"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:text="@string/seasons"
|
||||
android:textAppearance="@style/TextAppearance.MaterialComponents.Subtitle1"
|
||||
android:textSize="18sp" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/seasons_recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:clipToPadding="false"
|
||||
android:orientation="horizontal"
|
||||
android:paddingHorizontal="12dp"
|
||||
app:items="@{viewModel.seasons}"
|
||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||
tools:itemCount="3"
|
||||
tools:listitem="@layout/base_item" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/actors"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="24dp"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:text="@string/cast_amp_crew"
|
||||
android:textAppearance="@style/TextAppearance.MaterialComponents.Subtitle1"
|
||||
android:textSize="18sp" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/people_recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:clipToPadding="false"
|
||||
android:orientation="horizontal"
|
||||
android:paddingHorizontal="16dp"
|
||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||
app:people="@{viewModel.actors}"
|
||||
tools:itemCount="3"
|
||||
tools:listitem="@layout/person_item" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
||||
</layout>
|
||||
|
|
|
@ -12,10 +12,27 @@
|
|||
|
||||
</data>
|
||||
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
android:id="@+id/main_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.google.android.material.progressindicator.CircularProgressIndicator
|
||||
android:id="@+id/loading_indicator"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:indeterminate="true"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:trackCornerRadius="10dp" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/episodes_recycler_view"
|
||||
android:layout_width="0dp"
|
||||
|
@ -30,5 +47,6 @@
|
|||
tools:itemCount="4"
|
||||
tools:listitem="@layout/episode_item" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
||||
</layout>
|
Loading…
Reference in a new issue