mirror of
https://github.com/mediathekview/zapp.git
synced 2024-09-20 12:22:15 +02:00
Add tab navigation
This commit is contained in:
parent
51acdbc16c
commit
c1a2941f54
@ -169,4 +169,5 @@ dependencies {
|
||||
|
||||
// android tv
|
||||
implementation 'androidx.leanback:leanback:1.0.0'
|
||||
implementation "androidx.leanback:leanback-tab:1.1.0-beta01"
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
@ -11,7 +11,7 @@ class ErrorFragment : ErrorSupportFragment() {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
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)
|
||||
imageDrawable = ContextCompat.getDrawable(requireContext(), R.drawable.ic_sad_tv)
|
||||
|
@ -5,40 +5,34 @@ 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.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(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
val binding = TvFragmentMainBinding.inflate(inflater, container, false)
|
||||
_binding = TvFragmentMainBinding.inflate(inflater, container, false)
|
||||
|
||||
channelList = SortableVisibleJsonChannelList(requireContext())
|
||||
|
||||
binding.grid.setNumColumns(2)
|
||||
binding.grid.adapter = ChannelListAdapter(channelList, this, this)
|
||||
binding.viewpager.adapter = MainNavPagerAdapter(requireContext(), requireFragmentManager())
|
||||
binding.tabs.setupWithViewPager(binding.viewpager)
|
||||
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onItemClick(channel: ChannelModel) {
|
||||
val intent = PlayerActivity.getStartIntent(requireContext(), channel)
|
||||
startActivity(intent)
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
}
|
||||
|
||||
override fun onItemLongClick(channel: ChannelModel, view: View) {
|
||||
// no action
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
binding.viewpager.requestFocus()
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
23
app/src/main/res/layout/tv_fragment_channel_list.xml
Normal file
23
app/src/main/res/layout/tv_fragment_channel_list.xml
Normal 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>
|
@ -1,23 +1,26 @@
|
||||
<?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">
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.leanback.widget.VerticalGridView
|
||||
android:id="@+id/grid"
|
||||
<androidx.leanback.tab.LeanbackTabLayout
|
||||
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_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" />
|
||||
app:layout_constraintTop_toBottomOf="@id/tabs">
|
||||
|
||||
</androidx.leanback.tab.LeanbackViewPager>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
@ -79,6 +79,7 @@
|
||||
<string name="menu_refresh">Refresh</string>
|
||||
<string name="menu_retry">Reload</string>
|
||||
<string name="menu_about">About Zapp</string>
|
||||
<string name="menu_about_short">About</string>
|
||||
<string name="menu_settings">Settings</string>
|
||||
<string name="menu_feedback">Feedback</string>
|
||||
<string name="menu_filter">Filter</string>
|
||||
|
@ -79,6 +79,7 @@
|
||||
<string name="menu_refresh">Aktualisieren</string>
|
||||
<string name="menu_retry">Wiederholen</string>
|
||||
<string name="menu_about">Über Zapp</string>
|
||||
<string name="menu_about_short">Über</string>
|
||||
<string name="menu_settings">Einstellungen</string>
|
||||
<string name="menu_feedback">Feedback</string>
|
||||
<string name="menu_filter">Filter</string>
|
||||
|
Loading…
Reference in New Issue
Block a user