From 1ecff571ff9d9ab79046c357f8e3d14b67aee49e Mon Sep 17 00:00:00 2001 From: FongMi Date: Sun, 6 Aug 2023 02:41:11 +0800 Subject: [PATCH] [leanback] support multi view type --- .../java/com/fongmi/android/tv/Product.java | 25 +++++++++++ .../android/tv/ui/base/BaseVodHolder.java | 16 +++++++ .../fongmi/android/tv/ui/base/ViewType.java | 5 ++- .../android/tv/ui/fragment/VodFragment.java | 30 ++++++++----- .../android/tv/ui/holder/VodFolderHolder.java | 5 ++- .../android/tv/ui/holder/VodFullHolder.java | 29 ++++++++++++ .../android/tv/ui/holder/VodGridHolder.java | 11 ++++- .../android/tv/ui/holder/VodOvalHolder.java | 35 +++++++++++++++ .../android/tv/ui/presenter/VodPresenter.java | 41 ++++++++--------- .../res/drawable/selector_vod_oval.xml | 4 ++ .../res/drawable/shape_vod_oval_focused.xml | 9 ++++ .../leanback/res/layout/adapter_vod_full.xml | 25 +++++++++++ .../leanback/res/layout/adapter_vod_oval.xml | 45 +++++++++++++++++++ .../android/tv/ui/holder/VodGridHolder.java | 4 +- .../android/tv/ui/holder/VodOvalHolder.java | 4 +- ...hape_vod_circle.xml => shape_vod_oval.xml} | 0 .../mobile/res/layout/adapter_vod_oval.xml | 2 +- 17 files changed, 247 insertions(+), 43 deletions(-) create mode 100644 app/src/leanback/java/com/fongmi/android/tv/ui/base/BaseVodHolder.java create mode 100644 app/src/leanback/java/com/fongmi/android/tv/ui/holder/VodFullHolder.java create mode 100644 app/src/leanback/java/com/fongmi/android/tv/ui/holder/VodOvalHolder.java create mode 100644 app/src/leanback/res/drawable/selector_vod_oval.xml create mode 100644 app/src/leanback/res/drawable/shape_vod_oval_focused.xml create mode 100644 app/src/leanback/res/layout/adapter_vod_full.xml create mode 100644 app/src/leanback/res/layout/adapter_vod_oval.xml rename app/src/mobile/res/drawable/{shape_vod_circle.xml => shape_vod_oval.xml} (100%) diff --git a/app/src/leanback/java/com/fongmi/android/tv/Product.java b/app/src/leanback/java/com/fongmi/android/tv/Product.java index bdc2046a3..151d95f6a 100644 --- a/app/src/leanback/java/com/fongmi/android/tv/Product.java +++ b/app/src/leanback/java/com/fongmi/android/tv/Product.java @@ -1,6 +1,7 @@ package com.fongmi.android.tv; import com.fongmi.android.tv.ui.activity.LiveActivity; +import com.fongmi.android.tv.ui.base.ViewType; import com.fongmi.android.tv.utils.ResUtil; public class Product { @@ -13,10 +14,34 @@ public class Product { return Math.abs(Setting.getSize() - 7); } + public static int getColumn(int viewType) { + if (viewType == ViewType.LAND) return getColumn() - 1; + if (viewType == ViewType.FULL) return 3; + return getColumn(); + } + public static void bootLive() { LiveActivity.start(App.activity()); } + public static int[] getSpec(int viewType) { + int column = getColumn(viewType); + int space = ResUtil.dp2px(48) + ResUtil.dp2px(16 * (column - 1)); + return getSpec(space, column, viewType); + } + + private static int[] getSpec(int space, int column, int viewType) { + int base = ResUtil.getScreenWidth() - space; + int width = base / column; + return new int[]{width, getHeight(viewType, width)}; + } + + private static int getHeight(int viewType, int value) { + if (viewType == ViewType.LAND) return (int) (value * 0.75f); + if (viewType == ViewType.OVAL) return value; + return (int) (value / 0.75f); + } + public static int getEms() { return Math.min(ResUtil.getScreenWidth() / ResUtil.sp2px(24), 35); } diff --git a/app/src/leanback/java/com/fongmi/android/tv/ui/base/BaseVodHolder.java b/app/src/leanback/java/com/fongmi/android/tv/ui/base/BaseVodHolder.java new file mode 100644 index 000000000..c5d720bb7 --- /dev/null +++ b/app/src/leanback/java/com/fongmi/android/tv/ui/base/BaseVodHolder.java @@ -0,0 +1,16 @@ +package com.fongmi.android.tv.ui.base; + +import android.view.View; + +import androidx.leanback.widget.Presenter; + +import com.fongmi.android.tv.bean.Vod; + +public abstract class BaseVodHolder extends Presenter.ViewHolder { + + public BaseVodHolder(View view) { + super(view); + } + + public abstract void initView(Vod item); +} diff --git a/app/src/leanback/java/com/fongmi/android/tv/ui/base/ViewType.java b/app/src/leanback/java/com/fongmi/android/tv/ui/base/ViewType.java index 025f260ef..06c1a40ee 100644 --- a/app/src/leanback/java/com/fongmi/android/tv/ui/base/ViewType.java +++ b/app/src/leanback/java/com/fongmi/android/tv/ui/base/ViewType.java @@ -3,5 +3,8 @@ package com.fongmi.android.tv.ui.base; public class ViewType { public static final int GRID = 0; - public static final int FOLDER = 1; + public static final int LAND = 1; + public static final int OVAL = 2; + public static final int FULL = 3; + public static final int FOLDER = 99; } diff --git a/app/src/leanback/java/com/fongmi/android/tv/ui/fragment/VodFragment.java b/app/src/leanback/java/com/fongmi/android/tv/ui/fragment/VodFragment.java index 46e196a66..e36e893a7 100644 --- a/app/src/leanback/java/com/fongmi/android/tv/ui/fragment/VodFragment.java +++ b/app/src/leanback/java/com/fongmi/android/tv/ui/fragment/VodFragment.java @@ -19,8 +19,10 @@ import androidx.viewbinding.ViewBinding; import com.fongmi.android.tv.App; import com.fongmi.android.tv.Product; import com.fongmi.android.tv.R; +import com.fongmi.android.tv.api.ApiConfig; import com.fongmi.android.tv.bean.Filter; import com.fongmi.android.tv.bean.Page; +import com.fongmi.android.tv.bean.Site; import com.fongmi.android.tv.bean.Vod; import com.fongmi.android.tv.databinding.FragmentVodBinding; import com.fongmi.android.tv.model.SiteViewModel; @@ -80,10 +82,18 @@ public class VodFragment extends BaseFragment implements CustomScroller.Callback return getArguments().getBoolean("folder"); } + private Site getSite() { + return ApiConfig.get().getSite(getKey()); + } + private Page getLastPage() { return mPages.get(mPages.size() - 1); } + private int getDefaultViewType() { + return isFolder() ? ViewType.FOLDER : getSite().getViewType(); + } + @Override protected ViewBinding getBinding(@NonNull LayoutInflater inflater, @Nullable ViewGroup container) { return mBinding = FragmentVodBinding.inflate(inflater, container, false); @@ -151,9 +161,9 @@ public class VodFragment extends BaseFragment implements CustomScroller.Callback private void addVideo(List items) { if (items.isEmpty()) return; - boolean list = items.get(0).isList(isFolder()); - if (list) mAdapter.addAll(mAdapter.size(), items); - else addGrid(items); + int viewType = items.get(0).getViewType(getDefaultViewType()); + if (viewType == ViewType.FOLDER) mAdapter.addAll(mAdapter.size(), items); + else addGrid(items, viewType); } private void checkPosition() { @@ -169,21 +179,21 @@ public class VodFragment extends BaseFragment implements CustomScroller.Callback getVideo(getTypeId(), String.valueOf(mScroller.addPage())); } - private boolean checkLastSize(List items) { + private boolean checkLastSize(List items, int viewType) { if (mLast == null || items.size() == 0) return false; - int size = Product.getColumn() - mLast.size(); + int size = Product.getColumn(viewType) - mLast.size(); if (size == 0) return false; size = Math.min(size, items.size()); mLast.addAll(mLast.size(), new ArrayList<>(items.subList(0, size))); - addGrid(new ArrayList<>(items.subList(size, items.size()))); + addGrid(new ArrayList<>(items.subList(size, items.size())), viewType); return true; } - private void addGrid(List items) { - if (checkLastSize(items)) return; + private void addGrid(List items, int viewType) { + if (checkLastSize(items, viewType)) return; List rows = new ArrayList<>(); - for (List part : Lists.partition(items, Product.getColumn())) { - mLast = new ArrayObjectAdapter(new VodPresenter(this)); + for (List part : Lists.partition(items, Product.getColumn(viewType))) { + mLast = new ArrayObjectAdapter(new VodPresenter(this, viewType)); mLast.setItems(part, null); rows.add(new ListRow(mLast)); } diff --git a/app/src/leanback/java/com/fongmi/android/tv/ui/holder/VodFolderHolder.java b/app/src/leanback/java/com/fongmi/android/tv/ui/holder/VodFolderHolder.java index 8e2a3063c..529987525 100644 --- a/app/src/leanback/java/com/fongmi/android/tv/ui/holder/VodFolderHolder.java +++ b/app/src/leanback/java/com/fongmi/android/tv/ui/holder/VodFolderHolder.java @@ -3,14 +3,14 @@ package com.fongmi.android.tv.ui.holder; import android.widget.ImageView; import androidx.annotation.NonNull; -import androidx.leanback.widget.Presenter; import com.fongmi.android.tv.bean.Vod; import com.fongmi.android.tv.databinding.AdapterVodFolderBinding; +import com.fongmi.android.tv.ui.base.BaseVodHolder; import com.fongmi.android.tv.ui.presenter.VodPresenter; import com.fongmi.android.tv.utils.ImgUtil; -public class VodFolderHolder extends Presenter.ViewHolder { +public class VodFolderHolder extends BaseVodHolder { private final VodPresenter.OnClickListener listener; public final AdapterVodFolderBinding binding; @@ -21,6 +21,7 @@ public class VodFolderHolder extends Presenter.ViewHolder { this.listener = listener; } + @Override public void initView(Vod item) { binding.name.setText(item.getVodName()); binding.remark.setText(item.getVodRemarks()); diff --git a/app/src/leanback/java/com/fongmi/android/tv/ui/holder/VodFullHolder.java b/app/src/leanback/java/com/fongmi/android/tv/ui/holder/VodFullHolder.java new file mode 100644 index 000000000..79e7f0031 --- /dev/null +++ b/app/src/leanback/java/com/fongmi/android/tv/ui/holder/VodFullHolder.java @@ -0,0 +1,29 @@ +package com.fongmi.android.tv.ui.holder; + +import androidx.annotation.NonNull; + +import com.fongmi.android.tv.bean.Vod; +import com.fongmi.android.tv.databinding.AdapterVodFullBinding; +import com.fongmi.android.tv.ui.base.BaseVodHolder; +import com.fongmi.android.tv.utils.ImgUtil; + +public class VodFullHolder extends BaseVodHolder { + + public final AdapterVodFullBinding binding; + + public VodFullHolder(@NonNull AdapterVodFullBinding binding) { + super(binding.getRoot()); + this.binding = binding; + } + + public VodFullHolder size(int[] size) { + binding.getRoot().getLayoutParams().width = size[0]; + binding.getRoot().getLayoutParams().height = size[1]; + return this; + } + + @Override + public void initView(Vod item) { + ImgUtil.load(item.getVodPic(), binding.image); + } +} diff --git a/app/src/leanback/java/com/fongmi/android/tv/ui/holder/VodGridHolder.java b/app/src/leanback/java/com/fongmi/android/tv/ui/holder/VodGridHolder.java index ab3de4ca6..72a1702c9 100644 --- a/app/src/leanback/java/com/fongmi/android/tv/ui/holder/VodGridHolder.java +++ b/app/src/leanback/java/com/fongmi/android/tv/ui/holder/VodGridHolder.java @@ -1,14 +1,14 @@ package com.fongmi.android.tv.ui.holder; import androidx.annotation.NonNull; -import androidx.leanback.widget.Presenter; import com.fongmi.android.tv.bean.Vod; import com.fongmi.android.tv.databinding.AdapterVodGridBinding; +import com.fongmi.android.tv.ui.base.BaseVodHolder; import com.fongmi.android.tv.ui.presenter.VodPresenter; import com.fongmi.android.tv.utils.ImgUtil; -public class VodGridHolder extends Presenter.ViewHolder { +public class VodGridHolder extends BaseVodHolder { private final VodPresenter.OnClickListener listener; public final AdapterVodGridBinding binding; @@ -19,6 +19,13 @@ public class VodGridHolder extends Presenter.ViewHolder { this.listener = listener; } + public VodGridHolder size(int[] size) { + binding.getRoot().getLayoutParams().width = size[0]; + binding.getRoot().getLayoutParams().height = size[1]; + return this; + } + + @Override public void initView(Vod item) { binding.name.setText(item.getVodName()); binding.year.setText(item.getVodYear()); diff --git a/app/src/leanback/java/com/fongmi/android/tv/ui/holder/VodOvalHolder.java b/app/src/leanback/java/com/fongmi/android/tv/ui/holder/VodOvalHolder.java new file mode 100644 index 000000000..081c05e34 --- /dev/null +++ b/app/src/leanback/java/com/fongmi/android/tv/ui/holder/VodOvalHolder.java @@ -0,0 +1,35 @@ +package com.fongmi.android.tv.ui.holder; + +import androidx.annotation.NonNull; + +import com.fongmi.android.tv.bean.Vod; +import com.fongmi.android.tv.databinding.AdapterVodOvalBinding; +import com.fongmi.android.tv.ui.base.BaseVodHolder; +import com.fongmi.android.tv.ui.presenter.VodPresenter; +import com.fongmi.android.tv.utils.ImgUtil; + +public class VodOvalHolder extends BaseVodHolder { + + private final VodPresenter.OnClickListener listener; + public final AdapterVodOvalBinding binding; + + public VodOvalHolder(@NonNull AdapterVodOvalBinding binding, VodPresenter.OnClickListener listener) { + super(binding.getRoot()); + this.binding = binding; + this.listener = listener; + } + + public VodOvalHolder size(int[] size) { + binding.image.getLayoutParams().width = size[0]; + binding.image.getLayoutParams().height = size[1]; + return this; + } + + @Override + public void initView(Vod item) { + binding.name.setText(item.getVodName()); + binding.getRoot().setOnClickListener(v -> listener.onItemClick(item)); + binding.getRoot().setOnLongClickListener(v -> listener.onLongClick(item)); + ImgUtil.load(item.getVodPic(), binding.image); + } +} diff --git a/app/src/leanback/java/com/fongmi/android/tv/ui/presenter/VodPresenter.java b/app/src/leanback/java/com/fongmi/android/tv/ui/presenter/VodPresenter.java index c6ffc3400..92df356d7 100644 --- a/app/src/leanback/java/com/fongmi/android/tv/ui/presenter/VodPresenter.java +++ b/app/src/leanback/java/com/fongmi/android/tv/ui/presenter/VodPresenter.java @@ -8,17 +8,21 @@ import androidx.leanback.widget.Presenter; import com.fongmi.android.tv.Product; import com.fongmi.android.tv.bean.Vod; import com.fongmi.android.tv.databinding.AdapterVodFolderBinding; +import com.fongmi.android.tv.databinding.AdapterVodFullBinding; import com.fongmi.android.tv.databinding.AdapterVodGridBinding; +import com.fongmi.android.tv.databinding.AdapterVodOvalBinding; +import com.fongmi.android.tv.ui.base.BaseVodHolder; import com.fongmi.android.tv.ui.base.ViewType; import com.fongmi.android.tv.ui.holder.VodFolderHolder; +import com.fongmi.android.tv.ui.holder.VodFullHolder; import com.fongmi.android.tv.ui.holder.VodGridHolder; -import com.fongmi.android.tv.utils.ResUtil; +import com.fongmi.android.tv.ui.holder.VodOvalHolder; public class VodPresenter extends Presenter { private final OnClickListener mListener; private final int viewType; - private int width, height; + private final int[] size; public VodPresenter(OnClickListener listener) { this(listener, ViewType.GRID); @@ -27,7 +31,7 @@ public class VodPresenter extends Presenter { public VodPresenter(OnClickListener listener, int viewType) { this.mListener = listener; this.viewType = viewType; - setLayoutSize(); + this.size = Product.getSpec(viewType); } public interface OnClickListener { @@ -37,32 +41,23 @@ public class VodPresenter extends Presenter { boolean onLongClick(Vod item); } - private void setLayoutSize() { - int space = ResUtil.dp2px(48) + ResUtil.dp2px(16 * (Product.getColumn() - 1)); - int base = ResUtil.getScreenWidth() - space; - width = base / Product.getColumn(); - height = (int) (width / 0.75f); - } - @Override public Presenter.ViewHolder onCreateViewHolder(ViewGroup parent) { - if (viewType == ViewType.FOLDER) return new VodFolderHolder(AdapterVodFolderBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false), mListener); - VodGridHolder holder = new VodGridHolder(AdapterVodGridBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false), mListener); - holder.binding.getRoot().getLayoutParams().width = width; - holder.binding.getRoot().getLayoutParams().height = height; - return holder; + switch (viewType) { + case ViewType.FOLDER: + return new VodFolderHolder(AdapterVodFolderBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false), mListener); + case ViewType.FULL: + return new VodFullHolder(AdapterVodFullBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false)).size(size); + case ViewType.OVAL: + return new VodOvalHolder(AdapterVodOvalBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false), mListener).size(size); + default: + return new VodGridHolder(AdapterVodGridBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false), mListener).size(size); + } } @Override public void onBindViewHolder(Presenter.ViewHolder viewHolder, Object object) { - switch (viewType) { - case ViewType.GRID: - ((VodGridHolder) viewHolder).initView((Vod) object); - break; - case ViewType.FOLDER: - ((VodFolderHolder) viewHolder).initView((Vod) object); - break; - } + ((BaseVodHolder) viewHolder).initView((Vod) object); } @Override diff --git a/app/src/leanback/res/drawable/selector_vod_oval.xml b/app/src/leanback/res/drawable/selector_vod_oval.xml new file mode 100644 index 000000000..7b3dabf2b --- /dev/null +++ b/app/src/leanback/res/drawable/selector_vod_oval.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/src/leanback/res/drawable/shape_vod_oval_focused.xml b/app/src/leanback/res/drawable/shape_vod_oval_focused.xml new file mode 100644 index 000000000..829b75d96 --- /dev/null +++ b/app/src/leanback/res/drawable/shape_vod_oval_focused.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/leanback/res/layout/adapter_vod_full.xml b/app/src/leanback/res/layout/adapter_vod_full.xml new file mode 100644 index 000000000..5fcb543ee --- /dev/null +++ b/app/src/leanback/res/layout/adapter_vod_full.xml @@ -0,0 +1,25 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/leanback/res/layout/adapter_vod_oval.xml b/app/src/leanback/res/layout/adapter_vod_oval.xml new file mode 100644 index 000000000..d6c455855 --- /dev/null +++ b/app/src/leanback/res/layout/adapter_vod_oval.xml @@ -0,0 +1,45 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/mobile/java/com/fongmi/android/tv/ui/holder/VodGridHolder.java b/app/src/mobile/java/com/fongmi/android/tv/ui/holder/VodGridHolder.java index fdd39b23b..af5cc31c4 100644 --- a/app/src/mobile/java/com/fongmi/android/tv/ui/holder/VodGridHolder.java +++ b/app/src/mobile/java/com/fongmi/android/tv/ui/holder/VodGridHolder.java @@ -20,8 +20,8 @@ public class VodGridHolder extends BaseVodHolder { } public VodGridHolder size(int[] size) { - this.itemView.getLayoutParams().width = size[0]; - this.itemView.getLayoutParams().height = size[1]; + itemView.getLayoutParams().width = size[0]; + itemView.getLayoutParams().height = size[1]; return this; } diff --git a/app/src/mobile/java/com/fongmi/android/tv/ui/holder/VodOvalHolder.java b/app/src/mobile/java/com/fongmi/android/tv/ui/holder/VodOvalHolder.java index 3e41fa369..450ead004 100644 --- a/app/src/mobile/java/com/fongmi/android/tv/ui/holder/VodOvalHolder.java +++ b/app/src/mobile/java/com/fongmi/android/tv/ui/holder/VodOvalHolder.java @@ -20,8 +20,8 @@ public class VodOvalHolder extends BaseVodHolder { } public VodOvalHolder size(int[] size) { - this.binding.image.getLayoutParams().width = size[0]; - this.binding.image.getLayoutParams().height = size[1]; + binding.image.getLayoutParams().width = size[0]; + binding.image.getLayoutParams().height = size[1]; return this; } diff --git a/app/src/mobile/res/drawable/shape_vod_circle.xml b/app/src/mobile/res/drawable/shape_vod_oval.xml similarity index 100% rename from app/src/mobile/res/drawable/shape_vod_circle.xml rename to app/src/mobile/res/drawable/shape_vod_oval.xml diff --git a/app/src/mobile/res/layout/adapter_vod_oval.xml b/app/src/mobile/res/layout/adapter_vod_oval.xml index 49f4beaa6..931c9137e 100644 --- a/app/src/mobile/res/layout/adapter_vod_oval.xml +++ b/app/src/mobile/res/layout/adapter_vod_oval.xml @@ -11,7 +11,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@color/black_20" - android:foreground="@drawable/shape_vod_circle" + android:foreground="@drawable/shape_vod_oval" android:scaleType="center" app:shapeAppearanceOverlay="@style/Vod.Circle" tools:src="@drawable/ic_img_loading" />