From 26109ef23e3066c8669000192c61ab53ed8220a9 Mon Sep 17 00:00:00 2001 From: jhengazuki Date: Fri, 24 Oct 2025 03:48:38 +0800 Subject: [PATCH] Add swipe refresh for tv --- app/build.gradle | 6 ++-- .../android/tv/ui/base/BaseFragment.java | 4 +++ .../android/tv/ui/custom/CustomScroller.java | 3 +- .../android/tv/ui/fragment/TypeFragment.java | 23 ++++++++----- app/src/leanback/res/layout/fragment_type.xml | 34 +++++++++++-------- .../android/tv/ui/activity/VideoActivity.java | 1 + .../android/tv/ui/fragment/TypeFragment.java | 4 ++- 7 files changed, 47 insertions(+), 28 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index b0f85a7f1..dbf45d0b3 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -95,7 +95,8 @@ dependencies { implementation 'androidx.core:core-splashscreen:1.0.1' implementation 'androidx.media:media:1.7.1' implementation 'androidx.palette:palette:1.0.0' - implementation 'androidx.room:room-runtime:2.8.2' + implementation 'androidx.room:room-runtime:2.8.3' + implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0' implementation 'cat.ereza:customactivityoncrash:2.4.0' implementation 'com.airbnb.android:lottie:6.6.10' implementation 'com.github.bassaer:materialdesigncolors:1.0.0' @@ -121,10 +122,9 @@ dependencies { leanbackImplementation 'androidx.leanback:leanback:1.2.0' leanbackImplementation 'com.github.JessYanCoding:AndroidAutoSize:1.2.1' mobileImplementation 'androidx.biometric:biometric:1.1.0' - mobileImplementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0' mobileImplementation 'com.google.android.flexbox:flexbox:3.0.0' mobileImplementation('com.journeyapps:zxing-android-embedded:4.3.0') { transitive = false } - annotationProcessor 'androidx.room:room-compiler:2.8.2' + annotationProcessor 'androidx.room:room-compiler:2.8.3' annotationProcessor 'com.github.bumptech.glide:compiler:' + glideVersion annotationProcessor 'org.greenrobot:eventbus-annotation-processor:3.3.1' coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs_nio:2.1.5' diff --git a/app/src/leanback/java/com/fongmi/android/tv/ui/base/BaseFragment.java b/app/src/leanback/java/com/fongmi/android/tv/ui/base/BaseFragment.java index 9d6b2a541..a506737ed 100644 --- a/app/src/leanback/java/com/fongmi/android/tv/ui/base/BaseFragment.java +++ b/app/src/leanback/java/com/fongmi/android/tv/ui/base/BaseFragment.java @@ -23,8 +23,12 @@ public abstract class BaseFragment extends Fragment { @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { initView(); + initEvent(); } protected void initView() { } + + protected void initEvent() { + } } diff --git a/app/src/leanback/java/com/fongmi/android/tv/ui/custom/CustomScroller.java b/app/src/leanback/java/com/fongmi/android/tv/ui/custom/CustomScroller.java index 267be1806..0380e3b7a 100644 --- a/app/src/leanback/java/com/fongmi/android/tv/ui/custom/CustomScroller.java +++ b/app/src/leanback/java/com/fongmi/android/tv/ui/custom/CustomScroller.java @@ -29,8 +29,7 @@ public class CustomScroller extends RecyclerView.OnScrollListener { private boolean isBottom(RecyclerView view) { if (view == null || view.getLayoutManager() == null || view.getLayoutManager().getItemCount() == 0) return false; View lastChild = view.getLayoutManager().getChildAt(view.getLayoutManager().getChildCount() - 1); - int lastPosition = view.getLayoutManager().getPosition(lastChild); - return lastPosition == view.getLayoutManager().getItemCount() - 1; + return lastChild != null && view.getLayoutManager().getPosition(lastChild) == view.getLayoutManager().getItemCount() - 1; } public void reset() { diff --git a/app/src/leanback/java/com/fongmi/android/tv/ui/fragment/TypeFragment.java b/app/src/leanback/java/com/fongmi/android/tv/ui/fragment/TypeFragment.java index 26af852e4..c571a670b 100644 --- a/app/src/leanback/java/com/fongmi/android/tv/ui/fragment/TypeFragment.java +++ b/app/src/leanback/java/com/fongmi/android/tv/ui/fragment/TypeFragment.java @@ -13,6 +13,7 @@ import androidx.leanback.widget.HorizontalGridView; import androidx.leanback.widget.ItemBridgeAdapter; import androidx.leanback.widget.ListRow; import androidx.lifecycle.ViewModelProvider; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import androidx.viewbinding.ViewBinding; import com.fongmi.android.tv.Product; @@ -44,7 +45,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; -public class TypeFragment extends BaseFragment implements CustomScroller.Callback, VodPresenter.OnClickListener { +public class TypeFragment extends BaseFragment implements CustomScroller.Callback, VodPresenter.OnClickListener, SwipeRefreshLayout.OnRefreshListener { private HashMap mExtends; private FragmentTypeBinding mBinding; @@ -107,6 +108,8 @@ public class TypeFragment extends BaseFragment implements CustomScroller.Callbac @Override protected void initView() { + mBinding.swipeLayout.setColorSchemeResources(R.color.accent); + mScroller = new CustomScroller(this); mExtends = getExtend(); mFilters = getFilter(); setRecyclerView(); @@ -115,13 +118,18 @@ public class TypeFragment extends BaseFragment implements CustomScroller.Callbac getVideo(); } + @Override + protected void initEvent() { + mBinding.swipeLayout.setOnRefreshListener(this); + mBinding.recycler.addOnScrollListener(mScroller); + } + @SuppressLint("RestrictedApi") private void setRecyclerView() { CustomSelector selector = new CustomSelector(); selector.addPresenter(Vod.class, new VodPresenter(this, Style.list())); selector.addPresenter(ListRow.class, new CustomRowPresenter(16), VodPresenter.class); selector.addPresenter(ListRow.class, new CustomRowPresenter(8, FocusHighlight.ZOOM_FACTOR_NONE, HorizontalGridView.FOCUS_SCROLL_ALIGNED), FilterPresenter.class); - mBinding.recycler.addOnScrollListener(mScroller = new CustomScroller(this)); mBinding.recycler.setAdapter(new ItemBridgeAdapter(mAdapter = new ArrayObjectAdapter(selector))); mBinding.recycler.setHeader(requireActivity().findViewById(R.id.recycler)); mBinding.recycler.setVerticalSpacing(ResUtil.dp2px(16)); @@ -165,6 +173,7 @@ public class TypeFragment extends BaseFragment implements CustomScroller.Callbac boolean flag = mExtends.isEmpty(); int size = result.getList().size(); mBinding.progressLayout.showContent(first & flag, size); + mBinding.swipeLayout.setRefreshing(false); if (size > 0) addVideo(result); mScroller.endLoading(result); checkMore(size); @@ -210,10 +219,6 @@ public class TypeFragment extends BaseFragment implements CustomScroller.Callbac return new ListRow(adapter); } - private void showProgress() { - if (!filterVisible) mBinding.progressLayout.showProgress(); - } - private void showFilter() { List rows = new ArrayList<>(); for (Filter filter : mFilters) rows.add(getRow(filter)); @@ -232,9 +237,11 @@ public class TypeFragment extends BaseFragment implements CustomScroller.Callbac } private void checkFilter() { + int adapterSize = mAdapter.size(); int filterSize = filterVisible ? mFilters.size() : 0; - if (mAdapter.size() > filterSize) mAdapter.removeItems(filterSize, mAdapter.size() - filterSize); - else showProgress(); + if (adapterSize > filterSize) mAdapter.removeItems(filterSize, mAdapter.size() - filterSize); + if (adapterSize == 0) mBinding.progressLayout.showProgress(); + else mBinding.swipeLayout.setRefreshing(true); } public void onRefresh() { diff --git a/app/src/leanback/res/layout/fragment_type.xml b/app/src/leanback/res/layout/fragment_type.xml index 724c3b4c8..a7e7a7fe4 100644 --- a/app/src/leanback/res/layout/fragment_type.xml +++ b/app/src/leanback/res/layout/fragment_type.xml @@ -1,21 +1,27 @@ - - + android:layout_height="match_parent"> - \ No newline at end of file + + + + \ No newline at end of file diff --git a/app/src/mobile/java/com/fongmi/android/tv/ui/activity/VideoActivity.java b/app/src/mobile/java/com/fongmi/android/tv/ui/activity/VideoActivity.java index 09974af48..2e60524a9 100644 --- a/app/src/mobile/java/com/fongmi/android/tv/ui/activity/VideoActivity.java +++ b/app/src/mobile/java/com/fongmi/android/tv/ui/activity/VideoActivity.java @@ -278,6 +278,7 @@ public class VideoActivity extends BaseActivity implements Clock.Callback, Custo @Override protected void initView(Bundle savedInstanceState) { ViewCompat.setOnApplyWindowInsetsListener(mBinding.getRoot(), (v, insets) -> setStatusBar(insets)); + mBinding.swipeLayout.setColorSchemeResources(R.color.accent); mKeyDown = CustomKeyDown.create(this, mBinding.exo); mFrameParams = mBinding.video.getLayoutParams(); mBinding.progressLayout.showProgress(); diff --git a/app/src/mobile/java/com/fongmi/android/tv/ui/fragment/TypeFragment.java b/app/src/mobile/java/com/fongmi/android/tv/ui/fragment/TypeFragment.java index 72fd40da5..572703d7e 100644 --- a/app/src/mobile/java/com/fongmi/android/tv/ui/fragment/TypeFragment.java +++ b/app/src/mobile/java/com/fongmi/android/tv/ui/fragment/TypeFragment.java @@ -13,6 +13,7 @@ import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import androidx.viewbinding.ViewBinding; import com.fongmi.android.tv.Product; +import com.fongmi.android.tv.R; import com.fongmi.android.tv.api.config.VodConfig; import com.fongmi.android.tv.bean.Result; import com.fongmi.android.tv.bean.Site; @@ -95,6 +96,7 @@ public class TypeFragment extends BaseFragment implements CustomScroller.Callbac @Override protected void initView() { + mBinding.swipeLayout.setColorSchemeResources(R.color.accent); mScroller = new CustomScroller(this); mExtends = getExtend(); setRecyclerView(); @@ -104,7 +106,7 @@ public class TypeFragment extends BaseFragment implements CustomScroller.Callbac @Override protected void initEvent() { mBinding.swipeLayout.setOnRefreshListener(this); - mBinding.recycler.addOnScrollListener(mScroller = new CustomScroller(this)); + mBinding.recycler.addOnScrollListener(mScroller); } @Override