具有固定列和标题的RecyclerView,以及可滚动的页脚 [英] RecyclerView with fixed column and header, plus scrollable footer

查看:89
本文介绍了具有固定列和标题的RecyclerView,以及可滚动的页脚的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试找到一种方法来为体育应用实现站立表​​(例如NBA Game Time排名),并具有固定的页眉,固定的第一列和页脚.我搜索了一些方法,但是最好的选择是这个项目( https://github.com/InQBarna/TableFixHeaders ),但它使用自己的视图而不是GridView的Recycler.有人知道这样的事还是知道我该如何开始(适配器或布局管理器)?

I am trying to find a way to implement a standing table for a sports app (like NBA Game Time standings), with a fixed header, fixed first column and a footer. I searched a bit on how to get it, but the best shot was this project (https://github.com/InQBarna/TableFixHeaders) but it uses its own view instead of Recycler of GridView. Do anyone knows something like this or knows how I can start with it (Adapter or LayoutManager)?

编辑(添加图像)

推荐答案

经过大量测试和搜索,我自己实现了此任务,将ListView与内部HorizontalScrollView s组合在一起.

After testing and searching a lot, I implemented by my own, combining a ListView with inner HorizontalScrollViews.

首先,我扩展了HorizontalScrollView以向我报告滚动事件,并添加了一个侦听器:

First, I extended HorizontalScrollView to report me the scroll event, adding a listener:

public class MyHorizontalScrollView extends HorizontalScrollView {

    private OnScrollListener listener;

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
        if (listener != null) listener.onScroll(this, l, t);
    }

    public void setOnScrollListener(OnScrollListener listener) {
        this.listener = listener;
    }

    public interface OnScrollListener {
        void onScroll(HorizontalScrollView view, int x, int y);
    }       
}

然后,我用LinearLayout创建了布局,其中包含我的标头和Activity(如果需要,可以为Fragment)的ListView.

Then, I created my layout with a LinearLayout, containing my header and a ListView for my Activity (or Fragment, if it's your need).

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <include
        android:id="@+id/header"
        layout="@layout/header" />

    <ListView
        android:id="@+id/list"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

列表中的每个项目都是LinearLayout,其中包含TextView(固定列)和HorizontalScrollView.标题和行的布局如下:

Each item of my list is a LinearLayout, with a TextView (the fixed column) and a HorizontalScrollView. The layout of both header and lines are the following:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

    <TextView
        style="?android:attr/textAppearanceMedium"
        android:background="#f00"
        android:minWidth="40dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <View
        android:layout_width="1px"
        android:layout_height="match_parent"
        android:background="@android:color/black" />

    <net.rafaeltoledo.example.MyHorizontalScrollView
        android:id="@+id/scroll"
        android:scrollbars="none"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:orientation="horizontal">

            <!-- Childs, or columns -->

        </LinearLayout>

    </net.rafaeltoledo.example.MyHorizontalScrollView>

</LinearLayout>

诀窍是在EventBus的帮助下滚动全部内容(我使用了 GreenRobot的)滚动水平滚动事件,并将所有滚动条移动为一个.我的事件对象包含来自侦听器类的相同数据(也许我可以使用侦听器对象本身?)

The trick is to scroll all With a help of a EventBus (I used the GreenRobot's one) to fire the horizontal scroll event and move all scrollers as one. My event object contains the same data from the listener class (maybe I can use the listener object itself?)

public static class Event {

    private final int x;
    private final int y;
    private final HorizontalScrollView view;

    public Event(HorizontalScrollView view, int x, int y) {
        this.x = x;
        this.y = y;
        this.view = view;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    public HorizontalScrollView getView() {
        return view;
    }
}

列表适配器类接收一个侦听器,用于在每个项目的HorizontalScrollView中进行设置.

The list adapter class receives a listener to set in the HorizontalScrollView of each item.

public static class Adapter extends BaseAdapter {

    private final Context context;
    private MyHorizontalScrollView.OnScrollListener listener;

    public Adapter(Context context, MyHorizontalScrollView.OnScrollListener listener) {
        this.context = context;
        this.listener = listener;
    }

    @Override
    public int getCount() {
        return 30;
    }

    @Override
    public Object getItem(int position) {
        return new Object();
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            convertView = LayoutInflater.from(getContext()).inflate(R.layout.header, parent, false);
            MyHorizontalScrollView scroll = (MyHorizontalScrollView) convertView.findViewById(R.id.scroll);
            scroll.setOnScrollListener(listener);
        }
        return convertView;
    }

    public Context getContext() {
        return context;
    }
}

在继续之前,我在EventBus中注册了MyHorizontalScrollView,在每个版本的构造函数中添加了EventBus.getDefault().register(this),并向其添加了接收器方法:

Before continue, I registered MyHorizontalScrollView to EventBus, adding EventBus.getDefault().register(this) to each version of constructor, and added the receiver method to it:

public void onEventMainThread(MainActivity.Event event) {
    if (!event.getView().equals(this)) scrollTo(event.getX(), event.getY());
}

,如果不是触发滚动事件的本身,它将滚动到接收的位置.

that will scroll to the received position, if was not itself that fired the scroll event.

最后,我在ActivityonCreate()方法中设置了所有内容:

And finally, I setted up everything in the onCreate() method of my Activity:

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

    MyHorizontalScrollView.OnScrollListener listener = new MyHorizontalScrollView.OnScrollListener() {
        @Override
        public void onScroll(HorizontalScrollView view, int x, int y) {
            Log.d("Scroll Event", String.format("Fired! %d %d", x, y));
            EventBus.getDefault().post(new Event(view, x, y));
        }
    };

    ListView listView = (ListView) findViewById(R.id.list);

    ViewGroup header = (ViewGroup) findViewById(R.id.header);
    header.getChildAt(0).setBackgroundColor(Color.WHITE);
    header.setBackgroundColor(Color.BLUE);
    ((MyHorizontalScrollView) header.findViewById(R.id.scroll)).setOnScrollListener(listener);

    listView.setAdapter(new Adapter(this, listener));
    listView.addFooterView(getLayoutInflater().inflate(R.layout.footer, listView, false));
}

((请忽略一些奇怪的颜色,这是为了更好地查看正在发生的事情).

(Please ignore some weird coloring, it's for better viewing what's happening).

还有ta-daa,这是理想的结果!

And ta-daa, here is the desired result!

这篇关于具有固定列和标题的RecyclerView,以及可滚动的页脚的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆