diff --git a/serenity-app/src/main/java/us/nineworlds/serenity/fragments/EpisodeVideoGalleryFragment.java b/serenity-app/src/main/java/us/nineworlds/serenity/fragments/EpisodeVideoGalleryFragment.java index 13dc97788..5ed932175 100644 --- a/serenity-app/src/main/java/us/nineworlds/serenity/fragments/EpisodeVideoGalleryFragment.java +++ b/serenity-app/src/main/java/us/nineworlds/serenity/fragments/EpisodeVideoGalleryFragment.java @@ -43,6 +43,7 @@ import us.nineworlds.serenity.ui.browser.tv.episodes.EpisodePosterOnItemSelectedListener; import us.nineworlds.serenity.ui.browser.tv.seasons.EpisodePosterOnItemClickListener; import us.nineworlds.serenity.ui.listeners.GalleryVideoOnItemLongClickListener; +import us.nineworlds.serenity.ui.recyclerview.FocusableLinearLayoutManager; public class EpisodeVideoGalleryFragment extends InjectingFragment { @@ -74,8 +75,11 @@ public EpisodeVideoGalleryFragment() { videoGallery.setAdapter(adapter); videoGallery.setItemAnimator(new FadeInAnimator()); videoGallery.setHorizontalFadingEdgeEnabled(false); - videoGallery.setLayoutManager( - new LinearLayoutManager(getActivity(), LinearLayoutManager.HORIZONTAL, false)); + + FocusableLinearLayoutManager linearLayoutManager = new FocusableLinearLayoutManager(getActivity()); + linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); + videoGallery.setLayoutManager(linearLayoutManager); + videoGallery.addItemDecoration(new SpaceItemDecoration( getResources().getDimensionPixelOffset(R.dimen.horizontal_spacing))); videoGallery.setClipToPadding(false); diff --git a/serenity-app/src/main/java/us/nineworlds/serenity/fragments/MovieVideoGalleryFragment.java b/serenity-app/src/main/java/us/nineworlds/serenity/fragments/MovieVideoGalleryFragment.java index 6d46a525a..09c08ec79 100644 --- a/serenity-app/src/main/java/us/nineworlds/serenity/fragments/MovieVideoGalleryFragment.java +++ b/serenity-app/src/main/java/us/nineworlds/serenity/fragments/MovieVideoGalleryFragment.java @@ -51,6 +51,7 @@ import us.nineworlds.serenity.ui.listeners.AbstractVideoOnItemSelectedListener; import us.nineworlds.serenity.ui.listeners.GalleryVideoOnItemClickListener; import us.nineworlds.serenity.ui.listeners.GalleryVideoOnItemLongClickListener; +import us.nineworlds.serenity.ui.recyclerview.FocusableLinearLayoutManager; import static android.view.View.*; import static butterknife.ButterKnife.bind; @@ -135,7 +136,7 @@ private AbstractVideoOnItemLongClickListener createOnItemLongClickListener(Movie } protected LinearLayoutManager createLayoutManager() { - LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity()); + LinearLayoutManager linearLayoutManager = new FocusableLinearLayoutManager(getActivity()); linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); return linearLayoutManager; } diff --git a/serenity-app/src/main/java/us/nineworlds/serenity/fragments/VideoGridFragment.java b/serenity-app/src/main/java/us/nineworlds/serenity/fragments/VideoGridFragment.java index 8e8785dd1..993fb02dc 100644 --- a/serenity-app/src/main/java/us/nineworlds/serenity/fragments/VideoGridFragment.java +++ b/serenity-app/src/main/java/us/nineworlds/serenity/fragments/VideoGridFragment.java @@ -37,6 +37,7 @@ import us.nineworlds.serenity.ui.browser.movie.MoviePosterImageAdapter; import us.nineworlds.serenity.ui.browser.movie.MoviePosterOnItemSelectedListener; import us.nineworlds.serenity.ui.listeners.AbstractVideoOnItemSelectedListener; +import us.nineworlds.serenity.ui.recyclerview.FocusableGridLayoutManager; import us.nineworlds.serenity.widgets.SerenityMenuGridLayoutManager; import static butterknife.ButterKnife.bind; @@ -66,7 +67,7 @@ public VideoGridFragment() { protected LinearLayoutManager createLayoutManager() { GridLayoutManager layoutManager = - new GridLayoutManager(getActivity(), 3, + new FocusableGridLayoutManager(getActivity(), 3, GridLayoutManager.HORIZONTAL, false); return layoutManager; } diff --git a/serenity-app/src/main/java/us/nineworlds/serenity/ui/activity/SerenityActivity.java b/serenity-app/src/main/java/us/nineworlds/serenity/ui/activity/SerenityActivity.java index 5f2d9d2e0..9976faee1 100644 --- a/serenity-app/src/main/java/us/nineworlds/serenity/ui/activity/SerenityActivity.java +++ b/serenity-app/src/main/java/us/nineworlds/serenity/ui/activity/SerenityActivity.java @@ -68,12 +68,6 @@ public abstract class SerenityActivity extends InjectingMvpActivity { } gallery.smoothScrollToPosition(newPosition); Timber.d("New ItemPosition: " + newPosition); - - scrollingHandler.postDelayed(() -> { - LinearLayoutManager linearLayout = (LinearLayoutManager) gallery.getLayoutManager(); - View viewByPosition = linearLayout.findViewByPosition(linearLayout.findFirstVisibleItemPosition()); - viewByPosition.requestFocusFromTouch(); - }, 200); return true; } @@ -84,12 +78,6 @@ public abstract class SerenityActivity extends InjectingMvpActivity { } gallery.smoothScrollToPosition(newPosition); Timber.d("New ItemPosition: " + newPosition); - scrollingHandler.postDelayed(() -> { - LinearLayoutManager linearLayout = (LinearLayoutManager) gallery.getLayoutManager(); - View viewByPosition = linearLayout.findViewByPosition(linearLayout.findLastCompletelyVisibleItemPosition()); - viewByPosition.requestFocusFromTouch(); - }, 200); - return true; } } diff --git a/serenity-app/src/main/java/us/nineworlds/serenity/ui/browser/tv/OnKeyDownDelegate.java b/serenity-app/src/main/java/us/nineworlds/serenity/ui/browser/tv/OnKeyDownDelegate.java index d66277085..aea1478bf 100644 --- a/serenity-app/src/main/java/us/nineworlds/serenity/ui/browser/tv/OnKeyDownDelegate.java +++ b/serenity-app/src/main/java/us/nineworlds/serenity/ui/browser/tv/OnKeyDownDelegate.java @@ -74,14 +74,8 @@ public boolean onKeyDown(int keyCode, KeyEvent keyEvent) { if (newPosition < 0) { newPosition = 0; } - tvRecyclerView.scrollToPosition(newPosition); + tvRecyclerView.smoothScrollToPosition(newPosition); Timber.d("New ItemPosition: " + newPosition); - - scrollingHandler.postDelayed(() -> { - LinearLayoutManager linearLayout = (LinearLayoutManager) tvRecyclerView.getLayoutManager(); - View viewByPosition = linearLayout.findViewByPosition(linearLayout.findFirstCompletelyVisibleItemPosition()); - viewByPosition.requestFocusFromTouch(); - }, 700); return true; } @@ -90,13 +84,8 @@ public boolean onKeyDown(int keyCode, KeyEvent keyEvent) { if (newPosition > itemsCount) { newPosition = itemsCount - 1; } - tvRecyclerView.scrollToPosition(newPosition); + tvRecyclerView.smoothScrollToPosition(newPosition); Timber.d("New ItemPosition: " + newPosition); - scrollingHandler.postDelayed(() -> { - LinearLayoutManager linearLayout = (LinearLayoutManager) tvRecyclerView.getLayoutManager(); - linearLayout.findViewByPosition(linearLayout.findLastCompletelyVisibleItemPosition()).requestFocusFromTouch(); - }, 700); - return true; } } diff --git a/serenity-app/src/main/java/us/nineworlds/serenity/ui/browser/tv/TVShowBrowserActivity.java b/serenity-app/src/main/java/us/nineworlds/serenity/ui/browser/tv/TVShowBrowserActivity.java index 28b395de1..ada2010c8 100644 --- a/serenity-app/src/main/java/us/nineworlds/serenity/ui/browser/tv/TVShowBrowserActivity.java +++ b/serenity-app/src/main/java/us/nineworlds/serenity/ui/browser/tv/TVShowBrowserActivity.java @@ -57,6 +57,8 @@ import us.nineworlds.serenity.ui.activity.SerenityMultiViewVideoActivity; import us.nineworlds.serenity.ui.adapters.AbstractPosterImageGalleryAdapter; import us.nineworlds.serenity.ui.adapters.MenuDrawerAdapter; +import us.nineworlds.serenity.ui.recyclerview.FocusableGridLayoutManager; +import us.nineworlds.serenity.ui.recyclerview.FocusableLinearLayoutManager; import us.nineworlds.serenity.ui.util.DisplayUtils; import static android.view.View.*; @@ -111,7 +113,7 @@ public class TVShowBrowserActivity extends SerenityMultiViewVideoActivity private void populateTVShowContent() { if (gridViewActive) { - GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 3, GridLayoutManager.HORIZONTAL, false); + GridLayoutManager gridLayoutManager = new FocusableGridLayoutManager(this, 3, GridLayoutManager.HORIZONTAL, false); tvShowRecyclerView.setLayoutManager(gridLayoutManager); tvShowRecyclerView.addItemDecoration( @@ -124,8 +126,8 @@ private void populateTVShowContent() { return; } - LinearLayoutManager linearLayoutManager = - new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false); + LinearLayoutManager linearLayoutManager = new FocusableLinearLayoutManager(this); + linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); tvShowRecyclerView.setLayoutManager(linearLayoutManager); tvShowRecyclerView.addItemDecoration( new SpaceItemDecoration( diff --git a/serenity-app/src/main/java/us/nineworlds/serenity/ui/browser/tv/seasons/TVShowSeasonBrowserActivity.java b/serenity-app/src/main/java/us/nineworlds/serenity/ui/browser/tv/seasons/TVShowSeasonBrowserActivity.java index 07152ea9d..44fe6ea0c 100644 --- a/serenity-app/src/main/java/us/nineworlds/serenity/ui/browser/tv/seasons/TVShowSeasonBrowserActivity.java +++ b/serenity-app/src/main/java/us/nineworlds/serenity/ui/browser/tv/seasons/TVShowSeasonBrowserActivity.java @@ -49,6 +49,8 @@ import us.nineworlds.serenity.ui.activity.SerenityVideoActivity; import us.nineworlds.serenity.ui.adapters.AbstractPosterImageGalleryAdapter; import us.nineworlds.serenity.ui.adapters.MenuDrawerAdapter; +import us.nineworlds.serenity.ui.recyclerview.FocusableGridLayoutManager; +import us.nineworlds.serenity.ui.recyclerview.FocusableLinearLayoutManager; import us.nineworlds.serenity.ui.util.DisplayUtils; import us.nineworlds.serenity.widgets.DrawerLayout; @@ -98,8 +100,9 @@ protected void setupSeasons() { tvShowSeasonsGallery.setClipToPadding(false); tvShowSeasonsGallery.setAdapter(adapter); tvShowSeasonsGallery.setItemAnimator(new FadeInAnimator()); - tvShowSeasonsGallery.setLayoutManager( - new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)); + LinearLayoutManager linearLayoutManager = new FocusableLinearLayoutManager(this); + linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); + tvShowSeasonsGallery.setLayoutManager(linearLayoutManager); tvShowSeasonsGallery.addItemDecoration(createItemDecorator()); tvShowSeasonsGallery.setFocusable(true); @@ -112,7 +115,7 @@ protected void setupSeasons() { gridView.setAdapter(episodeAdapter); gridView.addItemDecoration(createItemDecorator()); gridView.setItemAnimator(new FadeInAnimator()); - GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 2, GridLayoutManager.HORIZONTAL, false) { + GridLayoutManager gridLayoutManager = new FocusableGridLayoutManager(this, 2, GridLayoutManager.HORIZONTAL, false) { @Override public boolean supportsPredictiveItemAnimations() { return false; } diff --git a/serenity-app/src/main/kotlin/us/nineworlds/serenity/ui/recyclerview/FocusableGridLayoutManager.kt b/serenity-app/src/main/kotlin/us/nineworlds/serenity/ui/recyclerview/FocusableGridLayoutManager.kt new file mode 100644 index 000000000..be02be861 --- /dev/null +++ b/serenity-app/src/main/kotlin/us/nineworlds/serenity/ui/recyclerview/FocusableGridLayoutManager.kt @@ -0,0 +1,17 @@ +package us.nineworlds.serenity.ui.recyclerview + +import android.content.Context +import android.support.v7.widget.GridLayoutManager +import android.support.v7.widget.RecyclerView + +open class FocusableGridLayoutManager(val context: Context, spanCount: Int, orientation: Int, reverseLayout: Boolean) : GridLayoutManager(context, spanCount, orientation, reverseLayout) { + + override fun smoothScrollToPosition(recyclerView: RecyclerView?, state: RecyclerView.State?, position: Int) { + val smoothScroller = FocusableLinearSmoothScroller(context) + + smoothScroller.targetPosition = position + startSmoothScroll(smoothScroller) + } + + +} \ No newline at end of file diff --git a/serenity-app/src/main/kotlin/us/nineworlds/serenity/ui/recyclerview/FocusableLinearLayoutManager.kt b/serenity-app/src/main/kotlin/us/nineworlds/serenity/ui/recyclerview/FocusableLinearLayoutManager.kt new file mode 100644 index 000000000..bb29c9fe5 --- /dev/null +++ b/serenity-app/src/main/kotlin/us/nineworlds/serenity/ui/recyclerview/FocusableLinearLayoutManager.kt @@ -0,0 +1,14 @@ +package us.nineworlds.serenity.ui.recyclerview + +import android.content.Context +import android.support.v7.widget.LinearLayoutManager +import android.support.v7.widget.RecyclerView + +class FocusableLinearLayoutManager(val context: Context) : LinearLayoutManager(context) { + + override fun smoothScrollToPosition(recyclerView: RecyclerView?, state: RecyclerView.State?, position: Int) { + val smoothScroller = FocusableLinearSmoothScroller(context) + smoothScroller.targetPosition = position + startSmoothScroll(smoothScroller) + } +} \ No newline at end of file diff --git a/serenity-app/src/main/kotlin/us/nineworlds/serenity/ui/recyclerview/FocusableLinearSmoothScroller.kt b/serenity-app/src/main/kotlin/us/nineworlds/serenity/ui/recyclerview/FocusableLinearSmoothScroller.kt new file mode 100644 index 000000000..19fab2a50 --- /dev/null +++ b/serenity-app/src/main/kotlin/us/nineworlds/serenity/ui/recyclerview/FocusableLinearSmoothScroller.kt @@ -0,0 +1,24 @@ +package us.nineworlds.serenity.ui.recyclerview + +import android.content.Context +import android.support.v7.widget.LinearSmoothScroller +import android.support.v7.widget.RecyclerView +import android.view.View + +class FocusableLinearSmoothScroller(context: Context) : LinearSmoothScroller(context) { + + var targetView : View? = null + + override fun onTargetFound(targetView: View?, state: RecyclerView.State?, action: Action?) { + super.onTargetFound(targetView, state, action) + this.targetView = targetView + } + + override fun onStop() { + super.onStop() + + if (targetView != null && !targetView!!.hasFocus()) { + targetView!!.requestFocusFromTouch() + } + } +} \ No newline at end of file