mirror of
https://github.com/recloudstream/cloudstream.git
synced 2024-08-15 01:53:11 +00:00
focus fix + rtl fix
This commit is contained in:
parent
a1824c86a3
commit
c98f35fd94
13 changed files with 284 additions and 126 deletions
|
@ -13,16 +13,15 @@ import android.os.Bundle
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.*
|
import android.view.*
|
||||||
import android.view.animation.Animation
|
|
||||||
import android.view.animation.AnimationSet
|
|
||||||
import android.widget.LinearLayout
|
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.activity.result.ActivityResultLauncher
|
import androidx.activity.result.ActivityResultLauncher
|
||||||
import androidx.annotation.IdRes
|
import androidx.annotation.IdRes
|
||||||
|
import androidx.annotation.MainThread
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.constraintlayout.widget.ConstraintLayout
|
import androidx.constraintlayout.widget.ConstraintLayout
|
||||||
import androidx.core.view.doOnLayout
|
import androidx.core.animation.addListener
|
||||||
|
import androidx.core.view.ViewCompat
|
||||||
import androidx.core.view.isGone
|
import androidx.core.view.isGone
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.fragment.app.FragmentActivity
|
import androidx.fragment.app.FragmentActivity
|
||||||
|
@ -35,22 +34,12 @@ import androidx.navigation.NavOptions
|
||||||
import androidx.navigation.fragment.NavHostFragment
|
import androidx.navigation.fragment.NavHostFragment
|
||||||
import androidx.navigation.ui.setupWithNavController
|
import androidx.navigation.ui.setupWithNavController
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
|
||||||
import androidx.transition.ChangeBounds
|
|
||||||
import androidx.transition.ChangeTransform
|
|
||||||
import androidx.transition.Scene
|
|
||||||
import androidx.transition.TransitionManager
|
|
||||||
import androidx.transition.TransitionManager.beginDelayedTransition
|
|
||||||
import androidx.transition.TransitionSet
|
|
||||||
import com.fasterxml.jackson.databind.DeserializationFeature
|
import com.fasterxml.jackson.databind.DeserializationFeature
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper
|
import com.fasterxml.jackson.databind.ObjectMapper
|
||||||
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
||||||
import com.google.android.gms.cast.framework.*
|
import com.google.android.gms.cast.framework.*
|
||||||
import com.google.android.material.bottomnavigation.BottomNavigationView
|
import com.google.android.material.bottomnavigation.BottomNavigationView
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||||
import com.google.android.material.button.MaterialButton
|
|
||||||
import com.google.android.material.navigationrail.NavigationRailView
|
import com.google.android.material.navigationrail.NavigationRailView
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import com.jaredrummler.android.colorpicker.ColorPickerDialogListener
|
import com.jaredrummler.android.colorpicker.ColorPickerDialogListener
|
||||||
|
@ -108,6 +97,7 @@ import com.lagradost.cloudstream3.ui.setup.SetupFragmentExtensions
|
||||||
import com.lagradost.cloudstream3.utils.*
|
import com.lagradost.cloudstream3.utils.*
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.html
|
import com.lagradost.cloudstream3.utils.AppUtils.html
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.isCastApiAvailable
|
import com.lagradost.cloudstream3.utils.AppUtils.isCastApiAvailable
|
||||||
|
import com.lagradost.cloudstream3.utils.AppUtils.isLtr
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.isNetworkAvailable
|
import com.lagradost.cloudstream3.utils.AppUtils.isNetworkAvailable
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.loadCache
|
import com.lagradost.cloudstream3.utils.AppUtils.loadCache
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.loadRepository
|
import com.lagradost.cloudstream3.utils.AppUtils.loadRepository
|
||||||
|
@ -131,6 +121,7 @@ import com.lagradost.cloudstream3.utils.UIHelper.getResourceColor
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard
|
import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.navigate
|
import com.lagradost.cloudstream3.utils.UIHelper.navigate
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.requestRW
|
import com.lagradost.cloudstream3.utils.UIHelper.requestRW
|
||||||
|
import com.lagradost.cloudstream3.utils.UIHelper.toPx
|
||||||
import com.lagradost.nicehttp.Requests
|
import com.lagradost.nicehttp.Requests
|
||||||
import com.lagradost.nicehttp.ResponseParser
|
import com.lagradost.nicehttp.ResponseParser
|
||||||
import kotlinx.coroutines.sync.Mutex
|
import kotlinx.coroutines.sync.Mutex
|
||||||
|
@ -140,6 +131,7 @@ import java.lang.ref.WeakReference
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
import java.net.URLDecoder
|
import java.net.URLDecoder
|
||||||
import java.nio.charset.Charset
|
import java.nio.charset.Charset
|
||||||
|
import kotlin.math.absoluteValue
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
import kotlin.system.exitProcess
|
import kotlin.system.exitProcess
|
||||||
|
|
||||||
|
@ -472,13 +464,24 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
||||||
|
|
||||||
binding?.navHostFragment?.apply {
|
binding?.navHostFragment?.apply {
|
||||||
val params = layoutParams as ConstraintLayout.LayoutParams
|
val params = layoutParams as ConstraintLayout.LayoutParams
|
||||||
|
val push = if (!dontPush && isTvSettings()) resources.getDimensionPixelSize(R.dimen.navbar_width) else 0
|
||||||
|
|
||||||
|
if(!this.isLtr()) {
|
||||||
params.setMargins(
|
params.setMargins(
|
||||||
if (!dontPush && isTvSettings()) resources.getDimensionPixelSize(R.dimen.navbar_width) else 0,
|
params.leftMargin,
|
||||||
|
params.topMargin,
|
||||||
|
push,
|
||||||
|
params.bottomMargin
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
params.setMargins(
|
||||||
|
push,
|
||||||
params.topMargin,
|
params.topMargin,
|
||||||
params.rightMargin,
|
params.rightMargin,
|
||||||
params.bottomMargin
|
params.bottomMargin
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
layoutParams = params
|
layoutParams = params
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -572,9 +575,22 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun dispatchKeyEvent(event: KeyEvent?): Boolean {
|
override fun dispatchKeyEvent(event: KeyEvent?): Boolean {
|
||||||
CommonActivity.dispatchKeyEvent(this, event)?.let {
|
val start = System.currentTimeMillis()
|
||||||
return it
|
try {
|
||||||
|
val response = CommonActivity.dispatchKeyEvent(this, event)
|
||||||
|
|
||||||
|
if (response != null)
|
||||||
|
return response
|
||||||
|
} finally {
|
||||||
|
debugAssert({
|
||||||
|
val end = System.currentTimeMillis()
|
||||||
|
val delta = end - start
|
||||||
|
delta > 100
|
||||||
|
}) {
|
||||||
|
"Took over 100ms to navigate, smth is VERY wrong"
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return super.dispatchKeyEvent(event)
|
return super.dispatchKeyEvent(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -745,15 +761,40 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
private var binding: ActivityMainBinding? = null
|
private var binding: ActivityMainBinding? = null
|
||||||
private var focusOutline: WeakReference<View> = WeakReference(null)
|
|
||||||
private var lastFocus: WeakReference<View> = WeakReference(null)
|
object TvFocus {
|
||||||
|
data class FocusTarget(
|
||||||
|
val width: Int,
|
||||||
|
val height: Int,
|
||||||
|
val x: Float,
|
||||||
|
val y: Float,
|
||||||
|
) {
|
||||||
|
companion object {
|
||||||
|
fun lerp(a: FocusTarget, b: FocusTarget, lerp: Float): FocusTarget {
|
||||||
|
val ilerp = 1 - lerp
|
||||||
|
return FocusTarget(
|
||||||
|
width = (a.width * ilerp + b.width * lerp).toInt(),
|
||||||
|
height = (a.height * ilerp + b.height * lerp).toInt(),
|
||||||
|
x = a.x * ilerp + b.x * lerp,
|
||||||
|
y = a.y * ilerp + b.y * lerp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var last: FocusTarget = FocusTarget(0, 0, 0.0f, 0.0f)
|
||||||
|
var current: FocusTarget = FocusTarget(0, 0, 0.0f, 0.0f)
|
||||||
|
|
||||||
|
var focusOutline: WeakReference<View> = WeakReference(null)
|
||||||
|
var lastFocus: WeakReference<View> = WeakReference(null)
|
||||||
private val layoutListener: View.OnLayoutChangeListener =
|
private val layoutListener: View.OnLayoutChangeListener =
|
||||||
View.OnLayoutChangeListener { v, _, _, _, _, _, _, _, _ ->
|
View.OnLayoutChangeListener { v, _, _, _, _, _, _, _, _ ->
|
||||||
updateFocusView(
|
updateFocusView(
|
||||||
v
|
v, same = true
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
private val attachListener : View.OnAttachStateChangeListener = object : View.OnAttachStateChangeListener {
|
private val attachListener: View.OnAttachStateChangeListener =
|
||||||
|
object : View.OnAttachStateChangeListener {
|
||||||
override fun onViewAttachedToWindow(v: View) {
|
override fun onViewAttachedToWindow(v: View) {
|
||||||
updateFocusView(v)
|
updateFocusView(v)
|
||||||
}
|
}
|
||||||
|
@ -764,44 +805,120 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateFocusView(newFocus: View?) {
|
private fun setTargetPosition(target: FocusTarget) {
|
||||||
|
focusOutline.get()?.apply {
|
||||||
|
layoutParams = layoutParams?.apply {
|
||||||
|
width = target.width
|
||||||
|
height = target.height
|
||||||
|
}
|
||||||
|
|
||||||
|
translationX = target.x
|
||||||
|
translationY = target.y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var animator: ValueAnimator? = null
|
||||||
|
|
||||||
|
@MainThread
|
||||||
|
fun updateFocusView(newFocus: View?, same: Boolean = false) {
|
||||||
val focusOutline = focusOutline.get() ?: return
|
val focusOutline = focusOutline.get() ?: return
|
||||||
lastFocus.get()?.removeOnLayoutChangeListener(layoutListener)
|
lastFocus.get()?.apply {
|
||||||
lastFocus.get()?.removeOnAttachStateChangeListener(attachListener)
|
removeOnLayoutChangeListener(layoutListener)
|
||||||
|
removeOnAttachStateChangeListener(attachListener)
|
||||||
|
}
|
||||||
|
|
||||||
val wasGone = focusOutline.isGone
|
val wasGone = focusOutline.isGone
|
||||||
|
|
||||||
val visible =
|
val visible =
|
||||||
newFocus != null && newFocus.measuredHeight > 0 && newFocus.measuredWidth > 0 && newFocus.isShown && newFocus.tag != "tv_no_focus_tag"
|
newFocus != null && newFocus.measuredHeight > 0 && newFocus.measuredWidth > 0 && newFocus.isShown && newFocus.tag != "tv_no_focus_tag"
|
||||||
focusOutline.isVisible = visible
|
focusOutline.isVisible = visible
|
||||||
|
|
||||||
if (newFocus != null) {
|
if (newFocus != null) {
|
||||||
lastFocus = WeakReference(newFocus)
|
lastFocus = WeakReference(newFocus)
|
||||||
|
|
||||||
val out = IntArray(2)
|
val out = IntArray(2)
|
||||||
newFocus.getLocationInWindow(out)
|
newFocus.getLocationInWindow(out)
|
||||||
val (x, y) = out
|
val (screenX, screenY) = out
|
||||||
|
var (x,y) = screenX.toFloat() to screenY.toFloat()
|
||||||
|
val (currentX, currentY) = focusOutline.translationX to focusOutline.translationY
|
||||||
|
// println(">><<< $x $y $currentX $currentY")
|
||||||
|
if(!newFocus.isLtr()) {
|
||||||
|
x = x - focusOutline.rootView.width + newFocus.measuredWidth
|
||||||
|
}
|
||||||
|
|
||||||
// out of bounds = 0,0
|
// out of bounds = 0,0
|
||||||
if(x == 0 && y == 0) {
|
if (screenX == 0 && screenY == 0) {
|
||||||
focusOutline.isVisible = false
|
focusOutline.isVisible = false
|
||||||
}
|
}
|
||||||
/*(newFocus.parent as? RecyclerView)?.let { recycle ->
|
|
||||||
println("PARET IS RECYLE")
|
|
||||||
val position = recycle.getChildAdapterPosition(newFocus)
|
|
||||||
recycle.scrollToPosition(position)
|
|
||||||
|
|
||||||
(recycle.layoutManager as? GridLayoutManager)?.let {
|
|
||||||
if(it.orientation == LinearLayout.HORIZONTAL) {
|
|
||||||
println("SCROLL")
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}*/
|
|
||||||
newFocus.addOnLayoutChangeListener(layoutListener)
|
newFocus.addOnLayoutChangeListener(layoutListener)
|
||||||
newFocus.addOnAttachStateChangeListener(attachListener)
|
newFocus.addOnAttachStateChangeListener(attachListener)
|
||||||
|
|
||||||
// val set = AnimationSet(true)
|
val start = FocusTarget(
|
||||||
if(!wasGone) {
|
x = currentX,
|
||||||
|
y = currentY,
|
||||||
|
width = focusOutline.measuredWidth,
|
||||||
|
height = focusOutline.measuredHeight
|
||||||
|
)
|
||||||
|
val end = FocusTarget(
|
||||||
|
x = x,
|
||||||
|
y = y,
|
||||||
|
width = newFocus.measuredWidth,
|
||||||
|
height = newFocus.measuredHeight
|
||||||
|
)
|
||||||
|
|
||||||
|
// if they are the same within then snap, aka scrolling
|
||||||
|
val deltaMin = 50.toPx
|
||||||
|
if (start.width == end.width && start.height == end.height && (start.x - end.x).absoluteValue < deltaMin && (start.y - end.y).absoluteValue < deltaMin) {
|
||||||
|
animator?.cancel()
|
||||||
|
last = start
|
||||||
|
current = end
|
||||||
|
setTargetPosition(end)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// if running then "reuse"
|
||||||
|
if (animator?.isRunning == true) {
|
||||||
|
current = end
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
animator?.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
last = start
|
||||||
|
current = end
|
||||||
|
|
||||||
|
// if previously gone, then tp
|
||||||
|
if (wasGone) {
|
||||||
|
setTargetPosition(current)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// animate between a and b
|
||||||
|
animator = ValueAnimator.ofFloat(0.0f, 1.0f).apply {
|
||||||
|
startDelay = 0
|
||||||
|
duration = 100
|
||||||
|
addUpdateListener { animation ->
|
||||||
|
val animatedValue = animation.animatedValue as Float
|
||||||
|
val target = FocusTarget.lerp(last, current, minOf(animatedValue, 1.0f))
|
||||||
|
setTargetPosition(target)
|
||||||
|
}
|
||||||
|
start()
|
||||||
|
}
|
||||||
|
|
||||||
|
// post check
|
||||||
|
if (!same) {
|
||||||
|
newFocus.postDelayed({
|
||||||
|
updateFocusView(lastFocus.get(), same = true)
|
||||||
|
}, 200)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
the following is working, but somewhat bad code code
|
||||||
|
|
||||||
|
if (!wasGone) {
|
||||||
(focusOutline.parent as? ViewGroup)?.let {
|
(focusOutline.parent as? ViewGroup)?.let {
|
||||||
TransitionManager.endTransitions(it)
|
TransitionManager.endTransitions(it)
|
||||||
TransitionManager.beginDelayedTransition(
|
TransitionManager.beginDelayedTransition(
|
||||||
|
@ -812,17 +929,17 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ObjectAnimator.ofFloat(focusOutline, "translationX",focusOutline.translationX, x.toFloat()
|
|
||||||
|
|
||||||
|
|
||||||
focusOutline.layoutParams = focusOutline.layoutParams?.apply {
|
focusOutline.layoutParams = focusOutline.layoutParams?.apply {
|
||||||
width = newFocus.measuredWidth
|
width = newFocus.measuredWidth
|
||||||
height = newFocus.measuredHeight
|
height = newFocus.measuredHeight
|
||||||
}
|
}
|
||||||
focusOutline.translationX = x.toFloat()
|
focusOutline.translationX = x.toFloat()
|
||||||
focusOutline.translationY = y.toFloat()
|
focusOutline.translationY = y.toFloat()*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
app.initClient(this)
|
app.initClient(this)
|
||||||
|
@ -872,13 +989,13 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
||||||
if (isTvSettings()) {
|
if (isTvSettings()) {
|
||||||
val newLocalBinding = ActivityMainTvBinding.inflate(layoutInflater, null, false)
|
val newLocalBinding = ActivityMainTvBinding.inflate(layoutInflater, null, false)
|
||||||
setContentView(newLocalBinding.root)
|
setContentView(newLocalBinding.root)
|
||||||
focusOutline = WeakReference(newLocalBinding.focusOutline)
|
TvFocus.focusOutline = WeakReference(newLocalBinding.focusOutline)
|
||||||
newLocalBinding.root.viewTreeObserver.addOnGlobalFocusChangeListener { _, newFocus ->
|
newLocalBinding.root.viewTreeObserver.addOnGlobalFocusChangeListener { _, newFocus ->
|
||||||
// println("refocus $oldFocus -> $newFocus")
|
// println("refocus $oldFocus -> $newFocus")
|
||||||
updateFocusView(newFocus)
|
TvFocus.updateFocusView(newFocus)
|
||||||
}
|
}
|
||||||
newLocalBinding.root.viewTreeObserver.addOnScrollChangedListener {
|
newLocalBinding.root.viewTreeObserver.addOnScrollChangedListener {
|
||||||
updateFocusView(lastFocus.get())
|
TvFocus.updateFocusView(TvFocus.lastFocus.get(), same = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
ActivityMainBinding.bind(newLocalBinding.root) // this may crash
|
ActivityMainBinding.bind(newLocalBinding.root) // this may crash
|
||||||
|
@ -1230,6 +1347,7 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
if (BuildConfig.DEBUG) {
|
if (BuildConfig.DEBUG) {
|
||||||
|
try {
|
||||||
var providersAndroidManifestString = "Current androidmanifest should be:\n"
|
var providersAndroidManifestString = "Current androidmanifest should be:\n"
|
||||||
for (api in allProviders) {
|
for (api in allProviders) {
|
||||||
providersAndroidManifestString += "<data android:scheme=\"https\" android:host=\"${
|
providersAndroidManifestString += "<data android:scheme=\"https\" android:host=\"${
|
||||||
|
@ -1238,8 +1356,12 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
||||||
)
|
)
|
||||||
}\" android:pathPrefix=\"/\"/>\n"
|
}\" android:pathPrefix=\"/\"/>\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
println(providersAndroidManifestString)
|
println(providersAndroidManifestString)
|
||||||
|
|
||||||
|
} catch (t: Throwable) {
|
||||||
|
logError(t)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handleAppIntent(intent)
|
handleAppIntent(intent)
|
||||||
|
|
|
@ -177,7 +177,7 @@ open class ParentItemAdapter(
|
||||||
).apply {
|
).apply {
|
||||||
isHorizontal = info.isHorizontalImages
|
isHorizontal = info.isHorizontalImages
|
||||||
}
|
}
|
||||||
recyclerView.setLinearListLayout()
|
//recyclerView.setLinearListLayout()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,7 +192,7 @@ open class ParentItemAdapter(
|
||||||
isHorizontal = info.isHorizontalImages
|
isHorizontal = info.isHorizontalImages
|
||||||
hasNext = expand.hasNext
|
hasNext = expand.hasNext
|
||||||
}
|
}
|
||||||
recyclerView.setLinearListLayout()
|
// recyclerView.setLinearListLayout()
|
||||||
title.text = info.name
|
title.text = info.name
|
||||||
|
|
||||||
recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
||||||
|
|
|
@ -19,6 +19,7 @@ import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueT
|
||||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings
|
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.html
|
import com.lagradost.cloudstream3.utils.AppUtils.html
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.setImage
|
import com.lagradost.cloudstream3.utils.UIHelper.setImage
|
||||||
|
import com.lagradost.cloudstream3.utils.UIHelper.toPx
|
||||||
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
|
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
@ -48,7 +49,8 @@ const val ACTION_PLAY_EPISODE_IN_WEB_VIDEO = 16
|
||||||
const val ACTION_PLAY_EPISODE_IN_MPV = 17
|
const val ACTION_PLAY_EPISODE_IN_MPV = 17
|
||||||
|
|
||||||
const val ACTION_MARK_AS_WATCHED = 18
|
const val ACTION_MARK_AS_WATCHED = 18
|
||||||
|
const val TV_EP_SIZE_LARGE = 400
|
||||||
|
const val TV_EP_SIZE_SMALL = 300
|
||||||
data class EpisodeClickEvent(val action: Int, val data: ResultEpisode)
|
data class EpisodeClickEvent(val action: Int, val data: ResultEpisode)
|
||||||
|
|
||||||
class EpisodeAdapter(
|
class EpisodeAdapter(
|
||||||
|
@ -172,7 +174,7 @@ class EpisodeAdapter(
|
||||||
localCard = card
|
localCard = card
|
||||||
|
|
||||||
val setWidth =
|
val setWidth =
|
||||||
if (isTvSettings()) ViewGroup.LayoutParams.WRAP_CONTENT else ViewGroup.LayoutParams.MATCH_PARENT
|
if (isTvSettings()) TV_EP_SIZE_LARGE.toPx else ViewGroup.LayoutParams.MATCH_PARENT
|
||||||
|
|
||||||
binding.episodeLinHolder.layoutParams.width = setWidth
|
binding.episodeLinHolder.layoutParams.width = setWidth
|
||||||
binding.episodeHolderLarge.layoutParams.width = setWidth
|
binding.episodeHolderLarge.layoutParams.width = setWidth
|
||||||
|
@ -293,7 +295,7 @@ class EpisodeAdapter(
|
||||||
|
|
||||||
binding.episodeHolder.layoutParams.apply {
|
binding.episodeHolder.layoutParams.apply {
|
||||||
width =
|
width =
|
||||||
if (isTvSettings()) ViewGroup.LayoutParams.WRAP_CONTENT else ViewGroup.LayoutParams.MATCH_PARENT
|
if (isTvSettings()) TV_EP_SIZE_SMALL.toPx else ViewGroup.LayoutParams.MATCH_PARENT
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.apply {
|
binding.apply {
|
||||||
|
|
|
@ -2,15 +2,19 @@ package com.lagradost.cloudstream3.ui.result
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import android.view.View.LAYOUT_DIRECTION_LTR
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.lagradost.cloudstream3.mvvm.logError
|
import com.lagradost.cloudstream3.mvvm.logError
|
||||||
|
import com.lagradost.cloudstream3.utils.AppUtils.isLtr
|
||||||
|
import com.lagradost.cloudstream3.utils.AppUtils.isRtl
|
||||||
|
|
||||||
fun RecyclerView?.setLinearListLayout(isHorizontal: Boolean = true) {
|
fun RecyclerView?.setLinearListLayout(isHorizontal: Boolean = true) {
|
||||||
if (this == null) return
|
if (this == null) return
|
||||||
|
|
||||||
this.layoutManager =
|
this.layoutManager =
|
||||||
this.context?.let { LinearListLayout(it).apply { if (isHorizontal) setHorizontal() else setVertical() } }
|
this.context?.let { LinearListLayout(it).apply { if (isHorizontal) setHorizontal() else setVertical() } }
|
||||||
?: this.layoutManager
|
// ?: this.layoutManager
|
||||||
}
|
}
|
||||||
|
|
||||||
open class LinearListLayout(context: Context?) :
|
open class LinearListLayout(context: Context?) :
|
||||||
|
@ -56,7 +60,7 @@ open class LinearListLayout(context: Context?) :
|
||||||
startSmoothScroll(linearSmoothScroller)
|
startSmoothScroll(linearSmoothScroller)
|
||||||
}*/
|
}*/
|
||||||
override fun onInterceptFocusSearch(focused: View, direction: Int): View? {
|
override fun onInterceptFocusSearch(focused: View, direction: Int): View? {
|
||||||
val dir = if (orientation == HORIZONTAL) {
|
var dir = if (orientation == HORIZONTAL) {
|
||||||
if (direction == View.FOCUS_DOWN || direction == View.FOCUS_UP) {
|
if (direction == View.FOCUS_DOWN || direction == View.FOCUS_UP) {
|
||||||
// This scrolls the recyclerview before doing focus search, which
|
// This scrolls the recyclerview before doing focus search, which
|
||||||
// allows the focus search to work better.
|
// allows the focus search to work better.
|
||||||
|
@ -71,6 +75,9 @@ open class LinearListLayout(context: Context?) :
|
||||||
if (direction == View.FOCUS_RIGHT || direction == View.FOCUS_LEFT) return null
|
if (direction == View.FOCUS_RIGHT || direction == View.FOCUS_LEFT) return null
|
||||||
if (direction == View.FOCUS_DOWN) 1 else -1
|
if (direction == View.FOCUS_DOWN) 1 else -1
|
||||||
}
|
}
|
||||||
|
if(this.isLayoutRTL) {
|
||||||
|
dir = -dir
|
||||||
|
}
|
||||||
|
|
||||||
return try {
|
return try {
|
||||||
getPosition(getCorrectParent(focused))?.let { position ->
|
getPosition(getCorrectParent(focused))?.let { position ->
|
||||||
|
|
|
@ -62,6 +62,8 @@ import com.lagradost.cloudstream3.ui.search.SearchHelper
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.getNameFull
|
import com.lagradost.cloudstream3.utils.AppUtils.getNameFull
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.html
|
import com.lagradost.cloudstream3.utils.AppUtils.html
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.isCastApiAvailable
|
import com.lagradost.cloudstream3.utils.AppUtils.isCastApiAvailable
|
||||||
|
import com.lagradost.cloudstream3.utils.AppUtils.isLtr
|
||||||
|
import com.lagradost.cloudstream3.utils.AppUtils.isRtl
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.loadCache
|
import com.lagradost.cloudstream3.utils.AppUtils.loadCache
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.openBrowser
|
import com.lagradost.cloudstream3.utils.AppUtils.openBrowser
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||||
|
|
|
@ -14,6 +14,7 @@ import android.view.animation.DecelerateInterpolator
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.core.view.isGone
|
import androidx.core.view.isGone
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
|
import androidx.core.widget.NestedScrollView
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
@ -30,6 +31,7 @@ import com.lagradost.cloudstream3.mvvm.observe
|
||||||
import com.lagradost.cloudstream3.mvvm.observeNullable
|
import com.lagradost.cloudstream3.mvvm.observeNullable
|
||||||
import com.lagradost.cloudstream3.ui.WatchType
|
import com.lagradost.cloudstream3.ui.WatchType
|
||||||
import com.lagradost.cloudstream3.ui.download.DownloadButtonSetup
|
import com.lagradost.cloudstream3.ui.download.DownloadButtonSetup
|
||||||
|
import com.lagradost.cloudstream3.ui.player.CSPlayerEvent
|
||||||
import com.lagradost.cloudstream3.ui.player.ExtractorLinkGenerator
|
import com.lagradost.cloudstream3.ui.player.ExtractorLinkGenerator
|
||||||
import com.lagradost.cloudstream3.ui.player.GeneratorPlayer
|
import com.lagradost.cloudstream3.ui.player.GeneratorPlayer
|
||||||
import com.lagradost.cloudstream3.ui.result.ResultFragment.getStoredData
|
import com.lagradost.cloudstream3.ui.result.ResultFragment.getStoredData
|
||||||
|
@ -38,6 +40,8 @@ import com.lagradost.cloudstream3.ui.search.SearchAdapter
|
||||||
import com.lagradost.cloudstream3.ui.search.SearchHelper
|
import com.lagradost.cloudstream3.ui.search.SearchHelper
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.getNameFull
|
import com.lagradost.cloudstream3.utils.AppUtils.getNameFull
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.html
|
import com.lagradost.cloudstream3.utils.AppUtils.html
|
||||||
|
import com.lagradost.cloudstream3.utils.AppUtils.isLtr
|
||||||
|
import com.lagradost.cloudstream3.utils.AppUtils.isRtl
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.loadCache
|
import com.lagradost.cloudstream3.utils.AppUtils.loadCache
|
||||||
import com.lagradost.cloudstream3.utils.Coroutines.ioSafe
|
import com.lagradost.cloudstream3.utils.Coroutines.ioSafe
|
||||||
import com.lagradost.cloudstream3.utils.Coroutines.main
|
import com.lagradost.cloudstream3.utils.Coroutines.main
|
||||||
|
@ -254,6 +258,12 @@ class ResultFragmentTv : Fragment() {
|
||||||
resultEpisodesShow.onFocusChangeListener = rightListener
|
resultEpisodesShow.onFocusChangeListener = rightListener
|
||||||
resultDescription.onFocusChangeListener = leftListener
|
resultDescription.onFocusChangeListener = leftListener
|
||||||
resultBookmarkButton.onFocusChangeListener = leftListener
|
resultBookmarkButton.onFocusChangeListener = leftListener
|
||||||
|
resultEpisodesShow.setOnClickListener {
|
||||||
|
// toggle, to make it more touch accessable just in case someone thinks that a
|
||||||
|
// tv layout is better but is using a touch device
|
||||||
|
toggleEpisodes(!episodeHolderTv.isVisible)
|
||||||
|
}
|
||||||
|
|
||||||
redirectToPlay.setOnFocusChangeListener { _, hasFocus ->
|
redirectToPlay.setOnFocusChangeListener { _, hasFocus ->
|
||||||
if (!hasFocus) return@setOnFocusChangeListener
|
if (!hasFocus) return@setOnFocusChangeListener
|
||||||
toggleEpisodes(false)
|
toggleEpisodes(false)
|
||||||
|
@ -272,6 +282,12 @@ class ResultFragmentTv : Fragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// parallax on background
|
||||||
|
resultFinishLoading.setOnScrollChangeListener(NestedScrollView.OnScrollChangeListener { _, _, scrollY, _, oldScrollY ->
|
||||||
|
backgroundPosterHolder.translationY = -scrollY.toFloat() * 0.8f
|
||||||
|
})
|
||||||
|
|
||||||
redirectToEpisodes.setOnFocusChangeListener { _, hasFocus ->
|
redirectToEpisodes.setOnFocusChangeListener { _, hasFocus ->
|
||||||
if (!hasFocus) return@setOnFocusChangeListener
|
if (!hasFocus) return@setOnFocusChangeListener
|
||||||
toggleEpisodes(true)
|
toggleEpisodes(true)
|
||||||
|
@ -290,10 +306,10 @@ class ResultFragmentTv : Fragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
resultEpisodes.layoutManager =
|
resultEpisodes.setLinearListLayout(false)/*.layoutManager =
|
||||||
LinearListLayout(resultEpisodes.context).apply {
|
LinearListLayout(resultEpisodes.context, resultEpisodes.isRtl()).apply {
|
||||||
setVertical()
|
setVertical()
|
||||||
}
|
}*/
|
||||||
|
|
||||||
resultReloadConnectionerror.setOnClickListener {
|
resultReloadConnectionerror.setOnClickListener {
|
||||||
viewModel.load(
|
viewModel.load(
|
||||||
|
|
|
@ -20,6 +20,9 @@ import android.os.*
|
||||||
import android.provider.MediaStore
|
import android.provider.MediaStore
|
||||||
import android.text.Spanned
|
import android.text.Spanned
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import android.view.View
|
||||||
|
import android.view.View.LAYOUT_DIRECTION_LTR
|
||||||
|
import android.view.View.LAYOUT_DIRECTION_RTL
|
||||||
import android.view.animation.DecelerateInterpolator
|
import android.view.animation.DecelerateInterpolator
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
|
@ -90,6 +93,9 @@ object AppUtils {
|
||||||
return if (layoutManager == null || adapter == null) false else layoutManager.findLastCompletelyVisibleItemPosition() < adapter.itemCount - 7 // bit more than 1 to make it more seamless
|
return if (layoutManager == null || adapter == null) false else layoutManager.findLastCompletelyVisibleItemPosition() < adapter.itemCount - 7 // bit more than 1 to make it more seamless
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun View.isLtr() = this.layoutDirection == LAYOUT_DIRECTION_LTR
|
||||||
|
fun View.isRtl() = this.layoutDirection == LAYOUT_DIRECTION_RTL
|
||||||
|
|
||||||
fun BottomSheetDialog?.ownHide() {
|
fun BottomSheetDialog?.ownHide() {
|
||||||
this?.hide()
|
this?.hide()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<item android:state_focused="true" android:drawable="@drawable/outline_less" /> <!-- focused -->
|
|
||||||
|
<!--<item android:state_focused="true" android:drawable="@drawable/outline_less" />--> <!-- focused -->
|
||||||
</selector>
|
</selector>
|
|
@ -83,6 +83,7 @@
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
|
android:elevation="999999999dp"
|
||||||
android:focusable="false"
|
android:focusable="false"
|
||||||
android:focusableInTouchMode="false"
|
android:focusableInTouchMode="false"
|
||||||
android:clickable="false"
|
android:clickable="false"
|
||||||
|
|
|
@ -126,6 +126,7 @@ https://developer.android.com/design/ui/tv/samples/jet-fit
|
||||||
|
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
|
android:id="@+id/background_poster_holder"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="200dp"
|
android:layout_height="200dp"
|
||||||
android:visibility="visible">
|
android:visibility="visible">
|
||||||
|
@ -152,12 +153,12 @@ https://developer.android.com/design/ui/tv/samples/jet-fit
|
||||||
|
|
||||||
|
|
||||||
<androidx.core.widget.NestedScrollView
|
<androidx.core.widget.NestedScrollView
|
||||||
|
android:id="@+id/result_finish_loading"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/result_finish_loading"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
|
@ -415,6 +416,7 @@ https://developer.android.com/design/ui/tv/samples/jet-fit
|
||||||
<com.google.android.material.chip.ChipGroup
|
<com.google.android.material.chip.ChipGroup
|
||||||
android:id="@+id/result_tag"
|
android:id="@+id/result_tag"
|
||||||
style="@style/ChipParent"
|
style="@style/ChipParent"
|
||||||
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
|
@ -479,8 +481,8 @@ https://developer.android.com/design/ui/tv/samples/jet-fit
|
||||||
android:fadingEdge="horizontal"
|
android:fadingEdge="horizontal"
|
||||||
android:focusable="false"
|
android:focusable="false"
|
||||||
android:focusableInTouchMode="false"
|
android:focusableInTouchMode="false"
|
||||||
android:nextFocusUp="@id/result_back"
|
android:nextFocusUp="@id/result_episodes_show"
|
||||||
android:nextFocusDown="@id/result_play_movie"
|
android:nextFocusDown="@id/result_recommendations_filter_selection"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:paddingTop="5dp"
|
android:paddingTop="5dp"
|
||||||
android:requiresFadingEdge="horizontal"
|
android:requiresFadingEdge="horizontal"
|
||||||
|
@ -502,9 +504,9 @@ https://developer.android.com/design/ui/tv/samples/jet-fit
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginEnd="10dp"
|
android:layout_marginEnd="10dp"
|
||||||
android:nextFocusUp="@id/result_episodes"
|
android:nextFocusUp="@id/result_cast_items"
|
||||||
|
|
||||||
android:nextFocusDown="@id/result_recommendations_list"
|
android:nextFocusDown="@id/result_recommendations_list"
|
||||||
|
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||||
tools:itemCount="2"
|
tools:itemCount="2"
|
||||||
|
@ -525,7 +527,6 @@ https://developer.android.com/design/ui/tv/samples/jet-fit
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="?attr/primaryBlackBackground"
|
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
android:descendantFocusability="afterDescendants"
|
android:descendantFocusability="afterDescendants"
|
||||||
android:nextFocusUp="@id/result_recommendations_filter_selection"
|
android:nextFocusUp="@id/result_recommendations_filter_selection"
|
||||||
|
|
|
@ -122,18 +122,17 @@
|
||||||
tools:listitem="@layout/homepage_parent" />
|
tools:listitem="@layout/homepage_parent" />
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
|
android:background="?attr/primaryBlackBackground"
|
||||||
android:id="@+id/search_history_holder"
|
android:id="@+id/search_history_holder"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:paddingStart="@dimen/navbar_width"
|
android:layout_marginStart="@dimen/navbar_width"
|
||||||
android:id="@+id/search_history_recycler"
|
android:id="@+id/search_history_recycler"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
|
||||||
android:background="?attr/primaryBlackBackground"
|
|
||||||
android:descendantFocusability="afterDescendants"
|
android:descendantFocusability="afterDescendants"
|
||||||
android:nextFocusLeft="@id/nav_rail_view"
|
android:nextFocusLeft="@id/nav_rail_view"
|
||||||
android:visibility="visible"
|
android:visibility="visible"
|
||||||
|
@ -141,6 +140,7 @@
|
||||||
tools:listitem="@layout/search_history_item" />
|
tools:listitem="@layout/search_history_item" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:layout_marginStart="@dimen/navbar_width"
|
||||||
android:id="@+id/search_clear_call_history"
|
android:id="@+id/search_clear_call_history"
|
||||||
style="@style/BlackButton"
|
style="@style/BlackButton"
|
||||||
android:layout_gravity="bottom"
|
android:layout_gravity="bottom"
|
||||||
|
|
|
@ -6,10 +6,11 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="@drawable/outline_drawable_less"
|
android:background="@drawable/outline_drawable_less"
|
||||||
android:foreground="?android:attr/selectableItemBackgroundBorderless"
|
|
||||||
android:nextFocusRight="@id/home_history_remove"
|
android:nextFocusRight="@id/home_history_remove"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
<!-- android:foreground="?android:attr/selectableItemBackgroundBorderless"
|
||||||
|
-->
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/home_history_title"
|
android:id="@+id/home_history_title"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
@ -29,7 +30,6 @@
|
||||||
android:layout_gravity="center_vertical|end"
|
android:layout_gravity="center_vertical|end"
|
||||||
|
|
||||||
android:background="@drawable/outline_drawable_less"
|
android:background="@drawable/outline_drawable_less"
|
||||||
android:foreground="?android:attr/selectableItemBackgroundBorderless"
|
|
||||||
|
|
||||||
android:nextFocusLeft="@id/home_history_tab"
|
android:nextFocusLeft="@id/home_history_tab"
|
||||||
android:padding="10dp"
|
android:padding="10dp"
|
||||||
|
|
|
@ -104,7 +104,7 @@
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="ChipParent">
|
<style name="ChipParent">
|
||||||
<item name="chipSpacingVertical">5dp</item>
|
<item name="chipSpacingVertical">-5dp</item>
|
||||||
<item name="chipSpacingHorizontal">5dp</item>
|
<item name="chipSpacingHorizontal">5dp</item>
|
||||||
<item name="textColor">?attr/textColor</item>
|
<item name="textColor">?attr/textColor</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
Loading…
Reference in a new issue