mirror of
https://github.com/recloudstream/cloudstream.git
synced 2024-08-15 01:53:11 +00:00
Merge branch 'master' of https://github.com/recloudstream/cloudstream into favorites-button-tv
This commit is contained in:
commit
e64d46f0a0
14 changed files with 236 additions and 36 deletions
|
@ -51,7 +51,7 @@ android {
|
|||
}
|
||||
|
||||
// https://developer.android.com/about/versions/14/behavior-changes-14#safer-dynamic-code-loading
|
||||
compileSdk = 33 // android 14 is fucked
|
||||
compileSdk = 34 // android 14 is fucked
|
||||
buildToolsVersion = "34.0.0"
|
||||
|
||||
defaultConfig {
|
||||
|
@ -157,7 +157,7 @@ dependencies {
|
|||
implementation("androidx.test.ext:junit-ktx:1.1.5")
|
||||
testImplementation("org.json:json:20230618")
|
||||
|
||||
implementation("androidx.core:core-ktx:1.10.1") // need 34 for higher
|
||||
implementation("androidx.core:core-ktx:1.12.0") // need 34 for higher
|
||||
implementation("androidx.appcompat:appcompat:1.6.1") // need target 32 for 1.5.0
|
||||
|
||||
// dont change this to 1.6.0 it looks ugly af
|
||||
|
@ -165,10 +165,10 @@ dependencies {
|
|||
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
|
||||
|
||||
// need 34 for higher
|
||||
implementation("androidx.navigation:navigation-fragment-ktx:2.6.0")
|
||||
implementation("androidx.navigation:navigation-ui-ktx:2.6.0")
|
||||
implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.6.1")
|
||||
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1")
|
||||
implementation("androidx.navigation:navigation-fragment-ktx:2.7.4")
|
||||
implementation("androidx.navigation:navigation-ui-ktx:2.7.4")
|
||||
implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.6.2")
|
||||
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2")
|
||||
|
||||
testImplementation("junit:junit:4.13.2")
|
||||
androidTestImplementation("androidx.test.ext:junit:1.1.5")
|
||||
|
|
|
@ -19,6 +19,7 @@ import com.lagradost.cloudstream3.databinding.FragmentSearchBinding
|
|||
import com.lagradost.cloudstream3.databinding.FragmentSearchTvBinding
|
||||
import com.lagradost.cloudstream3.databinding.HomeResultGridBinding
|
||||
import com.lagradost.cloudstream3.databinding.HomepageParentBinding
|
||||
import com.lagradost.cloudstream3.databinding.HomepageParentEmulatorBinding
|
||||
import com.lagradost.cloudstream3.databinding.HomepageParentTvBinding
|
||||
import com.lagradost.cloudstream3.databinding.PlayerCustomLayoutBinding
|
||||
import com.lagradost.cloudstream3.databinding.PlayerCustomLayoutTvBinding
|
||||
|
@ -119,8 +120,9 @@ class ExampleInstrumentedTest {
|
|||
// testAllLayouts<HomeScrollViewBinding>(activity, R.layout.home_scroll_view, R.layout.home_scroll_view_tv)
|
||||
// testAllLayouts<HomeScrollViewTvBinding>(activity, R.layout.home_scroll_view, R.layout.home_scroll_view_tv)
|
||||
|
||||
testAllLayouts<HomepageParentTvBinding>(activity, R.layout.homepage_parent_tv, R.layout.homepage_parent)
|
||||
testAllLayouts<HomepageParentBinding>(activity, R.layout.homepage_parent_tv, R.layout.homepage_parent)
|
||||
testAllLayouts<HomepageParentTvBinding>(activity, R.layout.homepage_parent_tv, R.layout.homepage_parent_emulator, R.layout.homepage_parent)
|
||||
testAllLayouts<HomepageParentEmulatorBinding>(activity, R.layout.homepage_parent_tv, R.layout.homepage_parent_emulator, R.layout.homepage_parent)
|
||||
testAllLayouts<HomepageParentBinding>(activity, R.layout.homepage_parent_tv, R.layout.homepage_parent_emulator, R.layout.homepage_parent)
|
||||
|
||||
testAllLayouts<FragmentLibraryTvBinding>(activity, R.layout.fragment_library_tv, R.layout.fragment_library)
|
||||
testAllLayouts<FragmentLibraryBinding>(activity, R.layout.fragment_library_tv, R.layout.fragment_library)
|
||||
|
|
|
@ -662,7 +662,7 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
|||
val isAtHome =
|
||||
navController?.currentDestination?.matchDestination(R.id.navigation_home) == true
|
||||
|
||||
if (isAtHome && isTrueTvSettings()) {
|
||||
if (isAtHome && isTvSettings()) {
|
||||
showConfirmExitDialog()
|
||||
} else {
|
||||
super.onBackPressed()
|
||||
|
|
|
@ -8,7 +8,7 @@ import com.lagradost.cloudstream3.syncproviders.SyncIdName
|
|||
import com.lagradost.cloudstream3.ui.WatchType
|
||||
import com.lagradost.cloudstream3.ui.library.ListSorting
|
||||
import com.lagradost.cloudstream3.ui.result.txt
|
||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings
|
||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings
|
||||
import com.lagradost.cloudstream3.utils.Coroutines.ioWork
|
||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.getAllFavorites
|
||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.getAllSubscriptions
|
||||
|
@ -71,14 +71,14 @@ class LocalList : SyncAPI {
|
|||
}?.distinctBy { it.first } ?: return null
|
||||
|
||||
val list = ioWork {
|
||||
val isTv = isTvSettings()
|
||||
val isTrueTv = isTrueTvSettings()
|
||||
|
||||
val baseMap = WatchType.values().filter { it != WatchType.NONE }.associate {
|
||||
// None is not something to display
|
||||
it.stringRes to emptyList<SyncAPI.LibraryItem>()
|
||||
} + mapOf(
|
||||
R.string.favorites_list_name to emptyList()
|
||||
) + if (!isTv) {
|
||||
) + if (!isTrueTv) {
|
||||
mapOf(
|
||||
R.string.subscription_list_name to emptyList()
|
||||
)
|
||||
|
@ -96,8 +96,8 @@ class LocalList : SyncAPI {
|
|||
it.toLibraryItem()
|
||||
})
|
||||
|
||||
// Don't show subscriptions or favorites on TV
|
||||
val result = if (isTv) {
|
||||
// Don't show subscriptions on TV
|
||||
val result = if (isTrueTv) {
|
||||
baseMap + watchStatusMap + favoritesMap
|
||||
} else {
|
||||
val subscriptionsMap = mapOf(R.string.subscription_list_name to getAllSubscriptions().mapNotNull {
|
||||
|
|
|
@ -15,7 +15,8 @@ import com.lagradost.cloudstream3.ui.result.FOCUS_SELF
|
|||
import com.lagradost.cloudstream3.ui.result.setLinearListLayout
|
||||
import com.lagradost.cloudstream3.ui.search.SearchClickCallback
|
||||
import com.lagradost.cloudstream3.ui.search.SearchFragment.Companion.filterSearchResponse
|
||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings
|
||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isEmulatorSettings
|
||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.isRecyclerScrollable
|
||||
|
||||
class LoadClickCallback(
|
||||
|
@ -34,11 +35,13 @@ open class ParentItemAdapter(
|
|||
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
|
||||
val root = LayoutInflater.from(parent.context).inflate(
|
||||
if (isTvSettings()) R.layout.homepage_parent_tv else R.layout.homepage_parent,
|
||||
parent,
|
||||
false
|
||||
)
|
||||
val layoutResId = when {
|
||||
isTrueTvSettings() -> R.layout.homepage_parent_tv
|
||||
parent.context.isEmulatorSettings() -> R.layout.homepage_parent_emulator
|
||||
else -> R.layout.homepage_parent
|
||||
}
|
||||
|
||||
val root = LayoutInflater.from(parent.context).inflate(layoutResId, parent, false)
|
||||
|
||||
val binding = HomepageParentBinding.bind(root)
|
||||
|
||||
|
@ -234,7 +237,7 @@ open class ParentItemAdapter(
|
|||
})
|
||||
|
||||
//(recyclerView.adapter as HomeChildItemAdapter).notifyDataSetChanged()
|
||||
if (!isTvSettings()) {
|
||||
if (!isTrueTvSettings()) {
|
||||
title.setOnClickListener {
|
||||
moreInfoClickCallback.invoke(expand)
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ import com.lagradost.cloudstream3.ui.result.setLinearListLayout
|
|||
import com.lagradost.cloudstream3.ui.search.SEARCH_ACTION_LOAD
|
||||
import com.lagradost.cloudstream3.ui.search.SEARCH_ACTION_SHOW_METADATA
|
||||
import com.lagradost.cloudstream3.ui.search.SearchClickCallback
|
||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isEmulatorSettings
|
||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings
|
||||
import com.lagradost.cloudstream3.utils.DataStoreHelper
|
||||
import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showBottomDialog
|
||||
|
@ -81,6 +82,28 @@ class HomeParentItemAdapterPreview(
|
|||
parent,
|
||||
false
|
||||
) else FragmentHomeHeadBinding.inflate(inflater, parent, false)
|
||||
|
||||
if (binding is FragmentHomeHeadTvBinding && parent.context.isEmulatorSettings()) {
|
||||
binding.homeBookmarkParentItemMoreInfo.isVisible = true
|
||||
|
||||
val marginInDp = 50
|
||||
val density = binding.horizontalScrollChips.context.resources.displayMetrics.density
|
||||
val marginInPixels = (marginInDp * density).toInt()
|
||||
|
||||
val params = binding.horizontalScrollChips.layoutParams as ViewGroup.MarginLayoutParams
|
||||
params.marginEnd = marginInPixels
|
||||
binding.horizontalScrollChips.layoutParams = params
|
||||
binding.homeWatchParentItemTitle.setCompoundDrawablesWithIntrinsicBounds(
|
||||
null,
|
||||
null,
|
||||
ContextCompat.getDrawable(
|
||||
parent.context,
|
||||
R.drawable.ic_baseline_arrow_forward_24
|
||||
),
|
||||
null
|
||||
)
|
||||
}
|
||||
|
||||
HeaderViewHolder(
|
||||
binding,
|
||||
viewModel,
|
||||
|
@ -553,12 +576,19 @@ class HomeParentItemAdapterPreview(
|
|||
resumeHolder.isVisible = resumeWatching.isNotEmpty()
|
||||
resumeAdapter.updateList(resumeWatching)
|
||||
|
||||
if (binding is FragmentHomeHeadBinding) {
|
||||
binding.homeWatchParentItemTitle.setOnClickListener {
|
||||
if (
|
||||
binding is FragmentHomeHeadBinding ||
|
||||
binding is FragmentHomeHeadTvBinding &&
|
||||
binding.root.context.isEmulatorSettings()
|
||||
) {
|
||||
val title = (binding as? FragmentHomeHeadBinding)?.homeWatchParentItemTitle
|
||||
?: (binding as? FragmentHomeHeadTvBinding)?.homeWatchParentItemTitle
|
||||
|
||||
title?.setOnClickListener {
|
||||
viewModel.popup(
|
||||
HomeViewModel.ExpandableHomepageList(
|
||||
HomePageList(
|
||||
binding.homeWatchParentItemTitle.text.toString(),
|
||||
title.text.toString(),
|
||||
resumeWatching,
|
||||
false
|
||||
), 1, false
|
||||
|
@ -576,8 +606,15 @@ class HomeParentItemAdapterPreview(
|
|||
bookmarkHolder.isVisible = visible
|
||||
bookmarkAdapter.updateList(list)
|
||||
|
||||
if (binding is FragmentHomeHeadBinding) {
|
||||
binding.homeBookmarkParentItemTitle.setOnClickListener {
|
||||
if (
|
||||
binding is FragmentHomeHeadBinding ||
|
||||
binding is FragmentHomeHeadTvBinding &&
|
||||
binding.root.context.isEmulatorSettings()
|
||||
) {
|
||||
val title = (binding as? FragmentHomeHeadBinding)?.homeBookmarkParentItemTitle
|
||||
?: (binding as? FragmentHomeHeadTvBinding)?.homeBookmarkParentItemTitle
|
||||
|
||||
title?.setOnClickListener {
|
||||
val items = toggleList.map { it.first }.filter { it.isChecked }
|
||||
if (items.isEmpty()) return@setOnClickListener // we don't want to show an empty dialog
|
||||
val textSum = items
|
||||
|
|
|
@ -247,7 +247,7 @@ class ResultFragmentTv : Fragment() {
|
|||
|
||||
binding?.apply {
|
||||
//episodesShadow.rotationX = 180.0f//if(episodesShadow.isRtl()) 180.0f else 0.0f
|
||||
|
||||
|
||||
val leftListener: View.OnFocusChangeListener =
|
||||
View.OnFocusChangeListener { _, hasFocus ->
|
||||
if (!hasFocus) return@OnFocusChangeListener
|
||||
|
@ -575,6 +575,7 @@ class ResultFragmentTv : Fragment() {
|
|||
observeNullable(viewModel.movie) { data ->
|
||||
binding?.apply {
|
||||
resultPlayMovie.isVisible = data is Resource.Success
|
||||
resultPlaySeries.isVisible = data == null
|
||||
seriesHolder.isVisible = data == null
|
||||
resultEpisodesShow.isVisible = data == null
|
||||
|
||||
|
@ -804,12 +805,14 @@ class ResultFragmentTv : Fragment() {
|
|||
R.drawable.profile_bg_red,
|
||||
R.drawable.profile_bg_teal
|
||||
).random()
|
||||
//Change poster crop area to 20% from Top
|
||||
backgroundPoster.cropYCenterOffsetPct = 0.20F
|
||||
|
||||
backgroundPoster.setImage(
|
||||
d.posterBackgroundImage ?: UiImage.Drawable(error),
|
||||
radius = 0,
|
||||
errorImageDrawable = error
|
||||
)
|
||||
|
||||
resultComingSoon.isVisible = d.comingSoon
|
||||
resultDataHolder.isGone = d.comingSoon
|
||||
UIHelper.populateChips(resultTag, d.tags)
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
package com.lagradost.cloudstream3.utils
|
||||
//Reference: https://stackoverflow.com/a/29055283
|
||||
import android.content.Context
|
||||
import android.graphics.Matrix
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.util.AttributeSet
|
||||
|
||||
class PercentageCropImageView : androidx.appcompat.widget.AppCompatImageView {
|
||||
private var mCropYCenterOffsetPct: Float? = null
|
||||
private var mCropXCenterOffsetPct: Float? = null
|
||||
constructor(context: Context?) : super(context!!)
|
||||
constructor(context: Context?, attrs: AttributeSet?) : super(context!!, attrs)
|
||||
constructor(
|
||||
context: Context?, attrs: AttributeSet?,
|
||||
defStyle: Int
|
||||
) : super(context!!, attrs, defStyle)
|
||||
|
||||
var cropYCenterOffsetPct: Float
|
||||
get() = mCropYCenterOffsetPct!!
|
||||
set(cropYCenterOffsetPct) {
|
||||
require(cropYCenterOffsetPct <= 1.0) { "Value too large: Must be <= 1.0" }
|
||||
mCropYCenterOffsetPct = cropYCenterOffsetPct
|
||||
}
|
||||
var cropXCenterOffsetPct: Float
|
||||
get() = mCropXCenterOffsetPct!!
|
||||
set(cropXCenterOffsetPct) {
|
||||
require(cropXCenterOffsetPct <= 1.0) { "Value too large: Must be <= 1.0" }
|
||||
mCropXCenterOffsetPct = cropXCenterOffsetPct
|
||||
}
|
||||
|
||||
private fun myConfigureBounds() {
|
||||
if (this.scaleType == ScaleType.MATRIX) {
|
||||
|
||||
val d = this.drawable
|
||||
if (d != null) {
|
||||
val dWidth = d.intrinsicWidth
|
||||
val dHeight = d.intrinsicHeight
|
||||
val m = Matrix()
|
||||
val vWidth = width - this.paddingLeft - this.paddingRight
|
||||
val vHeight = height - this.paddingTop - this.paddingBottom
|
||||
val scale: Float
|
||||
var dx = 0f
|
||||
var dy = 0f
|
||||
if (dWidth * vHeight > vWidth * dHeight) {
|
||||
val cropXCenterOffsetPct =
|
||||
if (mCropXCenterOffsetPct != null) mCropXCenterOffsetPct!!.toFloat() else 0.5f
|
||||
scale = vHeight.toFloat() / dHeight.toFloat()
|
||||
dx = (vWidth - dWidth * scale) * cropXCenterOffsetPct
|
||||
} else {
|
||||
val cropYCenterOffsetPct =
|
||||
if (mCropYCenterOffsetPct != null) mCropYCenterOffsetPct!!.toFloat() else 0f
|
||||
scale = vWidth.toFloat() / dWidth.toFloat()
|
||||
dy = (vHeight - dHeight * scale) * cropYCenterOffsetPct
|
||||
}
|
||||
m.setScale(scale, scale)
|
||||
m.postTranslate((dx + 0.5f).toInt().toFloat(), (dy + 0.5f).toInt().toFloat())
|
||||
this.imageMatrix = m
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// These 3 methods call configureBounds in ImageView.java class, which
|
||||
// adjusts the matrix in a call to center_crop (android's built-in
|
||||
// scaling and centering crop method). We also want to trigger
|
||||
// in the same place, but using our own matrix, which is then set
|
||||
// directly at line 588 of ImageView.java and then copied over
|
||||
// as the draw matrix at line 942 of ImageView.java
|
||||
override fun setFrame(l: Int, t: Int, r: Int, b: Int): Boolean {
|
||||
val changed = super.setFrame(l, t, r, b)
|
||||
myConfigureBounds()
|
||||
return changed
|
||||
}
|
||||
|
||||
override fun setImageDrawable(d: Drawable?) {
|
||||
super.setImageDrawable(d)
|
||||
myConfigureBounds()
|
||||
}
|
||||
|
||||
override fun setImageResource(resId: Int) {
|
||||
super.setImageResource(resId)
|
||||
myConfigureBounds()
|
||||
}
|
||||
// In case you can change the ScaleType in code you have to call redraw()
|
||||
//fullsizeImageView.setScaleType(ScaleType.FIT_CENTER);
|
||||
//fullsizeImageView.redraw();
|
||||
fun redraw() {
|
||||
val d = this.drawable
|
||||
if (d != null) {
|
||||
// Force toggle to recalculate our bounds
|
||||
setImageDrawable(null)
|
||||
setImageDrawable(d)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -178,9 +178,10 @@ object UIHelper {
|
|||
fun Activity?.navigate(@IdRes navigation: Int, arguments: Bundle? = null) {
|
||||
try {
|
||||
if (this is FragmentActivity) {
|
||||
(supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as? NavHostFragment?)?.navController?.navigate(
|
||||
navigation, arguments
|
||||
)
|
||||
val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as? NavHostFragment?
|
||||
navHostFragment?.navController?.let {
|
||||
it.navigate(navigation, arguments)
|
||||
}
|
||||
}
|
||||
} catch (t: Throwable) {
|
||||
logError(t)
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
android:layout_margin="5dp"
|
||||
android:foreground="@drawable/outline_drawable"
|
||||
app:cardBackgroundColor="@color/transparent"
|
||||
|
||||
android:focusable="true"
|
||||
app:cardCornerRadius="@dimen/rounded_image_radius"
|
||||
app:cardElevation="0dp">
|
||||
|
||||
|
|
|
@ -232,7 +232,9 @@
|
|||
android:layout_marginStart="@dimen/navbar_width"
|
||||
android:layout_marginEnd="0dp"
|
||||
android:padding="12dp"
|
||||
android:text="@string/continue_watching" />
|
||||
android:text="@string/continue_watching"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
app:drawableTint="?attr/white" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/home_watch_child_recyclerview"
|
||||
|
@ -258,7 +260,15 @@
|
|||
android:visibility="gone"
|
||||
tools:visibility="visible">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/home_bookmark_parent_item_title"
|
||||
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?android:attr/selectableItemBackground">
|
||||
|
||||
<HorizontalScrollView
|
||||
android:id="@+id/horizontal_scroll_chips"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:fadingEdge="horizontal"
|
||||
|
@ -344,6 +354,18 @@
|
|||
</com.google.android.material.chip.ChipGroup>
|
||||
</HorizontalScrollView>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/home_bookmark_parent_item_more_info"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="end"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:contentDescription="@string/home_more_info"
|
||||
android:src="@drawable/ic_baseline_arrow_forward_24"
|
||||
android:visibility="gone"
|
||||
app:drawableTint="?attr/white" />
|
||||
</FrameLayout>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/home_bookmarked_child_recyclerview"
|
||||
android:layout_width="wrap_content"
|
||||
|
|
|
@ -140,6 +140,7 @@
|
|||
android:layout_gravity="end"
|
||||
android:background="@drawable/player_button_tv_attr_no_bg"
|
||||
android:contentDescription="@string/account"
|
||||
android:focusable="true"
|
||||
android:nextFocusLeft="@id/home_preview_search_button"
|
||||
android:nextFocusRight="@id/home_switch_account"
|
||||
android:nextFocusDown="@id/home_change_api"
|
||||
|
|
|
@ -130,14 +130,15 @@ https://developer.android.com/design/ui/tv/samples/jet-fit
|
|||
android:layout_height="250dp"
|
||||
android:visibility="visible">
|
||||
|
||||
<ImageView
|
||||
<com.lagradost.cloudstream3.utils.PercentageCropImageView
|
||||
android:id="@+id/background_poster"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="275dp"
|
||||
android:layout_gravity="center"
|
||||
android:alpha="0.8"
|
||||
android:scaleType="centerCrop"
|
||||
tools:src="@drawable/profile_bg_dark_blue" />
|
||||
android:scaleType="matrix"
|
||||
tools:src="@drawable/profile_bg_dark_blue" >
|
||||
</com.lagradost.cloudstream3.utils.PercentageCropImageView>
|
||||
|
||||
<ImageView
|
||||
android:layout_width="match_parent"
|
||||
|
@ -417,6 +418,7 @@ https://developer.android.com/design/ui/tv/samples/jet-fit
|
|||
android:fadingEdgeLength="30dp"
|
||||
android:foreground="@drawable/outline_drawable"
|
||||
android:maxLines="7"
|
||||
android:focusable="true"
|
||||
android:nextFocusUp="@id/result_back"
|
||||
android:nextFocusDown="@id/result_bookmark_button"
|
||||
android:padding="5dp"
|
||||
|
|
35
app/src/main/res/layout/homepage_parent_emulator.xml
Normal file
35
app/src/main/res/layout/homepage_parent_emulator.xml
Normal file
|
@ -0,0 +1,35 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout 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="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/home_child_more_info"
|
||||
style="@style/WatchHeaderText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/navbar_width"
|
||||
android:layout_marginEnd="0dp"
|
||||
android:padding="12dp"
|
||||
tools:text="@string/continue_watching"
|
||||
app:drawableRightCompat="@drawable/ic_baseline_arrow_forward_24"
|
||||
app:drawableTint="?attr/white"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:contentDescription="@string/home_more_info"/>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/home_child_recyclerview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:clipToPadding="false"
|
||||
android:descendantFocusability="afterDescendants"
|
||||
android:nextFocusUp="@id/home_child_more_info"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="@dimen/navbar_width"
|
||||
android:paddingEnd="5dp"
|
||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||
tools:listitem="@layout/home_result_grid" />
|
||||
</LinearLayout>
|
Loading…
Add table
Add a link
Reference in a new issue