From 39a048f13f5ba8bb4d24e78dbfedeacf2dfd8edd Mon Sep 17 00:00:00 2001 From: jhengazuki Date: Thu, 25 Sep 2025 02:28:43 +0800 Subject: [PATCH] Optimize folder ux --- .../tv/ui/activity/FolderActivity.java | 11 +- .../tv/ui/fragment/FolderFragment.java | 109 ++++++++++++++++++ .../android/tv/ui/fragment/TypeFragment.java | 58 +--------- .../android/tv/ui/fragment/VodFragment.java | 13 ++- app/src/mobile/res/layout/fragment_folder.xml | 11 ++ 5 files changed, 139 insertions(+), 63 deletions(-) create mode 100644 app/src/mobile/java/com/fongmi/android/tv/ui/fragment/FolderFragment.java create mode 100644 app/src/mobile/res/layout/fragment_folder.xml diff --git a/app/src/mobile/java/com/fongmi/android/tv/ui/activity/FolderActivity.java b/app/src/mobile/java/com/fongmi/android/tv/ui/activity/FolderActivity.java index 9d1a6a65e..9c83fae83 100644 --- a/app/src/mobile/java/com/fongmi/android/tv/ui/activity/FolderActivity.java +++ b/app/src/mobile/java/com/fongmi/android/tv/ui/activity/FolderActivity.java @@ -15,7 +15,7 @@ import com.fongmi.android.tv.bean.Class; import com.fongmi.android.tv.bean.Result; import com.fongmi.android.tv.databinding.ActivityFolderBinding; import com.fongmi.android.tv.ui.base.BaseActivity; -import com.fongmi.android.tv.ui.fragment.TypeFragment; +import com.fongmi.android.tv.ui.fragment.FolderFragment; import java.util.HashMap; @@ -55,11 +55,11 @@ public class FolderActivity extends BaseActivity { setSupportActionBar(mBinding.toolbar); Class type = getResult().getTypes().get(0); setTitle(type.getTypeName()); - getSupportFragmentManager().beginTransaction().replace(R.id.container, TypeFragment.newInstance(getKey(), type.getTypeId(), type.getStyle(), new HashMap<>(), "1".equals(type.getTypeFlag()), 8), "0").commit(); + getSupportFragmentManager().beginTransaction().replace(R.id.container, FolderFragment.newInstance(getKey(), type.getTypeId(), type.getStyle(), new HashMap<>(), "1".equals(type.getTypeFlag()), 8), "0").commit(); } - private TypeFragment getFragment() { - return (TypeFragment) getSupportFragmentManager().findFragmentByTag("0"); + private FolderFragment getFragment() { + return (FolderFragment) getSupportFragmentManager().findFragmentByTag("0"); } @Override @@ -70,6 +70,7 @@ public class FolderActivity extends BaseActivity { @Override protected void onBackInvoked() { - if (getFragment().canBack()) super.onBackInvoked(); + if (getFragment().canBack()) getFragment().goBack(); + else super.onBackInvoked(); } } diff --git a/app/src/mobile/java/com/fongmi/android/tv/ui/fragment/FolderFragment.java b/app/src/mobile/java/com/fongmi/android/tv/ui/fragment/FolderFragment.java new file mode 100644 index 000000000..0a87429bf --- /dev/null +++ b/app/src/mobile/java/com/fongmi/android/tv/ui/fragment/FolderFragment.java @@ -0,0 +1,109 @@ +package com.fongmi.android.tv.ui.fragment; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.FragmentTransaction; +import androidx.viewbinding.ViewBinding; + +import com.fongmi.android.tv.R; +import com.fongmi.android.tv.bean.Result; +import com.fongmi.android.tv.bean.Style; +import com.fongmi.android.tv.bean.Value; +import com.fongmi.android.tv.databinding.FragmentFolderBinding; +import com.fongmi.android.tv.ui.base.BaseFragment; +import com.github.catvod.utils.Prefers; + +import java.util.HashMap; +import java.util.Optional; + +public class FolderFragment extends BaseFragment { + + public static FolderFragment newInstance(String key, String typeId, Style style, HashMap extend, boolean folder, int y) { + Bundle args = new Bundle(); + args.putInt("y", y); + args.putString("key", key); + args.putString("typeId", typeId); + args.putBoolean("folder", folder); + args.putParcelable("style", style); + args.putSerializable("extend", extend); + FolderFragment fragment = new FolderFragment(); + fragment.setArguments(args); + return fragment; + } + + private String getKey() { + return getArguments().getString("key"); + } + + private String getTypeId() { + return getArguments().getString("typeId"); + } + + private boolean getFolder() { + return getArguments().getBoolean("folder"); + } + + private Style getStyle() { + return getArguments().getParcelable("style"); + } + + private HashMap getExtend() { + return (HashMap) getArguments().getSerializable("extend"); + } + + private int getY() { + return getArguments().getInt("y"); + } + + private VodFragment getParent() { + return (VodFragment) getParentFragment(); + } + + private TypeFragment getChild() { + return (TypeFragment) getChildFragmentManager().findFragmentById(R.id.container); + } + + @Override + protected ViewBinding getBinding(@NonNull LayoutInflater inflater, @Nullable ViewGroup container) { + return FragmentFolderBinding.inflate(inflater, container, false); + } + + @Override + protected void initView() { + getChildFragmentManager().beginTransaction().replace(R.id.container, TypeFragment.newInstance(getKey(), getTypeId(), getStyle(), getExtend(), getFolder(), getY())).commit(); + } + + public void openFolder(String typeId, HashMap extend) { + Prefers.put("filter_" + getKey() + "_" + typeId, Prefers.getString("filter_" + getKey() + "_" + getTypeId())); + TypeFragment next = TypeFragment.newInstance(getKey(), typeId, getStyle(), extend, getFolder(), getY()); + FragmentTransaction ft = getChildFragmentManager().beginTransaction(); + Optional.ofNullable(getChild()).ifPresent(ft::hide); + ft.add(R.id.container, next); + ft.addToBackStack(null); + ft.commit(); + } + + public Result getResult() { + return getParent().getResult(); + } + + public void scrollToTop() { + Optional.ofNullable(getChild()).ifPresent(TypeFragment::scrollToTop); + } + + public void setFilter(String key, Value value) { + Optional.ofNullable(getChild()).ifPresent(f -> f.setFilter(key, value)); + } + + public boolean canBack() { + return getChildFragmentManager().getBackStackEntryCount() > 0; + } + + public void goBack() { + getChildFragmentManager().popBackStack(); + } +} 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 3c4caf0d1..dab8961e7 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 @@ -14,7 +14,6 @@ import androidx.viewbinding.ViewBinding; import com.fongmi.android.tv.Product; import com.fongmi.android.tv.api.config.VodConfig; -import com.fongmi.android.tv.bean.Page; import com.fongmi.android.tv.bean.Result; import com.fongmi.android.tv.bean.Site; import com.fongmi.android.tv.bean.Style; @@ -30,10 +29,7 @@ import com.fongmi.android.tv.ui.custom.CustomScroller; import com.fongmi.android.tv.utils.Notify; import com.fongmi.android.tv.utils.ResUtil; -import java.io.Serializable; -import java.util.ArrayList; import java.util.HashMap; -import java.util.List; public class TypeFragment extends BaseFragment implements CustomScroller.Callback, VodAdapter.OnClickListener, SwipeRefreshLayout.OnRefreshListener { @@ -42,8 +38,6 @@ public class TypeFragment extends BaseFragment implements CustomScroller.Callbac private CustomScroller mScroller; private SiteViewModel mViewModel; private VodAdapter mAdapter; - private List mPages; - private Page mPage; public static TypeFragment newInstance(String key, String typeId, Style style, HashMap extend, boolean folder, int y) { Bundle args = new Bundle(); @@ -63,16 +57,15 @@ public class TypeFragment extends BaseFragment implements CustomScroller.Callbac } private String getTypeId() { - return mPages.isEmpty() ? getArguments().getString("typeId") : getLastPage().getVodId(); + return getArguments().getString("typeId"); } private Style getStyle() { - return isFolder() ? Style.list() : getSite().getStyle(mPages.isEmpty() ? getArguments().getParcelable("style") : getLastPage().getStyle()); + return isFolder() ? Style.list() : getSite().getStyle(getArguments().getParcelable("style")); } private HashMap getExtend() { - Serializable extend = getArguments().getSerializable("extend"); - return extend == null ? new HashMap<>() : (HashMap) extend; + return (HashMap) getArguments().getSerializable("extend"); } private int getY() { @@ -91,12 +84,8 @@ public class TypeFragment extends BaseFragment implements CustomScroller.Callbac return VodConfig.get().getSite(getKey()); } - private VodFragment getParent() { - return (VodFragment) getParentFragment(); - } - - private Page getLastPage() { - return mPages.get(mPages.size() - 1); + private FolderFragment getParent() { + return (FolderFragment) getParentFragment(); } @Override @@ -107,7 +96,6 @@ public class TypeFragment extends BaseFragment implements CustomScroller.Callbac @Override protected void initView() { mScroller = new CustomScroller(this); - mPages = new ArrayList<>(); mExtends = getExtend(); setRecyclerView(); setViewModel(); @@ -166,7 +154,6 @@ public class TypeFragment extends BaseFragment implements CustomScroller.Callbac mBinding.swipeLayout.setRefreshing(false); if (size > 0) addVideo(result); mScroller.endLoading(result); - checkPosition(first); checkMore(size); } @@ -176,35 +163,11 @@ public class TypeFragment extends BaseFragment implements CustomScroller.Callbac mAdapter.addAll(result.getList()); } - private void checkPosition(boolean first) { - if (mPage != null) scrollToPosition(mPage.getPosition()); - else if (first) mBinding.recycler.scrollToPosition(0); - mPage = null; - } - private void checkMore(int count) { if (mScroller.isDisable() || count == 0 || mBinding.recycler.canScrollVertically(1) || mBinding.recycler.getScrollState() > 0 || isHome()) return; getVideo(getTypeId(), String.valueOf(mScroller.addPage())); } - private int findPosition() { - if (mBinding.recycler.getLayoutManager() instanceof LinearLayoutManager) { - return ((LinearLayoutManager) mBinding.recycler.getLayoutManager()).findFirstVisibleItemPosition(); - } else if (mBinding.recycler.getLayoutManager() instanceof GridLayoutManager) { - return ((GridLayoutManager) mBinding.recycler.getLayoutManager()).findFirstVisibleItemPosition(); - } else { - return 0; - } - } - - private void scrollToPosition(int position) { - if (mBinding.recycler.getLayoutManager() instanceof LinearLayoutManager) { - ((LinearLayoutManager) mBinding.recycler.getLayoutManager()).scrollToPositionWithOffset(position, 0); - } else if (mBinding.recycler.getLayoutManager() instanceof GridLayoutManager) { - ((GridLayoutManager) mBinding.recycler.getLayoutManager()).scrollToPositionWithOffset(position, 0); - } - } - public void scrollToTop() { mBinding.recycler.smoothScrollToPosition(0); } @@ -233,8 +196,7 @@ public class TypeFragment extends BaseFragment implements CustomScroller.Callbac if (item.isAction()) { mViewModel.action(getKey(), item.getAction()); } else if (item.isFolder()) { - mPages.add(Page.get(item, findPosition())); - getVideo(item.getVodId(), "1"); + getParent().openFolder(item.getVodId(), mExtends); } else { if (getSite().isIndex()) SearchActivity.start(requireActivity(), item.getVodName()); else VideoActivity.start(requireActivity(), getKey(), item.getVodId(), item.getVodName(), item.getVodPic(), isFolder() ? item.getVodName() : null); @@ -246,12 +208,4 @@ public class TypeFragment extends BaseFragment implements CustomScroller.Callbac SearchActivity.start(requireActivity(), item.getVodName()); return true; } - - @Override - public boolean canBack() { - if (mPages.isEmpty()) return true; - mPages.remove(mPage = getLastPage()); - onRefresh(); - return false; - } } diff --git a/app/src/mobile/java/com/fongmi/android/tv/ui/fragment/VodFragment.java b/app/src/mobile/java/com/fongmi/android/tv/ui/fragment/VodFragment.java index bb3dccf6f..61dc97641 100644 --- a/app/src/mobile/java/com/fongmi/android/tv/ui/fragment/VodFragment.java +++ b/app/src/mobile/java/com/fongmi/android/tv/ui/fragment/VodFragment.java @@ -70,8 +70,8 @@ public class VodFragment extends BaseFragment implements ConfigCallback, SiteCal return new VodFragment(); } - private TypeFragment getFragment() { - return (TypeFragment) mBinding.pager.getAdapter().instantiateItem(mBinding.pager, mBinding.pager.getCurrentItem()); + private FolderFragment getFragment() { + return (FolderFragment) mBinding.pager.getAdapter().instantiateItem(mBinding.pager, mBinding.pager.getCurrentItem()); } private Site getSite() { @@ -286,9 +286,10 @@ public class VodFragment extends BaseFragment implements ConfigCallback, SiteCal @Override public boolean canBack() { - if (mBinding.pager.getAdapter() == null) return true; - if (mBinding.pager.getAdapter().getCount() == 0) return true; - return getFragment().canBack(); + if (mBinding.pager.getAdapter() == null || mBinding.pager.getAdapter().getCount() == 0) return true; + if (!getFragment().canBack()) return true; + getFragment().goBack(); + return false; } @Override @@ -312,7 +313,7 @@ public class VodFragment extends BaseFragment implements ConfigCallback, SiteCal @Override public Fragment getItem(int position) { Class type = mAdapter.get(position); - return TypeFragment.newInstance(getSite().getKey(), type.getTypeId(), type.getStyle(), type.getExtend(true), "1".equals(type.getTypeFlag()), 4); + return FolderFragment.newInstance(getSite().getKey(), type.getTypeId(), type.getStyle(), type.getExtend(true), "1".equals(type.getTypeFlag()), 4); } @Override diff --git a/app/src/mobile/res/layout/fragment_folder.xml b/app/src/mobile/res/layout/fragment_folder.xml new file mode 100644 index 000000000..beba12a85 --- /dev/null +++ b/app/src/mobile/res/layout/fragment_folder.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file