Add episode view switch

pull/220/head
FongMi 2 years ago
parent 18ba62f95e
commit 136ed7d36f
  1. 9
      app/src/leanback/java/com/fongmi/android/tv/ui/activity/SettingPlayerActivity.java
  2. 107
      app/src/leanback/java/com/fongmi/android/tv/ui/activity/VideoActivity.java
  3. 16
      app/src/leanback/java/com/fongmi/android/tv/ui/adapter/QualityAdapter.java
  4. 8
      app/src/leanback/java/com/fongmi/android/tv/ui/presenter/PartPresenter.java
  5. 29
      app/src/leanback/res/layout/activity_setting_player.xml
  6. 14
      app/src/leanback/res/layout/activity_video.xml
  7. 2
      app/src/leanback/res/layout/adapter_array.xml
  8. 2
      app/src/leanback/res/layout/adapter_episode.xml
  9. 1
      app/src/leanback/res/layout/adapter_flag.xml
  10. 1
      app/src/leanback/res/layout/adapter_part.xml
  11. 1
      app/src/leanback/res/layout/adapter_quality.xml
  12. 12
      app/src/main/java/com/fongmi/android/tv/Setting.java
  13. 6
      app/src/main/res/values-zh-rCN/strings.xml
  14. 6
      app/src/main/res/values-zh-rTW/strings.xml
  15. 6
      app/src/main/res/values/strings.xml

@ -30,6 +30,7 @@ public class SettingPlayerActivity extends BaseActivity implements UaCallback, B
private ActivitySettingPlayerBinding mBinding;
private String[] danmuSpeed;
private String[] caption;
private String[] episode;
private String[] player;
private String[] render;
private String[] scale;
@ -64,6 +65,7 @@ public class SettingPlayerActivity extends BaseActivity implements UaCallback, B
mBinding.scaleText.setText((scale = ResUtil.getStringArray(R.array.select_scale))[Setting.getScale()]);
mBinding.playerText.setText((player = ResUtil.getStringArray(R.array.select_player))[Setting.getPlayer()]);
mBinding.renderText.setText((render = ResUtil.getStringArray(R.array.select_render))[Setting.getRender()]);
mBinding.episodeText.setText((episode = ResUtil.getStringArray(R.array.select_episode))[Setting.getEpisode()]);
mBinding.captionText.setText((caption = ResUtil.getStringArray(R.array.select_caption))[Setting.isCaption() ? 1 : 0]);
mBinding.danmuSpeedText.setText((danmuSpeed = ResUtil.getStringArray(R.array.select_danmu_speed))[Setting.getDanmuSpeed()]);
}
@ -78,6 +80,7 @@ public class SettingPlayerActivity extends BaseActivity implements UaCallback, B
mBinding.player.setOnClickListener(this::setPlayer);
mBinding.render.setOnClickListener(this::setRender);
mBinding.tunnel.setOnClickListener(this::setTunnel);
mBinding.episode.setOnClickListener(this::setEpisode);
mBinding.caption.setOnClickListener(this::setCaption);
mBinding.subtitle.setOnClickListener(this::onSubtitle);
mBinding.caption.setOnLongClickListener(this::onCaption);
@ -150,6 +153,12 @@ public class SettingPlayerActivity extends BaseActivity implements UaCallback, B
mBinding.tunnelText.setText(getSwitch(Setting.isTunnel()));
}
private void setEpisode(View view) {
int index = Setting.getEpisode();
Setting.putEpisode(index = index == episode.length - 1 ? 0 : ++index);
mBinding.episodeText.setText(episode[index]);
}
private void setCaption(View view) {
Setting.putCaption(!Setting.isCaption());
mBinding.captionText.setText(caption[Setting.isCaption() ? 1 : 0]);

@ -23,6 +23,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.FragmentActivity;
import androidx.leanback.widget.ArrayObjectAdapter;
import androidx.leanback.widget.BaseGridView;
import androidx.leanback.widget.ItemBridgeAdapter;
import androidx.leanback.widget.OnChildViewHolderSelectedListener;
import androidx.lifecycle.ViewModelProvider;
@ -276,6 +277,10 @@ public class VideoActivity extends BaseActivity implements CustomKeyDownVod.List
return mBinding.ijk;
}
private BaseGridView getEpisodeView() {
return Setting.getEpisode() == 0 ? mBinding.episodeHori : mBinding.episodeVert;
}
private boolean isReplay() {
return Setting.getReset() == 1;
}
@ -302,6 +307,7 @@ public class VideoActivity extends BaseActivity implements CustomKeyDownVod.List
mR3 = this::showEmpty;
setBackground(false);
setRecyclerView();
setEpisodeView();
setVideoView();
setDanmuView();
setViewModel();
@ -352,7 +358,7 @@ public class VideoActivity extends BaseActivity implements CustomKeyDownVod.List
if (mFlagAdapter.size() > 0) setFlagActivated((Flag) mFlagAdapter.get(position));
}
});
mBinding.episode.addOnChildViewHolderSelectedListener(new OnChildViewHolderSelectedListener() {
getEpisodeView().addOnChildViewHolderSelectedListener(new OnChildViewHolderSelectedListener() {
@Override
public void onChildViewHolderSelected(@NonNull RecyclerView parent, @Nullable RecyclerView.ViewHolder child, int position, int subposition) {
if (child != null && mBinding.video != mFocus1) mFocus1 = child.itemView;
@ -361,7 +367,7 @@ public class VideoActivity extends BaseActivity implements CustomKeyDownVod.List
mBinding.array.addOnChildViewHolderSelectedListener(new OnChildViewHolderSelectedListener() {
@Override
public void onChildViewHolderSelected(@NonNull RecyclerView parent, @Nullable RecyclerView.ViewHolder child, int position, int subposition) {
if (mEpisodeAdapter.size() > 20 && position > 1) mBinding.episode.setSelectedPosition((position - 2) * 20);
if (mEpisodeAdapter.size() > 20 && position > 1) getEpisodeView().setSelectedPosition((position - 2) * 20);
}
});
}
@ -370,9 +376,6 @@ public class VideoActivity extends BaseActivity implements CustomKeyDownVod.List
mBinding.flag.setHorizontalSpacing(ResUtil.dp2px(8));
mBinding.flag.setRowHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
mBinding.flag.setAdapter(new ItemBridgeAdapter(mFlagAdapter = new ArrayObjectAdapter(mFlagPresenter = new FlagPresenter(this::setFlagActivated))));
mBinding.episode.setVerticalSpacing(ResUtil.dp2px(8));
mBinding.episode.setHorizontalSpacing(ResUtil.dp2px(8));
mBinding.episode.setAdapter(new ItemBridgeAdapter(mEpisodeAdapter = new ArrayObjectAdapter(mEpisodePresenter = new EpisodePresenter(this::setEpisodeActivated))));
mBinding.quality.setHorizontalSpacing(ResUtil.dp2px(8));
mBinding.quality.setRowHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
mBinding.quality.setAdapter(mQualityAdapter = new QualityAdapter(this::setQualityActivated));
@ -391,6 +394,13 @@ public class VideoActivity extends BaseActivity implements CustomKeyDownVod.List
mParseAdapter.setItems(VodConfig.get().getParses(), null);
}
private void setEpisodeView() {
getEpisodeView().setHorizontalSpacing(ResUtil.dp2px(8));
getEpisodeView().setAdapter(new ItemBridgeAdapter(mEpisodeAdapter = new ArrayObjectAdapter(mEpisodePresenter = new EpisodePresenter(this::setEpisodeActivated))));
if (Setting.getEpisode() == 0) mBinding.episodeHori.setRowHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
else mBinding.episodeVert.setVerticalSpacing(ResUtil.dp2px(8));
}
private void setVideoView() {
mPlayers.set(getExo(), getIjk());
getExo().getSubtitleView().setStyle(ExoUtil.getCaptionStyle());
@ -589,6 +599,14 @@ public class VideoActivity extends BaseActivity implements CustomKeyDownVod.List
}
private void setEpisodeAdapter(List<Episode> items) {
getEpisodeView().setVisibility(items.isEmpty() ? View.GONE : View.VISIBLE);
if (items.size() > 0 && Setting.getEpisode() == 1) setEpisodeView(items);
mEpisodeAdapter.setItems(items, null);
setArrayAdapter(items.size());
updateFocus();
}
private void setEpisodeView(List<Episode> items) {
int size = items.size();
for (int i = 0; i < size; i++) items.get(i).setIndex(i);
int episodeNameLength = items.isEmpty() ? 0 : items.get(0).getName().length();
@ -600,18 +618,14 @@ public class VideoActivity extends BaseActivity implements CustomKeyDownVod.List
if (size < numColumns) numColumns = size;
int rowNum = (int) Math.ceil((double) size / (double) numColumns);
int width = ResUtil.getScreenWidth() - ResUtil.dp2px(48);
mBinding.episode.setNumColumns(numColumns);
mBinding.episode.setColumnWidth((width - ((numColumns - 1) * ResUtil.dp2px(8))) / numColumns);
ViewGroup.LayoutParams layoutParams = mBinding.episode.getLayoutParams();
layoutParams.width = ResUtil.getScreenWidth();
layoutParams.height = rowNum > 6 ? ResUtil.dp2px(300) : ResUtil.dp2px(rowNum * 50);
mBinding.episode.setLayoutParams(layoutParams);
mBinding.episode.setVisibility(items.isEmpty() ? View.GONE : View.VISIBLE);
ViewGroup.LayoutParams params = mBinding.episodeVert.getLayoutParams();
params.width = ResUtil.getScreenWidth();
params.height = rowNum > 6 ? ResUtil.dp2px(300) : ResUtil.dp2px(rowNum * 50);
mBinding.episodeVert.setNumColumns(numColumns);
mBinding.episodeVert.setColumnWidth((width - ((numColumns - 1) * ResUtil.dp2px(8))) / numColumns);
mBinding.episodeVert.setLayoutParams(params);
mEpisodePresenter.setNumColumns(numColumns);
mEpisodePresenter.setNumRows(rowNum);
mEpisodeAdapter.setItems(items, null);
setArray(size);
updateFocus();
}
private void seamless(Flag flag) {
@ -620,8 +634,8 @@ public class VideoActivity extends BaseActivity implements CustomKeyDownVod.List
if (episode == null || episode.isActivated()) return;
if (Setting.getFlag() == 1) {
episode.setActivated(true);
mBinding.episode.requestFocus();
mBinding.episode.setSelectedPosition(getEpisodePosition());
getEpisodeView().requestFocus();
getEpisodeView().setSelectedPosition(getEpisodePosition());
episode.setActivated(false);
} else {
mHistory.setVodRemarks(episode.getName());
@ -634,24 +648,16 @@ public class VideoActivity extends BaseActivity implements CustomKeyDownVod.List
if (shouldEnterFullscreen(item)) return;
setCurrentFlag(mBinding.flag.getSelectedPosition());
for (int i = 0; i < mFlagAdapter.size(); i++) ((Flag) mFlagAdapter.get(i)).toggle(getCurrentFlag() == i, item);
mBinding.episode.setSelectedPosition(getEpisodePosition());
notifyItemChanged(mBinding.episode, mEpisodeAdapter);
getEpisodeView().setSelectedPosition(getEpisodePosition());
notifyItemChanged(getEpisodeView(), mEpisodeAdapter);
if (mEpisodeAdapter.size() == 0) return;
if (isFullscreen()) Notify.show(getString(R.string.play_ready, item.getName()));
onRefresh();
}
private void setQualityVisible(boolean visible) {
mArrayPresenter.setNextFocusDown(isVisible(mBinding.episode) ? R.id.episode : R.id.part);
mFlagPresenter.setNextFocusDown(visible ? R.id.quality : R.id.array);
mBinding.quality.setVisibility(visible ? View.VISIBLE : View.GONE);
mArrayPresenter.setNextFocusUp(visible ? R.id.quality : R.id.flag);
mEpisodePresenter.setNextFocusUp(R.id.array);
mQualityAdapter.setNextFocusDown(R.id.array);
mQualityAdapter.setNextFocusUp(R.id.flag);
notifyItemChanged(mBinding.episode, mEpisodeAdapter);
notifyItemChanged(mBinding.array, mArrayAdapter);
notifyItemChanged(mBinding.flag, mFlagAdapter);
updateFocus();
}
private void setQualityActivated(Result result) {
@ -668,7 +674,7 @@ public class VideoActivity extends BaseActivity implements CustomKeyDownVod.List
private void reverseEpisode(boolean scroll) {
for (int i = 0; i < mFlagAdapter.size(); i++) Collections.reverse(((Flag) mFlagAdapter.get(i)).getEpisodes());
setEpisodeAdapter(getFlag().getEpisodes());
if (scroll) mBinding.episode.setSelectedPosition(getEpisodePosition());
if (scroll) getEpisodeView().setSelectedPosition(getEpisodePosition());
}
private void setParseActivated(Parse item) {
@ -677,7 +683,7 @@ public class VideoActivity extends BaseActivity implements CustomKeyDownVod.List
onRefresh();
}
private void setArray(int size) {
private void setArrayAdapter(int size) {
List<String> items = new ArrayList<>();
items.add(getString(R.string.play_reverse));
items.add(getString(mHistory.getRevPlayText()));
@ -688,10 +694,27 @@ public class VideoActivity extends BaseActivity implements CustomKeyDownVod.List
}
private void updateFocus() {
mPartPresenter.setNextFocusUp(isVisible(mBinding.episode) ? R.id.episode : R.id.array);
mEpisodePresenter.setNextFocusDown(isVisible(mBinding.part) ? R.id.part : R.id.flag);
notifyItemChanged(mBinding.episode, mEpisodeAdapter);
if (Setting.getEpisode() == 0) {
mArrayPresenter.setNextFocusUp(R.id.episodeHori);
mQualityAdapter.setNextFocusDown(R.id.episodeHori);
mArrayPresenter.setNextFocusDown(isVisible(mBinding.part) ? R.id.part : R.id.quick);
mEpisodePresenter.setNextFocusDown(isVisible(mBinding.array) ? R.id.array : R.id.part);
mEpisodePresenter.setNextFocusUp(isVisible(mBinding.quality) ? R.id.quality : R.id.flag);
mPartPresenter.setNextFocusUp(isVisible(mBinding.array) ? R.id.array : R.id.episodeHori);
mFlagPresenter.setNextFocusDown(isVisible(mBinding.quality) ? R.id.quality : R.id.episodeHori);
} else {
mArrayPresenter.setNextFocusDown(R.id.episodeVert);
mEpisodePresenter.setNextFocusDown(isVisible(mBinding.part) ? R.id.part : R.id.quick);
mArrayPresenter.setNextFocusUp(isVisible(mBinding.quality) ? R.id.quality : R.id.flag);
mQualityAdapter.setNextFocusDown(isVisible(mBinding.array) ? R.id.array : R.id.episodeVert);
mEpisodePresenter.setNextFocusUp(isVisible(mBinding.array) ? R.id.array : isVisible(mBinding.quality) ? R.id.quality : R.id.flag);
mFlagPresenter.setNextFocusDown(isVisible(mBinding.quality) ? R.id.quality : isVisible(mBinding.array) ? R.id.array : R.id.episodeVert);
mPartPresenter.setNextFocusUp(isVisible(mBinding.episodeVert) ? R.id.episodeVert : isVisible(mBinding.quality) ? R.id.quality : R.id.flag);
}
notifyItemChanged(getEpisodeView(), mEpisodeAdapter);
notifyItemChanged(mBinding.array, mArrayAdapter);
notifyItemChanged(mBinding.part, mPartAdapter);
notifyItemChanged(mBinding.flag, mFlagAdapter);
}
@Override
@ -1055,25 +1078,23 @@ public class VideoActivity extends BaseActivity implements CustomKeyDownVod.List
public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
List<String> items = Part.get(response.body().string());
if (!items.contains(source)) items.add(0, source);
App.post(() -> {
mBinding.part.setVisibility(View.VISIBLE);
mPartAdapter.setItems(items, null);
updateFocus();
});
App.post(() -> setPartAdapter(items));
}
@Override
public void onFailure(@NonNull Call call, @NonNull IOException e) {
List<String> items = List.of(source);
App.post(() -> {
mBinding.part.setVisibility(View.VISIBLE);
mPartAdapter.setItems(items, null);
updateFocus();
});
App.post(() -> setPartAdapter(items));
}
});
}
private void setPartAdapter(List<String> items) {
mBinding.part.setVisibility(View.VISIBLE);
mPartAdapter.setItems(items, null);
updateFocus();
}
private void checkFlag(Vod item) {
boolean empty = item.getVodFlags().isEmpty();
mBinding.flag.setVisibility(empty ? View.GONE : View.VISIBLE);

@ -12,10 +12,9 @@ import com.fongmi.android.tv.databinding.AdapterQualityBinding;
public class QualityAdapter extends RecyclerView.Adapter<QualityAdapter.ViewHolder> {
private final OnClickListener mListener;
private int nextFocusDown;
private Result mResult;
private int position;
private int nextFocusUp;
private int nextFocusDown;
public QualityAdapter(OnClickListener listener) {
this.mListener = listener;
@ -27,18 +26,14 @@ public class QualityAdapter extends RecyclerView.Adapter<QualityAdapter.ViewHold
void onItemClick(Result result);
}
public int getPosition() {
return position;
}
public void setNextFocusUp(int nextFocusUp) {
this.nextFocusUp = nextFocusUp;
}
public void setNextFocusDown(int nextFocusDown) {
this.nextFocusDown = nextFocusDown;
}
public int getPosition() {
return position;
}
public void addAll(Result result) {
mResult = result;
notifyDataSetChanged();
@ -57,7 +52,6 @@ public class QualityAdapter extends RecyclerView.Adapter<QualityAdapter.ViewHold
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
holder.binding.text.setNextFocusUpId(nextFocusUp);
holder.binding.text.setNextFocusDownId(nextFocusDown);
holder.binding.text.setText(mResult.getUrl().n(position));
holder.binding.text.setOnClickListener(v -> onItemClick(position));

@ -12,7 +12,7 @@ import com.fongmi.android.tv.databinding.AdapterPartBinding;
public class PartPresenter extends Presenter {
private final OnClickListener mListener;
private int nextFocus;
private int nextFocusUp;
public PartPresenter(OnClickListener listener) {
this.mListener = listener;
@ -22,8 +22,8 @@ public class PartPresenter extends Presenter {
void onItemClick(String item);
}
public void setNextFocusUp(int nextFocus) {
this.nextFocus = nextFocus;
public void setNextFocusUp(int nextFocusUp) {
this.nextFocusUp = nextFocusUp;
}
@Override
@ -37,7 +37,7 @@ public class PartPresenter extends Presenter {
ViewHolder holder = (ViewHolder) viewHolder;
holder.binding.text.setText(text);
holder.binding.text.setMaxEms(Product.getEms());
holder.binding.text.setNextFocusUpId(nextFocus);
holder.binding.text.setNextFocusUpId(nextFocusUp);
setOnClickListener(holder, view -> mListener.onItemClick(text));
}

@ -291,6 +291,35 @@
</LinearLayout>
<LinearLayout
android:id="@+id/episode"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:background="@drawable/selector_item"
android:focusable="true"
android:focusableInTouchMode="true"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:text="@string/player_episode"
android:textColor="@color/white"
android:textSize="18sp" />
<TextView
android:id="@+id/episodeText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="end"
android:textColor="@color/white"
android:textSize="18sp"
tools:text="單列" />
</LinearLayout>
<LinearLayout
android:id="@+id/tunnel"
android:layout_width="match_parent"

@ -287,6 +287,18 @@
android:paddingBottom="8dp"
android:visibility="gone" />
<com.fongmi.android.tv.ui.custom.CustomHorizontalGridView
android:id="@+id/episodeHori"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipChildren="false"
android:clipToPadding="false"
android:paddingStart="24dp"
android:paddingTop="8dp"
android:paddingEnd="24dp"
android:paddingBottom="8dp"
android:visibility="gone" />
<com.fongmi.android.tv.ui.custom.CustomHorizontalGridView
android:id="@+id/array"
android:layout_width="match_parent"
@ -300,7 +312,7 @@
android:visibility="gone" />
<androidx.leanback.widget.VerticalGridView
android:id="@+id/episode"
android:id="@+id/episodeVert"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipChildren="false"

@ -8,8 +8,6 @@
android:focusable="true"
android:focusableInTouchMode="true"
android:gravity="center"
android:nextFocusUp="@id/episode"
android:nextFocusDown="@id/part"
android:textColor="@color/white"
android:textSize="16sp"
tools:text="11" />

@ -9,8 +9,6 @@
android:focusable="true"
android:focusableInTouchMode="true"
android:gravity="center"
android:nextFocusUp="@id/flag"
android:nextFocusDown="@id/array"
android:singleLine="true"
android:textColor="@color/text"
android:textSize="16sp"

@ -8,7 +8,6 @@
android:focusable="true"
android:focusableInTouchMode="true"
android:gravity="center"
android:nextFocusDown="@id/episode"
android:textColor="@color/text"
android:textSize="16sp"
tools:text="泥巴" />

@ -9,7 +9,6 @@
android:focusable="true"
android:focusableInTouchMode="true"
android:gravity="center"
android:nextFocusUp="@id/array"
android:singleLine="true"
android:textColor="@color/white"
android:textSize="16sp"

@ -10,7 +10,6 @@
android:focusableInTouchMode="true"
android:gravity="center"
android:nextFocusUp="@id/flag"
android:nextFocusDown="@id/episode"
android:singleLine="true"
android:textColor="@color/text"
android:textSize="16sp"

@ -173,8 +173,16 @@ public class Setting {
return Prefers.getInt("flag");
}
public static void putFlag(int mode) {
Prefers.put("flag", mode);
public static void putFlag(int flag) {
Prefers.put("flag", flag);
}
public static int getEpisode() {
return Prefers.getInt("episode");
}
public static void putEpisode(int episode) {
Prefers.put("episode", episode);
}
public static int getBackground() {

@ -89,6 +89,7 @@
<string name="player_danmu_line">弹幕行数</string>
<string name="player_background">后台播放</string>
<string name="player_flag">线路播放</string>
<string name="player_episode">选集样式</string>
<string name="player_exo_tunnel">隧道模式</string>
<string name="player_exo_http">连线方式</string>
<string name="player_exo_buffer">缓冲时间</string>
@ -192,6 +193,11 @@
<item>手动</item>
</string-array>
<string-array name="select_episode">
<item>单列</item>
<item>多列</item>
</string-array>
<string-array name="select_caption">
<item>预设</item>
<item>系统</item>

@ -89,6 +89,7 @@
<string name="player_danmu_line">彈幕行數</string>
<string name="player_background">背景播放</string>
<string name="player_flag">線路播放</string>
<string name="player_episode">選集樣式</string>
<string name="player_exo_tunnel">隧道模式</string>
<string name="player_exo_http">連線方式</string>
<string name="player_exo_buffer">緩衝時間</string>
@ -192,6 +193,11 @@
<item>手動</item>
</string-array>
<string-array name="select_episode">
<item>單列</item>
<item>多列</item>
</string-array>
<string-array name="select_caption">
<item>預設</item>
<item>系統</item>

@ -89,6 +89,7 @@
<string name="player_danmu_line">Danmu line</string>
<string name="player_background">Background play</string>
<string name="player_flag">Flag play</string>
<string name="player_episode">Episode style</string>
<string name="player_exo_tunnel">Tunnel mode</string>
<string name="player_exo_http">HTTP method</string>
<string name="player_exo_buffer">Buffer time</string>
@ -197,6 +198,11 @@
<item>Manual</item>
</string-array>
<string-array name="select_episode">
<item>Single</item>
<item>Multiple</item>
</string-array>
<string-array name="select_caption">
<item>Default</item>
<item>System</item>

Loading…
Cancel
Save