forked from recloudstream/cloudstream
		
	heavily improved android tv anime page navigation
This commit is contained in:
		
							parent
							
								
									ad2f2ec412
								
							
						
					
					
						commit
						83f3f7ff2e
					
				
					 7 changed files with 667 additions and 579 deletions
				
			
		|  | @ -333,7 +333,7 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener { | |||
|         } | ||||
| 
 | ||||
|         // this pulls the latest data so ppl don't have to update to simply change provider url | ||||
|         if(downloadFromGithub) { | ||||
|         if (downloadFromGithub) { | ||||
|             try { | ||||
|                 runBlocking { | ||||
|                     withContext(Dispatchers.IO) { | ||||
|  | @ -379,10 +379,12 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener { | |||
|                                 apis = allProviders.filter { api -> | ||||
|                                     val name = api.javaClass.simpleName | ||||
|                                     // if the provider does not exist in the json file, then it is shown by default | ||||
|                                     !providersJsonMap.containsKey(name) || acceptableProviders.contains(name) || restrictedApis.contains(name) | ||||
|                                     !providersJsonMap.containsKey(name) || acceptableProviders.contains( | ||||
|                                         name | ||||
|                                     ) || restrictedApis.contains(name) | ||||
|                                 } | ||||
|                             } | ||||
|                         } catch (e : Exception) { | ||||
|                         } catch (e: Exception) { | ||||
|                             logError(e) | ||||
|                         } | ||||
|                     } | ||||
|  |  | |||
|  | @ -39,6 +39,7 @@ import com.google.android.gms.cast.framework.CastContext | |||
| import com.google.android.gms.cast.framework.CastState | ||||
| import com.google.android.material.button.MaterialButton | ||||
| import com.lagradost.cloudstream3.* | ||||
| import com.lagradost.cloudstream3.APIHolder.getApiDubstatusSettings | ||||
| import com.lagradost.cloudstream3.APIHolder.getApiFromName | ||||
| import com.lagradost.cloudstream3.APIHolder.getId | ||||
| import com.lagradost.cloudstream3.AcraApplication.Companion.context | ||||
|  | @ -583,7 +584,6 @@ class ResultFragment : Fragment(), PanelsChildGestureRegionObserver.GestureRegio | |||
|     @SuppressLint("SetTextI18n") | ||||
|     override fun onViewCreated(view: View, savedInstanceState: Bundle?) { | ||||
|         super.onViewCreated(view, savedInstanceState) | ||||
| 
 | ||||
|         result_cast_items?.let { | ||||
|             PanelsChildGestureRegionObserver.Provider.get().register(it) | ||||
|         } | ||||
|  | @ -1077,6 +1077,65 @@ class ResultFragment : Fragment(), PanelsChildGestureRegionObserver.GestureRegio | |||
|             } | ||||
|         } | ||||
| 
 | ||||
|         /** | ||||
|          * Sets next focus to allow navigation up and down between 2 views | ||||
|          * if either of them is null nothing happens. | ||||
|          **/ | ||||
|         fun setFocusUpAndDown(upper: View?, down: View?) { | ||||
|             if (upper == null || down == null) return | ||||
|             upper.nextFocusDownId = down.id | ||||
|             down.nextFocusUpId = upper.id | ||||
|         } | ||||
| 
 | ||||
|         // This is to band-aid FireTV navigation | ||||
|         result_season_button?.isFocusableInTouchMode = context?.isTvSettings() == true | ||||
|         result_episode_select?.isFocusableInTouchMode = context?.isTvSettings() == true | ||||
|         result_dub_select?.isFocusableInTouchMode = context?.isTvSettings() == true | ||||
| 
 | ||||
|         observe(viewModel.selectedSeason) { season -> | ||||
|             result_season_button?.text = fromIndexToSeasonText(season) | ||||
|         } | ||||
| 
 | ||||
|         observe(viewModel.seasonSelections) { seasonList -> | ||||
|             result_season_button?.visibility = if (seasonList.size <= 1) GONE else VISIBLE.also { | ||||
| 
 | ||||
|                 // If the season button is visible the result season button will be next focus down | ||||
|                 if (result_series_parent?.isVisible == true) | ||||
|                     setFocusUpAndDown(result_resume_series_button, result_season_button) | ||||
|                 else | ||||
|                     setFocusUpAndDown(result_bookmark_button, result_season_button) | ||||
|             } | ||||
| 
 | ||||
|             result_season_button?.setOnClickListener { | ||||
|                 result_season_button?.popupMenuNoIconsAndNoStringRes( | ||||
|                     items = seasonList | ||||
|                         .map { Pair(it ?: -2, fromIndexToSeasonText(it)) }, | ||||
|                 ) { | ||||
|                     val id = this.itemId | ||||
| 
 | ||||
|                     viewModel.changeSeason(if (id == -2) null else id) | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         observe(viewModel.selectedRange) { range -> | ||||
|             result_episode_select?.text = range | ||||
|         } | ||||
| 
 | ||||
|         observe(viewModel.rangeOptions) { range -> | ||||
|             episodeRanges = range | ||||
|             result_episode_select?.visibility = if (range.size <= 1) GONE else VISIBLE.also { | ||||
| 
 | ||||
|                 // If Season button is invisible then the bookmark button next focus is episode select | ||||
|                 if (result_season_button?.isVisible != true) { | ||||
|                     if (result_series_parent?.isVisible == true) | ||||
|                         setFocusUpAndDown(result_resume_series_button, result_episode_select) | ||||
|                     else | ||||
|                         setFocusUpAndDown(result_bookmark_button, result_episode_select) | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         observe(viewModel.episodes) { episodeList -> | ||||
|             lateFixDownloadButton(episodeList.size <= 1) // movies can have multible parts but still be *movies* this will fix this | ||||
|             var isSeriesVisible = false | ||||
|  | @ -1118,6 +1177,17 @@ class ResultFragment : Fragment(), PanelsChildGestureRegionObserver.GestureRegio | |||
|             } | ||||
| 
 | ||||
|             result_series_parent?.isVisible = isSeriesVisible | ||||
|             if (isSeriesVisible) { | ||||
|                 val down = when { | ||||
|                     result_season_button?.isVisible == true -> result_season_button | ||||
|                     result_episode_select?.isVisible == true -> result_episode_select | ||||
|                     result_dub_select?.isVisible == true -> result_dub_select | ||||
|                     else -> null | ||||
|                 } | ||||
|                 setFocusUpAndDown(result_resume_series_button, down) | ||||
|                 setFocusUpAndDown(result_bookmark_button, result_resume_series_button) | ||||
|             } | ||||
| 
 | ||||
|             result_resume_progress_holder?.isVisible = isProgressVisible | ||||
|             context?.getString(if (isProgressVisible) R.string.resume else R.string.play_movie_button) | ||||
|                 ?.let { | ||||
|  | @ -1150,28 +1220,7 @@ class ResultFragment : Fragment(), PanelsChildGestureRegionObserver.GestureRegio | |||
|             startValue = null | ||||
|         } | ||||
| 
 | ||||
|         observe(viewModel.selectedSeason) | ||||
|         { season -> | ||||
|             result_season_button?.text = fromIndexToSeasonText(season) | ||||
|         } | ||||
| 
 | ||||
|         observe(viewModel.seasonSelections) | ||||
|         { seasonList -> | ||||
|             result_season_button?.visibility = if (seasonList.size <= 1) GONE else VISIBLE | ||||
|             result_season_button?.setOnClickListener { | ||||
|                 result_season_button?.popupMenuNoIconsAndNoStringRes( | ||||
|                     items = seasonList | ||||
|                         .map { Pair(it ?: -2, fromIndexToSeasonText(it)) }, | ||||
|                 ) { | ||||
|                     val id = this.itemId | ||||
| 
 | ||||
|                     viewModel.changeSeason(if (id == -2) null else id) | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         observe(viewModel.publicEpisodes) | ||||
|         { episodes -> | ||||
|         observe(viewModel.publicEpisodes) { episodes -> | ||||
|             when (episodes) { | ||||
|                 is Resource.Failure -> { | ||||
|                     result_episode_loading?.isVisible = false | ||||
|  | @ -1193,42 +1242,50 @@ class ResultFragment : Fragment(), PanelsChildGestureRegionObserver.GestureRegio | |||
|             } | ||||
|         } | ||||
| 
 | ||||
|         observe(viewModel.dubStatus) | ||||
|         { status -> | ||||
|         observe(viewModel.dubStatus) { status -> | ||||
|             result_dub_select?.text = status.toString() | ||||
|         } | ||||
| 
 | ||||
|         observe(viewModel.dubSubSelections) | ||||
|         { range -> | ||||
|         val preferDub = context?.getApiDubstatusSettings()?.all { it == DubStatus.Dubbed } == true | ||||
| 
 | ||||
|         observe(viewModel.dubSubSelections) { range -> | ||||
|             dubRange = range | ||||
| 
 | ||||
|             if (preferDub && dubRange?.contains(DubStatus.Dubbed) == true){ | ||||
|                 viewModel.changeDubStatus(DubStatus.Dubbed) | ||||
|             } | ||||
| 
 | ||||
|             result_dub_select?.visibility = if (range.size <= 1) GONE else VISIBLE | ||||
| 
 | ||||
|             if (result_season_button?.isVisible != true && result_episode_select?.isVisible != true) { | ||||
|                 if (result_series_parent?.isVisible == true) | ||||
|                     setFocusUpAndDown(result_resume_series_button, result_dub_select) | ||||
|                 else | ||||
|                     setFocusUpAndDown(result_bookmark_button, result_dub_select) | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         result_cast_items?.setOnFocusChangeListener { v, hasFocus -> | ||||
|             // Always escape focus | ||||
|             if (hasFocus) result_bookmark_button?.requestFocus() | ||||
|         } | ||||
| 
 | ||||
|         result_dub_select.setOnClickListener { | ||||
|             val ranges = dubRange | ||||
|             if (ranges != null) { | ||||
|                 it.popupMenuNoIconsAndNoStringRes(ranges.map { status -> | ||||
|                     Pair( | ||||
|                         status.ordinal, | ||||
|                         status.toString() | ||||
|                     ) | ||||
|                 } | ||||
|                 it.popupMenuNoIconsAndNoStringRes(ranges | ||||
|                     .map { status -> | ||||
|                         Pair( | ||||
|                             status.ordinal, | ||||
|                             status.toString() | ||||
|                         ) | ||||
|                     } | ||||
|                     .toList()) { | ||||
|                     viewModel.changeDubStatus(DubStatus.values()[itemId]) | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         observe(viewModel.selectedRange) | ||||
|         { range -> | ||||
|             result_episode_select?.text = range | ||||
|         } | ||||
| 
 | ||||
|         observe(viewModel.rangeOptions) { range -> | ||||
|             episodeRanges = range | ||||
|             result_episode_select?.visibility = if (range.size <= 1) GONE else VISIBLE | ||||
|         } | ||||
| 
 | ||||
|         result_episode_select.setOnClickListener { | ||||
|             val ranges = episodeRanges | ||||
|             if (ranges != null) { | ||||
|  |  | |||
|  | @ -44,7 +44,6 @@ class ResultViewModel : ViewModel() { | |||
|     private var repo: APIRepository? = null | ||||
|     private var generator: IGenerator? = null | ||||
| 
 | ||||
| 
 | ||||
|     private val _resultResponse: MutableLiveData<Resource<Any?>> = MutableLiveData() | ||||
|     private val _episodes: MutableLiveData<List<ResultEpisode>> = MutableLiveData() | ||||
|     private val episodeById: MutableLiveData<HashMap<Int, Int>> = | ||||
|  | @ -190,7 +189,7 @@ class ResultViewModel : ViewModel() { | |||
|     } | ||||
| 
 | ||||
|     fun changeDubStatus(status: DubStatus?) { | ||||
|         if(status == null) return | ||||
|         if (status == null) return | ||||
|         dubSubEpisodes.value?.get(status)?.let { episodes -> | ||||
|             id.value?.let { | ||||
|                 setDub(it, status) | ||||
|  | @ -220,7 +219,10 @@ class ResultViewModel : ViewModel() { | |||
|                 currentSubs.add(sub) | ||||
|             }) | ||||
| 
 | ||||
|             return@safeApiCall Pair(currentLinks.toSet(), currentSubs.toSet()) as Pair<Set<ExtractorLink>, Set<SubtitleData>> | ||||
|             return@safeApiCall Pair( | ||||
|                 currentLinks.toSet(), | ||||
|                 currentSubs.toSet() | ||||
|             ) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  | @ -247,13 +249,15 @@ class ResultViewModel : ViewModel() { | |||
|         generator = RepoLinkGenerator(list) | ||||
| 
 | ||||
|         val set = HashMap<Int, Int>() | ||||
|         val range = selectedRangeInt.value | ||||
| 
 | ||||
|         list.withIndex().forEach { set[it.value.id] = it.index } | ||||
|         episodeById.postValue(set) | ||||
| 
 | ||||
|         filterEpisodes( | ||||
|             list, | ||||
|             if (selection == -1) getResultSeason(localId ?: id.value ?: return) else selection, null | ||||
|             if (selection == -1) getResultSeason(localId ?: id.value ?: return) else selection, | ||||
|             range | ||||
|         ) | ||||
|     } | ||||
| 
 | ||||
|  | @ -330,9 +334,7 @@ class ResultViewModel : ViewModel() { | |||
|                         val status = getDub(mainId) | ||||
|                         val statuses = d.episodes.map { it.key } | ||||
|                         val dubStatus = if (statuses.contains(status)) status else statuses.first() | ||||
|                         _dubStatus.postValue(dubStatus) | ||||
| 
 | ||||
|                         _dubSubSelections.postValue(d.episodes.keys) | ||||
|                         val fillerEpisodes = | ||||
|                             if (showFillers) safeApiCall { getFillerEpisodes(d.name) } else null | ||||
| 
 | ||||
|  | @ -366,10 +368,14 @@ class ResultViewModel : ViewModel() { | |||
| 
 | ||||
|                             Pair(ep.key, episodes) | ||||
|                         }.toMap() | ||||
| 
 | ||||
|                         // These posts needs to be in this order as to make the preferDub in ResultFragment work | ||||
|                         _dubSubEpisodes.postValue(res) | ||||
|                         res[dubStatus]?.let { episodes -> | ||||
|                             updateEpisodes(mainId, episodes, -1) | ||||
|                         } | ||||
|                         _dubStatus.postValue(dubStatus) | ||||
|                         _dubSubSelections.postValue(d.episodes.keys) | ||||
|                     } | ||||
| 
 | ||||
|                     is TvSeriesLoadResponse -> { | ||||
|  |  | |||
							
								
								
									
										6
									
								
								app/src/main/res/color/tag_stroke_color.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								app/src/main/res/color/tag_stroke_color.xml
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,6 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <selector xmlns:android="http://schemas.android.com/apk/res/android"> | ||||
|   <item android:color="?attr/colorPrimary" android:state_checked="true"/> | ||||
|   <item android:color="?attr/colorPrimary" android:state_focused="true"/> | ||||
|   <item android:alpha="0.12" android:color="?attr/colorOnSurface" android:state_checked="false"/> | ||||
| </selector> | ||||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -1,28 +1,28 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|         xmlns:tools="http://schemas.android.com/tools" | ||||
|         xmlns:app="http://schemas.android.com/apk/res-auto" | ||||
|         android:layout_width="wrap_content" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:paddingLeft="2dp" | ||||
|         android:paddingRight="2dp" | ||||
|         android:paddingTop="-10dp" | ||||
|         android:layout_marginTop="-4dp" | ||||
|         android:layout_marginBottom="-4dp"> | ||||
|     xmlns:app="http://schemas.android.com/apk/res-auto" | ||||
|     xmlns:tools="http://schemas.android.com/tools" | ||||
|     android:layout_width="wrap_content" | ||||
|     android:layout_height="wrap_content" | ||||
|     android:layout_marginTop="-4dp" | ||||
|     android:layout_marginBottom="-4dp" | ||||
|     android:paddingLeft="2dp" | ||||
|     android:paddingTop="-10dp" | ||||
|     android:paddingRight="2dp"> | ||||
|     <!--app:strokeColor="@color/colorAccent"--> | ||||
| 
 | ||||
|     <com.google.android.material.button.MaterialButton | ||||
|             android:minHeight="0dp" | ||||
|             android:minWidth="0dp" | ||||
|             android:layout_height="37dp" | ||||
|             android:textAllCaps="false" | ||||
|             android:textSize="12sp" | ||||
|             android:layout_width="wrap_content" | ||||
|             app:cornerRadius="100dp" | ||||
|             tools:text="Test" | ||||
|             android:textColor="?attr/textColor" | ||||
|             style="@style/Widget.MaterialComponents.Button.OutlinedButton" | ||||
|             android:id="@+id/result_tag_card"> | ||||
|         android:id="@+id/result_tag_card" | ||||
|         style="@style/Tag" | ||||
|         android:layout_width="wrap_content" | ||||
|         android:layout_height="37dp" | ||||
|         android:minWidth="0dp" | ||||
|         android:minHeight="0dp" | ||||
|         android:textAllCaps="false" | ||||
|         android:textColor="?attr/textColor" | ||||
|         android:textSize="12sp" | ||||
|         app:cornerRadius="100dp" | ||||
|         tools:text="Test"> | ||||
| 
 | ||||
|     </com.google.android.material.button.MaterialButton> | ||||
| </FrameLayout> | ||||
|  | @ -186,8 +186,7 @@ | |||
|         <item name="android:windowBackground">?attr/primaryBlackBackground</item> | ||||
|     </style> | ||||
| 
 | ||||
|     <style name="AppSearchViewStyle" | ||||
|            parent="Theme.MaterialComponents.NoActionBar"> | ||||
|     <style name="AppSearchViewStyle" parent="Theme.MaterialComponents.NoActionBar"> | ||||
|         <item name="android:searchIcon">@drawable/search_icon</item> | ||||
|         <item name="android:queryHint">@string/search_hint</item> | ||||
|         <item name="android:background">@color/transparent</item> | ||||
|  | @ -212,8 +211,7 @@ | |||
|         <item name="behavior_peekHeight">512dp</item> | ||||
|     </style> | ||||
| 
 | ||||
|     <style name="PreferenceTheme" parent="@style/AppTheme"> | ||||
|     </style> | ||||
|     <style name="PreferenceTheme" parent="@style/AppTheme"></style> | ||||
| 
 | ||||
|     <style name="Theme.AlertDialog" parent="ThemeOverlay.MaterialComponents.Dialog.Alert"> | ||||
|         <item name="android:windowMinWidthMajor">@android:dimen/dialog_min_width_major</item> | ||||
|  | @ -229,6 +227,7 @@ | |||
|     <style name="AppButtonStyle" parent="android:Widget.Holo.Button"> | ||||
|         <item name="android:fontFamily">@font/google_sans</item> | ||||
|     </style> | ||||
| 
 | ||||
|     <style name="AppEditStyle" parent="android:Widget.EditText"> | ||||
|         <item name="android:fontFamily">@font/google_sans</item> | ||||
|     </style> | ||||
|  | @ -242,8 +241,8 @@ | |||
|         <item name="android:layout_height">wrap_content</item> | ||||
|         <item name="android:minHeight">24dp</item> | ||||
|         <item name="android:minWidth">0dp</item> | ||||
|      <!--   <item name="android:paddingStart">5dp</item> | ||||
|         <item name="android:paddingEnd">5dp</item>--> | ||||
|         <!--   <item name="android:paddingStart">5dp</item> | ||||
|            <item name="android:paddingEnd">5dp</item>--> | ||||
|     </style> | ||||
| 
 | ||||
|     <style name="AppMaterialButtonStyle" parent="Widget.MaterialComponents.Button"> | ||||
|  | @ -262,6 +261,7 @@ | |||
|         <item name="tabMinWidth">75dp</item> | ||||
|         <item name="tabMode">scrollable</item>--> | ||||
|     </style> | ||||
| 
 | ||||
|     <style name="AlertDialogCustom" parent="Theme.AppCompat.Dialog.Alert"> | ||||
|         <item name="android:windowFullscreen">true</item> | ||||
|         <item name="android:textColor">?attr/textColor</item> | ||||
|  | @ -278,9 +278,11 @@ | |||
|         <item name="android:windowMinWidthMinor">@android:dimen/dialog_min_width_minor</item> | ||||
|         <item name="android:windowBackground">@drawable/dialog__window_background</item> | ||||
|     </style> | ||||
| 
 | ||||
|     <style name="AlertDialogCustomTransparent" parent="Theme.AppCompat.Dialog.Alert"> | ||||
|         <item name="android:windowBackground">@color/transparent</item> | ||||
|     </style> | ||||
| 
 | ||||
|     <style name="AlertDialogCustomBlack" parent="Theme.AppCompat.Dialog.Alert"> | ||||
|         <item name="android:windowBackground">?attr/primaryBlackBackground</item> | ||||
|         <item name="android:layout_width">fill_parent</item> | ||||
|  | @ -451,6 +453,10 @@ | |||
|         <item name="strokeColor">@color/toggle_button_outline</item> | ||||
|     </style> | ||||
| 
 | ||||
|     <style name="Tag" parent="Widget.MaterialComponents.Button.OutlinedButton"> | ||||
|         <item name="strokeColor">@color/tag_stroke_color</item> | ||||
|     </style> | ||||
| 
 | ||||
|     <style name="VideoButtonTV"> | ||||
|         <item name="android:stateListAnimator">@null</item> | ||||
|         <item name="strokeColor">@color/transparent</item> | ||||
|  | @ -495,26 +501,34 @@ | |||
|         <item name="castPlayButtonDrawable">@drawable/ic_baseline_play_arrow_24</item> | ||||
|         <item name="castPauseButtonDrawable">@drawable/netflix_pause</item> | ||||
|         <item name="castStopButtonDrawable">@drawable/cast_ic_expanded_controller_stop</item> | ||||
|         <item name="castSkipPreviousButtonDrawable">@drawable/cast_ic_expanded_controller_skip_previous</item> | ||||
|         <item name="castSkipNextButtonDrawable">@drawable/cast_ic_expanded_controller_skip_next</item> | ||||
|         <item name="castSkipPreviousButtonDrawable"> | ||||
|             @drawable/cast_ic_expanded_controller_skip_previous | ||||
|         </item> | ||||
|         <item name="castSkipNextButtonDrawable">@drawable/cast_ic_expanded_controller_skip_next | ||||
|         </item> | ||||
|         <item name="castRewind30ButtonDrawable">@drawable/go_back_30</item> | ||||
|         <item name="castForward30ButtonDrawable">@drawable/go_forward_30</item> | ||||
|     </style> | ||||
| 
 | ||||
|     <style name="CustomCastMiniController" parent="CastMiniController"> | ||||
|         <item name="castMiniControllerLoadingIndicatorColor">?attr/colorPrimary</item> | ||||
|         <item name="castShowImageThumbnail">true</item> | ||||
| 
 | ||||
|         <item name="castTitleTextAppearance">@style/TextAppearance.AppCompat.Subhead</item> | ||||
|         <item name="castSubtitleTextAppearance">@style/TextAppearance.AppCompat.Caption</item> | ||||
|         <item name="castBackground">@color/transparent</item> <!--CHECK bitDarkerGrayBackground darkBackground--> | ||||
|         <item name="castBackground">@color/transparent | ||||
|         </item> <!--CHECK bitDarkerGrayBackground darkBackground--> | ||||
|         <item name="castProgressBarColor">?attr/colorPrimary</item> | ||||
|         <item name="castStopButtonDrawable">@drawable/cast_ic_mini_controller_stop</item>' | ||||
|         <item name="castLargeStopButtonDrawable">@drawable/cast_ic_mini_controller_stop_large</item> | ||||
|         <item name="castSkipPreviousButtonDrawable">@drawable/cast_ic_mini_controller_skip_prev</item> | ||||
|         <item name="castSkipPreviousButtonDrawable">@drawable/cast_ic_mini_controller_skip_prev | ||||
|         </item> | ||||
|         <item name="castSkipNextButtonDrawable">@drawable/cast_ic_mini_controller_skip_next</item> | ||||
|         <item name="castRewind30ButtonDrawable">@drawable/go_back_30</item> | ||||
|         <item name="castForward30ButtonDrawable">@drawable/go_forward_30</item> | ||||
|         <item name="castMuteToggleButtonDrawable">@drawable/cast_ic_mini_controller_mute</item> | ||||
|         <item name="castClosedCaptionsButtonDrawable">@drawable/cast_ic_mini_controller_closed_caption</item> | ||||
|         <item name="castClosedCaptionsButtonDrawable"> | ||||
|             @drawable/cast_ic_mini_controller_closed_caption | ||||
|         </item> | ||||
|     </style> | ||||
| </resources> | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue