Use leanback for live

pull/123/head
FongMi 4 years ago
parent 519cbaed65
commit e3ce57f6a2
  1. 56
      app/src/leanback/java/com/fongmi/android/tv/ui/activity/LiveActivity.java
  2. 110
      app/src/leanback/java/com/fongmi/android/tv/ui/adapter/ChannelAdapter.java
  3. 90
      app/src/leanback/java/com/fongmi/android/tv/ui/adapter/GroupAdapter.java
  4. 43
      app/src/leanback/java/com/fongmi/android/tv/ui/adapter/holder/ChannelHolder.java
  5. 35
      app/src/leanback/java/com/fongmi/android/tv/ui/adapter/holder/GroupHolder.java
  6. 53
      app/src/leanback/java/com/fongmi/android/tv/ui/presenter/ChannelPresenter.java
  7. 52
      app/src/leanback/java/com/fongmi/android/tv/ui/presenter/GroupPresenter.java
  8. 2
      app/src/leanback/res/drawable/selector_channel.xml
  9. 2
      app/src/leanback/res/drawable/selector_group.xml
  10. 11
      app/src/leanback/res/layout/activity_live.xml
  11. 1
      app/src/leanback/res/layout/adapter_channel.xml
  12. 3
      app/src/leanback/res/layout/adapter_group.xml
  13. 10
      app/src/main/java/com/fongmi/android/tv/bean/Channel.java
  14. 11
      app/src/main/java/com/fongmi/android/tv/bean/Group.java
  15. 2
      app/src/main/res/values-zh-rCN/strings.xml

@ -6,6 +6,12 @@ import android.os.Handler;
import android.os.Looper;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.leanback.widget.ArrayObjectAdapter;
import androidx.leanback.widget.ItemBridgeAdapter;
import androidx.leanback.widget.OnChildViewHolderSelectedListener;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewbinding.ViewBinding;
import com.fongmi.android.tv.api.LiveConfig;
@ -14,8 +20,8 @@ import com.fongmi.android.tv.bean.Group;
import com.fongmi.android.tv.databinding.ActivityLiveBinding;
import com.fongmi.android.tv.event.PlayerEvent;
import com.fongmi.android.tv.player.Players;
import com.fongmi.android.tv.ui.adapter.ChannelAdapter;
import com.fongmi.android.tv.ui.adapter.GroupAdapter;
import com.fongmi.android.tv.ui.presenter.ChannelPresenter;
import com.fongmi.android.tv.ui.presenter.GroupPresenter;
import com.fongmi.android.tv.utils.Prefers;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout;
@ -25,11 +31,11 @@ import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
public class LiveActivity extends BaseActivity implements GroupAdapter.OnItemClickListener, ChannelAdapter.OnItemClickListener {
public class LiveActivity extends BaseActivity implements GroupPresenter.OnClickListener, ChannelPresenter.OnClickListener {
private ActivityLiveBinding mBinding;
private ChannelAdapter mChannelAdapter;
private GroupAdapter mGroupAdapter;
private ArrayObjectAdapter mChannelAdapter;
private ArrayObjectAdapter mGroupAdapter;
private Handler mHandler;
private Players mPlayers;
@ -41,6 +47,14 @@ public class LiveActivity extends BaseActivity implements GroupAdapter.OnItemCli
return Prefers.getRender() == 0 ? mBinding.surface : mBinding.texture;
}
private Group getGroup() {
return (Group) mGroupAdapter.get(mBinding.group.getSelectedPosition());
}
private Channel getChannel() {
return (Channel) mChannelAdapter.get(mBinding.channel.getSelectedPosition());
}
@Override
protected ViewBinding getBinding() {
return mBinding = ActivityLiveBinding.inflate(getLayoutInflater());
@ -52,17 +66,33 @@ public class LiveActivity extends BaseActivity implements GroupAdapter.OnItemCli
mPlayers = new Players().init();
setRecyclerView();
setVideoView();
getLive();
}
@Override
protected void initEvent() {
EventBus.getDefault().register(this);
mBinding.group.addOnChildViewHolderSelectedListener(new OnChildViewHolderSelectedListener() {
@Override
public void onChildViewHolderSelected(@NonNull RecyclerView parent, @Nullable RecyclerView.ViewHolder child, int position, int subposition) {
onItemClick((Group) mGroupAdapter.get(position));
}
});
mBinding.channel.addOnChildViewHolderSelectedListener(new OnChildViewHolderSelectedListener() {
@Override
public void onChildViewHolderSelected(@NonNull RecyclerView parent, @Nullable RecyclerView.ViewHolder child, int position, int subposition) {
onItemClick((Channel) mChannelAdapter.get(position));
}
});
}
private void setRecyclerView() {
mBinding.group.setAdapter(mGroupAdapter = new GroupAdapter(this));
mBinding.channel.setAdapter(mChannelAdapter = new ChannelAdapter(this));
mGroupAdapter.addAll(LiveConfig.get().getLives().get(0).getGroups());
mBinding.group.setAdapter(new ItemBridgeAdapter(mGroupAdapter = new ArrayObjectAdapter(new GroupPresenter(this))));
mBinding.channel.setAdapter(new ItemBridgeAdapter(mChannelAdapter = new ArrayObjectAdapter(new ChannelPresenter(this))));
}
private void getLive() {
mGroupAdapter.setItems(LiveConfig.get().getLives().get(0).getGroups(), null);
}
private void setVideoView() {
@ -73,11 +103,13 @@ public class LiveActivity extends BaseActivity implements GroupAdapter.OnItemCli
@Override
public void onItemClick(Group item) {
mChannelAdapter.addAll(item);
mChannelAdapter.setItems(item.getChannel(), null);
mBinding.channel.setSelectedPosition(item.getPosition());
}
@Override
public void onItemClick(Channel item) {
getGroup().setPosition(mBinding.channel.getSelectedPosition());
mPlayers.start(item);
}
@ -99,13 +131,13 @@ public class LiveActivity extends BaseActivity implements GroupAdapter.OnItemCli
break;
default:
if (!event.isRetry() || mPlayers.addRetry() > 1) onError();
else mPlayers.start(mChannelAdapter.getCurrent());
//else mPlayers.start(mChannelAdapter.getCurrent());
break;
}
}
private void onError() {
int index = mChannelAdapter.getCurrent().getIndex() + 1;
/*int index = mChannelAdapter.getCurrent().getIndex() + 1;
int size = mChannelAdapter.getCurrent().getUrls().size();
mPlayers.setRetry(0);
if (index == size) {
@ -114,7 +146,7 @@ public class LiveActivity extends BaseActivity implements GroupAdapter.OnItemCli
} else {
mChannelAdapter.getCurrent().setIndex(index);
mPlayers.start(mChannelAdapter.getCurrent());
}
}*/
}
@Override

@ -1,110 +0,0 @@
package com.fongmi.android.tv.ui.adapter;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.fongmi.android.tv.bean.Channel;
import com.fongmi.android.tv.bean.Group;
import com.fongmi.android.tv.databinding.AdapterChannelBinding;
import com.fongmi.android.tv.ui.adapter.holder.ChannelHolder;
import java.util.ArrayList;
import java.util.List;
public class ChannelAdapter extends RecyclerView.Adapter<ChannelHolder> {
private OnItemClickListener mListener;
private final List<Channel> mItems;
private Channel current;
private boolean focus;
private int position;
private Group group;
public ChannelAdapter(OnItemClickListener listener) {
this.mItems = new ArrayList<>();
this.mListener = listener;
}
public interface OnItemClickListener {
void onItemClick(Channel item);
}
private Channel getItem() {
return mItems.get(position);
}
public Channel getCurrent() {
return current;
}
public void setCurrent(Channel current) {
this.current = current;
}
public boolean isFocus() {
return focus;
}
public void setFocus(boolean focus) {
this.focus = focus;
}
public int getPosition() {
return position;
}
public void setPosition(int position) {
this.position = position;
}
public Group getGroup() {
return group;
}
public void setGroup(Group group) {
this.group = group;
}
public void addAll(Group group) {
setGroup(group);
mItems.clear();
mItems.addAll(group.getChannel());
notifyDataSetChanged();
}
public void setSelected() {
for (int i = 0; i < mItems.size(); i++) mItems.get(i).setSelect(i == position);
notifyDataSetChanged();
setFocus(true);
}
public void setChannel() {
if (position < 0 || position > mItems.size() - 1) return;
//if (!getGroup().isHidden()) getItem().putKeep();
mListener.onItemClick(getItem());
getGroup().setPosition(position);
getItem().setGroup(getGroup());
setCurrent(getItem());
setSelected();
}
@Override
public int getItemCount() {
return mItems.size();
}
@NonNull
@Override
public ChannelHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new ChannelHolder(this, AdapterChannelBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false));
}
@Override
public void onBindViewHolder(@NonNull ChannelHolder holder, int position) {
holder.setView(mItems.get(position));
}
}

@ -1,90 +0,0 @@
package com.fongmi.android.tv.ui.adapter;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.fongmi.android.tv.bean.Group;
import com.fongmi.android.tv.databinding.AdapterGroupBinding;
import com.fongmi.android.tv.ui.adapter.holder.GroupHolder;
import java.util.ArrayList;
import java.util.List;
public class GroupAdapter extends RecyclerView.Adapter<GroupHolder> {
private OnItemClickListener mListener;
private final List<Group> mItems;
private final List<Group> mHides;
private boolean focus;
private int position;
public GroupAdapter(OnItemClickListener listener) {
this.mItems = new ArrayList<>();
this.mHides = new ArrayList<>();
this.mListener = listener;
}
public interface OnItemClickListener {
void onItemClick(Group item);
}
private Group getItem() {
return mItems.get(position);
}
public boolean isFocus() {
return focus;
}
public void setFocus(boolean focus) {
this.focus = focus;
}
public int getPosition() {
return position;
}
public void setPosition(int position) {
this.position = position;
}
public void addAll(List<Group> items) {
mItems.clear();
addGroup(items);
notifyDataSetChanged();
}
private void addGroup(List<Group> items) {
for (Group item : items) if (item.isHidden()) mHides.add(item); else mItems.add(item);
}
public void setSelected() {
for (int i = 0; i < mItems.size(); i++) mItems.get(i).setSelect(i == position);
notifyDataSetChanged();
setFocus(true);
}
public void setType() {
mListener.onItemClick(getItem());
}
@Override
public int getItemCount() {
return mItems.size();
}
@NonNull
@Override
public GroupHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new GroupHolder(this, AdapterGroupBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false));
}
@Override
public void onBindViewHolder(@NonNull GroupHolder holder, int position) {
holder.setView(mItems.get(position));
}
}

@ -1,43 +0,0 @@
package com.fongmi.android.tv.ui.adapter.holder;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.fongmi.android.tv.bean.Channel;
import com.fongmi.android.tv.databinding.AdapterChannelBinding;
import com.fongmi.android.tv.ui.adapter.ChannelAdapter;
public class ChannelHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
private final AdapterChannelBinding binding;
private final ChannelAdapter adapter;
public ChannelHolder(ChannelAdapter adapter, @NonNull AdapterChannelBinding binding) {
super(binding.getRoot());
this.binding = binding;
this.adapter = adapter;
itemView.setOnClickListener(this);
itemView.setOnLongClickListener(this);
}
@Override
public void onClick(View view) {
adapter.setPosition(getLayoutPosition());
adapter.setChannel();
}
@Override
public boolean onLongClick(View view) {
adapter.setPosition(getLayoutPosition());
return false;
}
public void setView(Channel item) {
itemView.setSelected(item.isSelect());
binding.name.setText(item.getName());
binding.number.setText(item.getNumber());
binding.icon.setVisibility(item.getVisible());
}
}

@ -1,35 +0,0 @@
package com.fongmi.android.tv.ui.adapter.holder;
import android.view.View;
import androidx.recyclerview.widget.RecyclerView;
import com.fongmi.android.tv.bean.Group;
import com.fongmi.android.tv.databinding.AdapterGroupBinding;
import com.fongmi.android.tv.ui.adapter.GroupAdapter;
public class GroupHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private final AdapterGroupBinding binding;
private final GroupAdapter adapter;
public GroupHolder(GroupAdapter adapter, AdapterGroupBinding binding) {
super(binding.getRoot());
this.binding = binding;
this.adapter = adapter;
itemView.setOnClickListener(this);
}
@Override
public void onClick(View view) {
adapter.setPosition(getLayoutPosition());
adapter.setSelected();
adapter.setType();
}
public void setView(Group item) {
itemView.setSelected(item.isSelect());
binding.name.setText(item.getName());
binding.icon.setVisibility(item.getVisible());
}
}

@ -0,0 +1,53 @@
package com.fongmi.android.tv.ui.presenter;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.leanback.widget.Presenter;
import com.fongmi.android.tv.bean.Channel;
import com.fongmi.android.tv.databinding.AdapterChannelBinding;
public class ChannelPresenter extends Presenter {
private final OnClickListener mListener;
public ChannelPresenter(OnClickListener listener) {
this.mListener = listener;
}
public interface OnClickListener {
void onItemClick(Channel item);
}
@Override
public Presenter.ViewHolder onCreateViewHolder(ViewGroup parent) {
return new ViewHolder(AdapterChannelBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false));
}
@Override
public void onBindViewHolder(Presenter.ViewHolder viewHolder, Object object) {
Channel item = (Channel) object;
ViewHolder holder = (ViewHolder) viewHolder;
holder.binding.name.setText(item.getName());
holder.binding.number.setText(item.getNumber());
holder.binding.icon.setVisibility(item.getVisible());
holder.binding.getRoot().setActivated(item.isActivated());
setOnClickListener(holder, view -> mListener.onItemClick(item));
}
@Override
public void onUnbindViewHolder(Presenter.ViewHolder viewHolder) {
}
public static class ViewHolder extends Presenter.ViewHolder {
private final AdapterChannelBinding binding;
public ViewHolder(@NonNull AdapterChannelBinding binding) {
super(binding.getRoot());
this.binding = binding;
}
}
}

@ -0,0 +1,52 @@
package com.fongmi.android.tv.ui.presenter;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.leanback.widget.Presenter;
import com.fongmi.android.tv.bean.Group;
import com.fongmi.android.tv.databinding.AdapterGroupBinding;
public class GroupPresenter extends Presenter {
private final OnClickListener mListener;
public GroupPresenter(OnClickListener listener) {
this.mListener = listener;
}
public interface OnClickListener {
void onItemClick(Group item);
}
@Override
public Presenter.ViewHolder onCreateViewHolder(ViewGroup parent) {
return new ViewHolder(AdapterGroupBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false));
}
@Override
public void onBindViewHolder(Presenter.ViewHolder viewHolder, Object object) {
Group item = (Group) object;
ViewHolder holder = (ViewHolder) viewHolder;
holder.binding.name.setText(item.getName());
holder.binding.icon.setVisibility(item.getVisible());
holder.binding.getRoot().setActivated(item.isActivated());
setOnClickListener(holder, view -> mListener.onItemClick(item));
}
@Override
public void onUnbindViewHolder(Presenter.ViewHolder viewHolder) {
}
public static class ViewHolder extends Presenter.ViewHolder {
private final AdapterGroupBinding binding;
public ViewHolder(@NonNull AdapterGroupBinding binding) {
super(binding.getRoot());
this.binding = binding;
}
}
}

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/shape_channel" android:state_focused="true" />
<item android:drawable="@drawable/shape_channel" android:state_selected="true" />
<item android:drawable="@drawable/shape_channel" android:state_activated="true" />
</selector>

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/shape_group" android:state_focused="true" />
<item android:drawable="@drawable/shape_group" android:state_selected="true" />
<item android:drawable="@drawable/shape_group" android:state_activated="true" />
</selector>

@ -33,14 +33,12 @@
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="@drawable/shape_live"
android:minWidth="400dp"
android:orientation="horizontal">
<androidx.recyclerview.widget.RecyclerView
<androidx.leanback.widget.VerticalGridView
android:id="@+id/group"
android:layout_width="wrap_content"
android:layout_width="160dp"
android:layout_height="match_parent"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:itemCount="5"
tools:listitem="@layout/adapter_group" />
@ -49,11 +47,10 @@
android:layout_height="match_parent"
android:background="@color/grey_700" />
<androidx.recyclerview.widget.RecyclerView
<androidx.leanback.widget.VerticalGridView
android:id="@+id/channel"
android:layout_width="match_parent"
android:layout_width="240dp"
android:layout_height="match_parent"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:itemCount="5"
tools:listitem="@layout/adapter_channel" />

@ -5,6 +5,7 @@
android:layout_height="wrap_content"
android:background="@drawable/selector_channel"
android:focusable="true"
android:focusableInTouchMode="true"
android:gravity="center"
android:orientation="horizontal"
android:paddingStart="20dp"

@ -5,7 +5,8 @@
android:layout_height="wrap_content"
android:background="@drawable/selector_group"
android:focusable="true"
android:gravity="center_vertical"
android:focusableInTouchMode="true"
android:gravity="center"
android:orientation="horizontal"
android:paddingStart="20dp"
android:paddingTop="12dp"

@ -31,8 +31,8 @@ public class Channel {
@SerializedName("ua")
private String ua;
private boolean activated;
private int index;
private boolean select;
public static Channel objectFrom(JsonElement element) {
return new Gson().fromJson(element, Channel.class);
@ -112,12 +112,12 @@ public class Channel {
this.index = index;
}
public boolean isSelect() {
return select;
public boolean isActivated() {
return activated;
}
public void setSelect(boolean select) {
this.select = select;
public void setActivated(boolean activated) {
this.activated = activated;
}
public int getVisible() {

@ -20,7 +20,8 @@ public class Group {
private String name;
@SerializedName("pass")
private String pass;
private boolean select;
private boolean activated;
private int position;
public Group(String name) {
@ -60,12 +61,12 @@ public class Group {
this.pass = pass;
}
public boolean isSelect() {
return select;
public boolean isActivated() {
return activated;
}
public void setSelect(boolean select) {
this.select = select;
public void setActivated(boolean activated) {
this.activated = activated;
}
public int getPosition() {

@ -53,7 +53,7 @@
<string name="setting_url">配置</string>
<string name="setting_render">渲染方式</string>
<string name="setting_scale">缩放比例</string>
<string name="setting_quality">图片品</string>
<string name="setting_quality">图片品</string>
<string name="setting_size">图片尺寸</string>
<string name="setting_version">版本</string>

Loading…
Cancel
Save