草庐IT

android - 具有固定列和标题的 RecyclerView,以及可滚动的页脚

coder 2023-11-29 原文

我正在尝试找到一种方法来为体育应用程序(例如 NBA 比赛时间排名)实现站立表​​,该表具有固定的标题、固定的第一列和页脚。我搜索了一下如何获得它,但最好的镜头是这个项目(https://github.com/InQBarna/TableFixHeaders)但它使用自己的 View 而不是 GridView 的 Recycler。有谁知道这样的事情或知道我如何开始使用它(适配器或布局管理器)?

编辑(添加图片)

最佳答案

经过大量测试和搜索,我自己实现了,将 ListView 与内部 Horizo​​ntalScrollView 组合在一起。

首先,我扩展了 Horizo​​ntalScrollView 来向我报告滚动事件,添加了一个监听器:

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,如果这是你的需要)。

<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(固定列)和一个 Horizo​​ntalScrollView。标题和行的布局如下:

<?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's 一个)的帮助下触发水平滚动事件并将所有滚动条作为一个移动。我的事件对象包含来自监听器类的相同数据(也许我可以使用监听器对象本身?)

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;
    }
}

列表适配器类接收一个监听器以在每个项目的 Horizo​​ntalScrollView 中设置。

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;
    }
}

在继续之前,我将MyHorizo​​ntalScrollView注册到EventBus,在每个版本的构造函数中添加了EventBus.getDefault().register(this),并为其添加了receiver方法:

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

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

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

@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));
}

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

太棒了,这就是你想要的结果!

关于android - 具有固定列和标题的 RecyclerView,以及可滚动的页脚,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29395847/

有关android - 具有固定列和标题的 RecyclerView,以及可滚动的页脚的更多相关文章

  1. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

    我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

  2. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

    我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

  3. ruby-on-rails - 使用 Rmagick 或 ImageMagick 在背景上放置标题 - 2

    我有一张背景图片,我想在其中添加一个文本框。我想弄清楚如何将标题放置在其顶部的正确位置。(我使用标题是因为我需要自动换行功能)。现在,我只能让文本显示在左上角,但我需要能够手动定位它的开始位置。require'RMagick'require'Pry'includeMagicktext="Loremipsumdolorsitamet"img=ImageList.new('template001.jpg')img 最佳答案 这是使用convert的ImageMagick命令行的答案。如果你想在Rmagick中使用这个方法,你必须自己移植

  4. ruby-on-rails - Rails 3.1 中具有相同形式的多个模型? - 2

    我正在使用Rails3.1并在一个论坛上工作。我有一个名为Topic的模型,每个模型都有许多Post。当用户创建新主题时,他们也应该创建第一个Post。但是,我不确定如何以相同的形式执行此操作。这是我的代码:classTopic:destroyaccepts_nested_attributes_for:postsvalidates_presence_of:titleendclassPost...但这似乎不起作用。有什么想法吗?谢谢! 最佳答案 @Pablo的回答似乎有你需要的一切。但更具体地说...首先改变你View中的这一行对此#

  5. 【鸿蒙应用开发系列】- 获取系统设备信息以及版本API兼容调用方式 - 2

    在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList​()Obt

  6. 阿里云国际版免费试用:如何注册以及注意事项 - 2

    作为新的阿里云用户,您可以50免费试用多种优惠,价值高达1,700美元(或8,500美元)。这将让您了解和体验阿里云平台上提供的一系列产品和服务。如果您以个人身份注册免费试用,您将获得价值1,700美元的优惠。但是,如果您是注册公司,您可以选择企业免费试用,提交基本信息通过企业实名注册验证,即可开始价值$8,500的免费试用!本教程介绍了如何设置您的帐户并使用您的免费试用版。​关于免费试用在我们开始此试用之前,您还必须遵守以下条款和条件才能访问您的免费试用:只有在一年内创建的账户才有资格获得阿里云免费试用。通过此免费试用优惠,用户可以免费试用免费试用活动页面上列出的每种产品一次。如果您有多个帐

  7. 安卓apk修改(Android反编译apk) - 2

    最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路

  8. ruby - 在 Ruby 中将整数格式化为固定长度的字符串 - 2

    有没有一种简单的方法可以将给定的整数格式化为具有固定长度和前导零的字符串?#convertnumberstostringsoffixedlength3[1,12,123,1234].map{|e|???}=>["001","012","123","234"]我找到了解决方案,但也许还有更聪明的方法。format('%03d',e)[-3..-1] 最佳答案 如何使用%1000而不是进行字符串操作来获取最后三位数字?[1,12,123,1234].map{|e|format('%03d',e%1000)}更新:根据theTinMan的

  9. ruby - 具有两个参数的 block - 2

    我从用户Hirolau那里找到了这段代码:defsum_to_n?(a,n)a.combination(2).find{|x,y|x+y==n}enda=[1,2,3,4,5]sum_to_n?(a,9)#=>[4,5]sum_to_n?(a,11)#=>nil我如何知道何时可以将两个参数发送到预定义方法(如find)?我不清楚,因为有时它不起作用。这是重新定义的东西吗? 最佳答案 如果您查看Enumerable#find的文档,您会发现它只接受一个block参数。您可以将它发送两次的原因是因为Ruby可以方便地让您根据它的“并行赋

  10. ruby-on-rails - 在 RSpec 中,如何以任意顺序期望具有不同参数的多条消息? - 2

    RSpec似乎按顺序匹配方法接收的消息。我不确定如何使以下代码工作:allow(a).toreceive(:f)expect(a).toreceive(:f).with(2)a.f(1)a.f(2)a.f(3)我问的原因是a.f的一些调用是由我的代码的上层控制的,所以我不能对这些方法调用添加期望。 最佳答案 RSpecspy是测试这种情况的一种方式。要监视一个方法,用allowstub,除了方法名称之外没有任何约束,调用该方法,然后expect确切的方法调用。例如:allow(a).toreceive(:f)a.f(2)a.f(1)

随机推荐