centos 多进程 海思 uitableview wcf dll jestjs Pure CSS sql数据库教学视频 db2从入门到精通 bootstrap模态框传参 java时间戳 数据库学习 python高级 python搭建环境 python的array python中的for循环 javasubstring java实现 java字符串查找 java命令 java连接sql数据库 java读取文本 linux下载安装 程序员面试宝典 fdisk下载 混沌世界隐藏英雄密码 iar下载 mac画图工具 视频编辑专家下载 maven项目打包 流媒体下载 bootskin 苹果电脑数据恢复 淘新闻下载 top命令详解 fabfilter excel乘积 pip安装教程 steam错误代码118怎么解决
当前位置: 首页 > 学习教程  > 编程学习

Android -- 固定在ScrollView顶部的View,类似于新浪微博的评论列表的顶部

2021/1/9 2:07:56 文章标签: 微博取消赞

http://my.oschina.net/Hideeee/blog/500933 摘要 现在很多App都实现了这个功能,例如新浪微博评论页面的评论、转发、赞的数字可以固定在屏幕上方。我个人很喜欢这种设计,所以利用一点空余时间简单实现了一个类似的功能。先来看一下上面这张图的效果。 这…

http://my.oschina.net/Hideeee/blog/500933

摘要
现在很多App都实现了这个功能,例如新浪微博评论页面的评论、转发、赞的数字可以固定在屏幕上方。我个人很喜欢这种设计,所以利用一点空余时间简单实现了一个类似的功能。

先来看一下上面这张图的效果。

这个是新浪微博的一个页面,整体布局大致分了三块:正文内容、转发评论赞的数字条、评论列表

其中数字条是可以跟着ScrollView一起滑动,但在滑到最顶部时固定在最上面,而下面的评论内容可以继续滑动。

这种效果还是挺赞的,但一开始没有什么思路,所以就去搜了下相关技术代码,一下就恍然大悟!原来是自己想复杂了,其实原理很简单!


下面是自己实现的效果图:



实现原理:

    当滚动条划过头部时,把需要固定的头部从父布局中移除,然后添加到最外层布局的顶部。

    当滚动条返回时又把最外层的头部移然后重新添加到原来的父布局里面。

    整个实现代码,不算上布局,也就100行左右


详细实现逻辑:

首先建一个自定义View叫MyHoveringScrollView继承自FrameLayout,在布局里MyHoveringScrollView处于最外层。由于FrameLayout本身是不支持滚动条的,所以在FrameLayout内部有一个自定义的ScrollView。

在初始化的时候,通过getChildAt(0)把子布局拿到,然后清空整个布局,然后实例化一个自己的ScrollView,把之前拿到的子布局添加到ScrollView里面,

最后把ScrollView添加到MyHoveringScrollView里面。

public void init() {
        post(new Runnable() {
            @Override
            public void run() {
                mContentView = (ViewGroup) getChildAt(0);
                removeAllViews();

                MyScrollView scrollView = new MyScrollView(getContext(), MyHoveringScrollView.this);
                scrollView.addView(mContentView);
                addView(scrollView);

            }
        });
    }

可能注意到了两点:

1、我用了post()。因为在构造方法里面布局还没有生成,getChildAt(0)是拿不到东西的,但是post()会把动作放到队列里,等布局完成后再从队列里取出来,所以这里是个小窍门。

2、我把MyHoveringScrollView传入到了ScrollView里面,这么做其实是为了让ScrollView回调MyHoveringScrollView的方法。(比较懒,不想写接口……)


然后通过setTopView()方法,把需要固定在顶部的ID传进来:

public void setTopView(final int id{
        post(new Runnable() {
            @Override
            public void run({
                mTopView = (ViewGroup) mContentView.findViewById(id);

                int height = mTopView.getChildAt(0).getMeasuredHeight();
                ViewGroup.LayoutParams params = mTopView.getLayoutParams();
                params.height = height;
                mTopView.setLayoutParams(params);
                mTopViewTop = mTopView.getTop();
                mTopContent = mTopView.getChildAt(0);

            }
        });
    }

注意为什么要调用mTopView.setLayoutParams(),因为头部的布局高度必须得固定,如果是wrap_content,虽然也不会有什么错误,但效果不太好,可以自己试一下。


接下来,在ScrollView里面重写onScrollChanged()方法,并回调给MyHoveringScrollView的onScroll方法:

private static class MyScrollView extends ScrollView {

        private MyHoveringScrollView mScrollView;

        public MyScrollView(Context context, MyHoveringScrollView scrollView) {
            super(context);
            mScrollView = scrollView;
        }


        @Override
        protected void onScrollChanged(int l, int t, int oldl, int oldt) {
            super.onScrollChanged(l, t, oldl, oldt);
            mScrollView.onScroll(t);
        }

    }
public void onScroll(final int scrollY) {
        post(new Runnable() {
            @Override
            public void run() {
                if (mTopView == null
                        ) return;

                if (scrollY >= mTopViewTop
                        && mTopContent.getParent() == mTopView) {
                    mTopView.removeView(mTopContent);
                    addView(mTopContent);
                } else if (scrollY < mTopViewTop
                        && mTopContent.getParent() == MyHoveringScrollView.this) {
                    removeView(mTopContent);
                    mTopView.addView(mTopContent);
                }

            }
        });
    }

如果scrollY >= mTopViewTop就是头部应该被固定在顶部的时候

如果scrollY < mTopViewTop就是头部应该取消固定,还原到原来父布局的时候

至此,功能就实现了!

    

怎么使用呢?首先先写布局:

<com.hide.myhoveringscroll.app.MyHoveringScrollView
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/view_hover"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    <LinearLayout android:layout_width="match_parent"
                  android:layout_height="match_parent"
                  android:orientation="vertical"
            >
        <TextView android:layout_width="match_parent"
                  android:layout_height="300dp"
                  android:text="这是头部"
                  android:gravity="center"
                />

        <FrameLayout android:layout_width="match_parent" android:layout_height="wrap_content"
                     android:id="@+id/top"
                >
            <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content"
                          android:padding="20dp"
                          android:background="#AAff0000"
                          android:orientation="horizontal">
                <TextView android:layout_width="0dp" android:layout_height="wrap_content"
                          android:layout_weight="1"
                          android:gravity="center"
                          android:layout_gravity="center"
                          android:textSize="16sp"
                          android:text="这是固定部分"
                        />
                <Button android:layout_width="wrap_content" android:layout_height="wrap_content"
                        android:text="点我一下"
                        android:id="@+id/btn"
                        />

            </LinearLayout>
        </FrameLayout>

        <TextView android:layout_width="match_parent" android:layout_height="wrap_content"
                  android:paddingTop="10dp"
                  android:text="内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n内容\n"
                />

    </LinearLayout>
</com.hide.myhoveringscroll.app.MyHoveringScrollView>

其中:MyHoveringScrollView在最外层,充当ScrollView的角色(所以子布局只能有一个)

android:id="@+id/top也就是需要固定在顶部的布局


最后回到Activity:

view_hover = (MyHoveringScrollView) findViewById(R.id.view_hover);
view_hover.setTopView(R.id.top);

两句话就实现了固定头部的效果。


源代码地址:https://github.com/w9xhc/MyHoveringScroll


本文链接: http://www.dtmao.cc/news_show_1100323.shtml

附件下载

相关教程

    暂无相关的数据...

共有条评论 网友评论

验证码: 看不清楚?