android tv 列表滚动控件-MetroRecyclerV

2019-10-17  本文已影响0人  ihu11

焦点展示结合了----FlowView-https://www.jianshu.com/p/dd559bcae221

github库---demo源码-https://github.com/ihu11/MetroRecyclerView

1.类GridView的实现,先看效果图

device-2019-10-17-101627.gif

功能
1、基于RecyclerView实现,主要实现了列表数据的展现,包括了横向滚动的列表和竖向滚动的列表模式。

2、控件对于上下左右事件的响应是立即的,不存在卡顿。

3、实现了动态增加,修改和删除列表项的功能。

4、图片的加载可以实现延迟加载,在用户松开遥控器时才加载,优化内存和网络加载的速度。

5、内部封装了各种事件监听器,包括了
1)焦点选择回调事件(MetroItemFocusListener),响应遥控器方向控制事件,当用户选择了列表中的一个项后,这个事件只在焦点移动停止后才会响应,回调给控件使用者,当前选择的项是哪个。
2)列表项点击事件(MetroItemClickListener),当前焦点在列表中时,点击遥控器的确定键或触摸点击到某个项则回调控件使用者,当前点击的是哪个项。
3)滚动到最顶端或最底端事件(OnScrollEndListener),当滚动到了列表的最顶端或最低端时,用户在继续按遥控器滚动时回调给控件使用者,当前已经到顶或底了,方便使用者加载分页数据。
4)焦点移动事件(OnMoveToListener),响应遥控器方向控制事件,移动焦点框到选择的位置上,和焦点选择事件不同,焦点移动每次移动都会回调,不用等事件停止,用于与焦点框控件交互,告诉焦点框需要把焦点移动到什么位置。
5)列表项长按事件(MetroItemLongClickListener),与列表项点击事件类似,不过这个只响应长按。
6)滚动条位置监听事件(OnScrollBarStatusListener),每次滚动完回调给使用者,列表项还能否继续向上或向下滚动,用于提示滚动条的位置。

6、优化滚动的效果,使界面滚动的之后更加平滑。

7、列表控件界面自动获得焦点的功能。

8、三种翻页模式:1.当焦点到了最后一行才往下滚,2.当焦点在倒数第二行在向下就自动滚动。3.在可以滚动时,焦点永远在中间,悠闲滚动布局,再移动焦点。

先上代码

package com.ihu11.metrorecylcerview;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;

import com.ihu11.metro.flow.FlowView;
import com.ihu11.metro.recycler.MetroItemClickListener;
import com.ihu11.metro.recycler.MetroItemFocusListener;
import com.ihu11.metro.recycler.MetroRecyclerView;
import com.ihu11.metro.recycler.OnMoveToListener;

import java.util.ArrayList;
import java.util.List;

public class GridActivity extends Activity {

    private MetroRecyclerView recyclerView;
    private FlowView flowView;
    private MyAdapter adapter;
    private List<Integer> dataList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_grid);

        flowView = findViewById(R.id.flow_view);
        recyclerView = findViewById(R.id.recycler_view);

        recyclerView.setScrollType(MetroRecyclerView.SCROLL_TYPE_ALWAYS_CENTER);
        MetroRecyclerView.MetroGridLayoutManager layoutManager = new MetroRecyclerView.MetroGridLayoutManager(
                this, 6, MetroRecyclerView.VERTICAL);
        recyclerView.setLayoutManager(layoutManager);
        recyclerView.setOnMoveToListener(new OnMoveToListener() {
            @Override
            public void onMoveTo(View view, float scale, int offsetX, int offsetY, boolean isSmooth) {
                flowView.moveTo(view, scale, offsetX, offsetY, isSmooth);
            }
        });
        recyclerView.setOnItemClickListener(new MetroItemClickListener() {
            @Override
            public void onItemClick(View parentView, View itemView, int position) {
                //TODO
            }
        });
        recyclerView.setOnItemFocusListener(new MetroItemFocusListener() {
            @Override
            public void onItemFocus(View parentView, View itemView, int position, int total) {
                //TODO
            }
        });
        recyclerView.setOnScrollEndListener(new MetroRecyclerView.OnScrollEndListener() {
            @Override
            public void onScrollToBottom(int keyCode) {
                //滑动到底部回调,用于刷新数据,每次到底部都会有回调,可能会回调多次,注意异步操作时的控制
                int size = dataList.size();
                dataList.addAll(genData());
                adapter.notifyItemInserted(size);
            }

            @Override
            public void onScrollToTop(int keyCode) {
            }
        });


        dataList = genData();
        adapter = new MyAdapter(dataList);
        recyclerView.setAdapter(adapter);
        recyclerView.requestFocus();
    }

    private List<Integer> genData() {
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < 24; i++) {
            if (i % 5 == 0) {
                list.add(R.drawable.a1);
            } else if (i % 5 == 1) {
                list.add(R.drawable.a2);
            } else if (i % 5 == 2) {
                list.add(R.drawable.a3);
            } else if (i % 5 == 3) {
                list.add(R.drawable.a4);
            } else if (i % 5 == 4) {
                list.add(R.drawable.a5);
            }
        }
        return list;
    }
}

MyAdapter

package com.ihu11.metrorecylcerview;

import android.support.annotation.NonNull;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import com.ihu11.metro.recycler.MetroRecyclerView;

import java.util.List;

public class MyAdapter extends MetroRecyclerView.MetroAdapter<MyAdapter.ItemViewHolder> {

    private List<Integer> list;

    public MyAdapter(List<Integer> list) {
        this.list = list;
    }

    @Override
    public void onPrepareBindViewHolder(ItemViewHolder holder, int position) {
        holder.dataTxt.setText("p-" + position);
    }

    @Override
    public void onDelayBindViewHolder(ItemViewHolder holder, int position) {
        holder.icon.setBackgroundResource(list.get(position));
        Log.i("Catch", "onDelayBindViewHolder:" + position);
    }

    @Override
    public void onUnBindDelayViewHolder(ItemViewHolder holder) {
        holder.icon.setBackgroundResource(R.drawable.translate);
        Log.i("Catch", "onUnBindDelayViewHolder:" + holder.getAdapterPosition());
    }

    @NonNull
    @Override
    public ItemViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) {
        View convertView = LayoutInflater.from(viewGroup.getContext()).inflate(
                R.layout.item, viewGroup, false);
        return new ItemViewHolder(convertView);
    }

    @Override
    public int getItemCount() {
        if (list == null) {
            return 0;
        }
        return list.size();
    }

    public final static class ItemViewHolder extends MetroRecyclerView.MetroViewHolder {
        TextView dataTxt;
        ImageView icon;

        public ItemViewHolder(View itemView) {
            super(itemView);
            dataTxt = itemView
                    .findViewById(R.id.text);
            icon = itemView.findViewById(R.id.img);
        }
    }
}

布局文件
activity_grid.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ffB0C4DE">

    <com.ihu11.metro.recycler.MetroRecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginLeft="200px"
        android:layout_marginTop="50px"
        app:itemSpaceLeft="10px"
        app:itemSpaceRight="10px"
        app:itemSpaceTop="15px"
        app:itemSpaceBottom="15px"
        app:delayBindEnable="true"
        app:supportVLeftKey="true"
        app:supportVRightKey="true"
        app:focusViewOnFrontEnable="true"/>

    <com.ihu11.metro.flow.FlowView
        android:id="@+id/flow_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:flow_color1="@color/color3"
        app:flow_color2="@color/color2"
        app:flow_stroke_width="2px"
        app:round_radius="5px"
        app:viewType="normal" />

</RelativeLayout>

item.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="200px"
    android:layout_height="250px">//必须指定宽高

    <ImageView
        android:id="@+id/img"
        android:layout_width="200px"
        android:layout_height="200px" />

    <TextView
        android:id="@+id/text"
        android:layout_width="200px"
        android:layout_height="50px"
        android:layout_below="@+id/img"
        android:gravity="center" />

</RelativeLayout>

2.可删除项的功能

先看看效果图


device-2019-10-17-102920.gif

结合上面的代码-加入关键代码

recyclerView.setOnItemClickListener(new MetroItemClickListener() {
            @Override
            public void onItemClick(View parentView, View itemView, int position) {
                recyclerView.deleteItem(position, dataList);
            }
        });

3.垂直的单列类似ListView

效果图


device-2019-10-17-103921.gif

只需要设置LayoutManager的spanCount为 1 方向为垂直的

MetroRecyclerView.MetroGridLayoutManager layoutManager = new MetroRecyclerView.MetroGridLayoutManager(
                this, 1, MetroRecyclerView.VERTICAL);

也可以使用LinearyLayoutManager来实现

LinearLayoutManager layoutManager = new LinearLayoutManager(this, RecyclerView.VERTICAL, false);

4.水平方向的单列表

效果图


device-2019-10-17-104602.gif

同上面类似只需要设置LayoutManager的spanCount为 1 方向为水平的

MetroRecyclerView.MetroGridLayoutManager layoutManager = new MetroRecyclerView.MetroGridLayoutManager(
                this, 1, MetroRecyclerView.HORIZONTAL);

也可以使用LinearyLayoutManager来实现

LinearLayoutManager layoutManager = new LinearLayoutManager(this, RecyclerView.HORIZONTAL, false);

5.实现原理

实现流程图
    // 进行按键转换,用于变化方向的时候直接映射到虚拟按键
    private int convertVirtualKeyCode(int keyCode) {
        if (mOrientation == VERTICAL) {
            switch (keyCode) {
                case KeyEvent.KEYCODE_DPAD_DOWN:
                    return VIRTUAL_KEY_CODE_NEXT_ROW;
                case KeyEvent.KEYCODE_DPAD_UP:
                    return VIRTUAL_KEY_CODE_PRE_ROW;
                case KeyEvent.KEYCODE_DPAD_LEFT:
                    return VIRTUAL_KEY_CODE_PRE_ONE;
                case KeyEvent.KEYCODE_DPAD_RIGHT:
                    return VIRTUAL_KEY_CODE_NEXT_ONE;
            }
        } else {
            switch (keyCode) {
                case KeyEvent.KEYCODE_DPAD_DOWN:
                    return VIRTUAL_KEY_CODE_NEXT_ONE;
                case KeyEvent.KEYCODE_DPAD_UP:
                    return VIRTUAL_KEY_CODE_PRE_ONE;
                case KeyEvent.KEYCODE_DPAD_LEFT:
                    return VIRTUAL_KEY_CODE_PRE_ROW;
                case KeyEvent.KEYCODE_DPAD_RIGHT:
                    return VIRTUAL_KEY_CODE_NEXT_ROW;
            }
        }
        return -1;
    }
这里焦点FlowView使用了不同的实现样式,可参见源码

核心类MetroRecyclerView的实现代码太长了详见github
github库---demo源码-https://github.com/ihu11/MetroRecyclerView

上一篇 下一篇

猜你喜欢

热点阅读