0
0
mirror of https://github.com/mediathekview/zapp.git synced 2024-09-20 20:23:04 +02:00

Add tab navigation

This commit is contained in:
Christine Coenen 2021-11-18 10:18:06 +01:00
parent 51acdbc16c
commit c1a2941f54
9 changed files with 138 additions and 32 deletions

View File

@ -169,4 +169,5 @@ dependencies {
// android tv // android tv
implementation 'androidx.leanback:leanback:1.0.0' implementation 'androidx.leanback:leanback:1.0.0'
implementation "androidx.leanback:leanback-tab:1.1.0-beta01"
} }

View File

@ -0,0 +1,44 @@
package de.christinecoenen.code.zapp.tv.channels
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import de.christinecoenen.code.zapp.app.livestream.ui.list.adapter.ChannelListAdapter
import de.christinecoenen.code.zapp.app.livestream.ui.list.adapter.ListItemListener
import de.christinecoenen.code.zapp.databinding.TvFragmentChannelListBinding
import de.christinecoenen.code.zapp.models.channels.ChannelModel
import de.christinecoenen.code.zapp.models.channels.ISortableChannelList
import de.christinecoenen.code.zapp.models.channels.json.SortableVisibleJsonChannelList
import de.christinecoenen.code.zapp.tv.player.PlayerActivity
class ChannelListFragment : Fragment(), ListItemListener {
private lateinit var channelList: ISortableChannelList
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
val binding = TvFragmentChannelListBinding.inflate(inflater, container, false)
channelList = SortableVisibleJsonChannelList(requireContext())
binding.grid.setNumColumns(2)
binding.grid.adapter = ChannelListAdapter(channelList, this, this)
return binding.root
}
override fun onItemClick(channel: ChannelModel) {
val intent = PlayerActivity.getStartIntent(requireContext(), channel)
startActivity(intent)
}
override fun onItemLongClick(channel: ChannelModel, view: View) {
// no action
}
}

View File

@ -11,7 +11,7 @@ class ErrorFragment : ErrorSupportFragment() {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
message = activity?.intent?.getStringExtra(ErrorActivity.EXTRA_MESSAGE) message = activity?.intent?.getStringExtra(ErrorActivity.EXTRA_MESSAGE)
?: throw IllegalArgumentException("message extra has to be set") //?: throw IllegalArgumentException("message extra has to be set")
title = getString(R.string.error_informal) title = getString(R.string.error_informal)
imageDrawable = ContextCompat.getDrawable(requireContext(), R.drawable.ic_sad_tv) imageDrawable = ContextCompat.getDrawable(requireContext(), R.drawable.ic_sad_tv)

View File

@ -5,40 +5,34 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import de.christinecoenen.code.zapp.app.livestream.ui.list.adapter.ChannelListAdapter
import de.christinecoenen.code.zapp.app.livestream.ui.list.adapter.ListItemListener
import de.christinecoenen.code.zapp.databinding.TvFragmentMainBinding import de.christinecoenen.code.zapp.databinding.TvFragmentMainBinding
import de.christinecoenen.code.zapp.models.channels.ChannelModel
import de.christinecoenen.code.zapp.models.channels.ISortableChannelList
import de.christinecoenen.code.zapp.models.channels.json.SortableVisibleJsonChannelList
import de.christinecoenen.code.zapp.tv.player.PlayerActivity
class MainFragment : Fragment(), ListItemListener { class MainFragment : Fragment() {
private lateinit var channelList: ISortableChannelList private var _binding: TvFragmentMainBinding? = null
private val binding: TvFragmentMainBinding get() = _binding!!
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
container: ViewGroup?, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View { ): View {
val binding = TvFragmentMainBinding.inflate(inflater, container, false) _binding = TvFragmentMainBinding.inflate(inflater, container, false)
channelList = SortableVisibleJsonChannelList(requireContext()) binding.viewpager.adapter = MainNavPagerAdapter(requireContext(), requireFragmentManager())
binding.tabs.setupWithViewPager(binding.viewpager)
binding.grid.setNumColumns(2)
binding.grid.adapter = ChannelListAdapter(channelList, this, this)
return binding.root return binding.root
} }
override fun onItemClick(channel: ChannelModel) { override fun onDestroyView() {
val intent = PlayerActivity.getStartIntent(requireContext(), channel) super.onDestroyView()
startActivity(intent) _binding = null
} }
override fun onItemLongClick(channel: ChannelModel, view: View) { override fun onResume() {
// no action super.onResume()
binding.viewpager.requestFocus()
} }
} }

View File

@ -0,0 +1,39 @@
package de.christinecoenen.code.zapp.tv.main
import android.content.Context
import androidx.annotation.StringRes
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentPagerAdapter
import de.christinecoenen.code.zapp.R
import de.christinecoenen.code.zapp.tv.channels.ChannelListFragment
import kotlin.reflect.KClass
class MainNavPagerAdapter(
private val context: Context,
fragmentManger: FragmentManager
) : FragmentPagerAdapter(fragmentManger) {
private val navItems = listOf(
MainNavItem(R.string.activity_main_tab_live, ChannelListFragment::class),
MainNavItem(R.string.menu_about_short, ChannelListFragment::class),
)
override fun getCount(): Int = navItems.size
override fun getItem(position: Int): Fragment {
return navItems[position].createFragment()
}
override fun getPageTitle(position: Int): CharSequence {
return navItems[position].getTitle(context)
}
private data class MainNavItem<T : Fragment>(
@StringRes val titleResId: Int,
val fragmentClass: KClass<T>
) {
fun createFragment(): T = fragmentClass.java.newInstance()
fun getTitle(context: Context) = context.getString(titleResId)
}
}

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingHorizontal="64dp">
<androidx.leanback.widget.VerticalGridView
android:id="@+id/grid"
android:layout_width="match_parent"
android:layout_height="0dp"
android:clipToPadding="false"
android:horizontalSpacing="16dp"
android:paddingTop="64dp"
android:paddingBottom="16dp"
android:verticalSpacing="8dp"
app:focusOutFront="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:listitem="@layout/fragment_channel_list_item" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,23 +1,26 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent">
android:paddingHorizontal="64dp">
<androidx.leanback.widget.VerticalGridView <androidx.leanback.tab.LeanbackTabLayout
android:id="@+id/grid" android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorPrimary"
android:theme="@style/Theme.AppCompat"
app:layout_constraintTop_toTopOf="parent"
app:tabIndicatorColor="@android:color/white"
app:tabTextAppearance="@style/TextAppearance.Leanback.ImageCardView.Title" />
<androidx.leanback.tab.LeanbackViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="0dp"
android:clipToPadding="false"
android:horizontalSpacing="16dp"
android:paddingTop="64dp"
android:paddingBottom="16dp"
android:verticalSpacing="8dp"
app:focusOutFront="true"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toBottomOf="@id/tabs">
tools:listitem="@layout/fragment_channel_list_item" />
</androidx.leanback.tab.LeanbackViewPager>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -79,6 +79,7 @@
<string name="menu_refresh">Refresh</string> <string name="menu_refresh">Refresh</string>
<string name="menu_retry">Reload</string> <string name="menu_retry">Reload</string>
<string name="menu_about">About Zapp</string> <string name="menu_about">About Zapp</string>
<string name="menu_about_short">About</string>
<string name="menu_settings">Settings</string> <string name="menu_settings">Settings</string>
<string name="menu_feedback">Feedback</string> <string name="menu_feedback">Feedback</string>
<string name="menu_filter">Filter</string> <string name="menu_filter">Filter</string>

View File

@ -79,6 +79,7 @@
<string name="menu_refresh">Aktualisieren</string> <string name="menu_refresh">Aktualisieren</string>
<string name="menu_retry">Wiederholen</string> <string name="menu_retry">Wiederholen</string>
<string name="menu_about">Über Zapp</string> <string name="menu_about">Über Zapp</string>
<string name="menu_about_short">Über</string>
<string name="menu_settings">Einstellungen</string> <string name="menu_settings">Einstellungen</string>
<string name="menu_feedback">Feedback</string> <string name="menu_feedback">Feedback</string>
<string name="menu_filter">Filter</string> <string name="menu_filter">Filter</string>