Android开发——实现固定在ScrollView顶部的View,类似于新浪微博的评论列表的顶部
- 现在很多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:gravity="center"
android:text="这是头部" /> <FrameLayout
android:id="@+id/top"
android:layout_width="match_parent"
android:layout_height="wrap_content" > <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#AAff0000"
android:orientation="horizontal"
android:padding="20dp" > <TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="1"
android:gravity="center"
android:text="这是固定部分"
android:textSize="16sp" /> <Button
android:id="@+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="点我一下" />
</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内容/nn内容/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);
- 两句话就实现了固定头部的效果。
Android开发——实现固定在ScrollView顶部的View,类似于新浪微博的评论列表的顶部的更多相关文章
- Android开发 - 解决DialogFragment在全屏时View被状态栏遮住的问题
我的上一篇文章:设置DialogFragment全屏显示 可以设置对话框的内容全屏显示,但是存在在某些机型上顶部的View被状态栏遮住的问题.经过测试,发现了一种解决办法,在DialogFragmen ...
- Android开发学习之路--Annotation注解简化view控件之初体验
一般我们在写android Activity的时候总是会在onCreate方法中加上setContentView方法来加载layout,通过findViewById来实现控件的绑定,每次写这么多代码总 ...
- Android 开发笔记 “The constructor AlertDialog.Builder(new View.OnKeyListener(){}) is undefined”
1.The constructor AlertDialog.Builder(new View.OnKeyListener(){}) is undefined等,应该有很多类似问题 比如你的源码文件名是 ...
- 50、转自知乎上android开发相见恨晚的接口
原文链接:http://www.zhihu.com/question/33636939 程序员软件开发Android 开发JavaAndroid修改 Android开发中,有哪些让你觉得相 ...
- Android开发学习之路-关于Exception
Exception在Java中是表示异常的一个类.它是Throwable的子类. 而Exception的子类RuntimeException是一个特殊的异常类,在代码中不需要对此类进行throw,而是 ...
- Android 开发日常积累
Android 集合 Android 开源项目分类汇总 扔物线的 HenCoder 高级 Android 教程 hencoder HenCoder:给高级 Android 工程师的进阶手册 Andro ...
- Android应用开发-小巫CSDN博客client之获取评论列表
Android应用开发-小巫CSDN博客客户端之获取评论列表 上一篇博客介绍了博文具体内容的业务逻辑实现,本篇博客介绍小巫CSDN博客客户端的最后一项功能.获取评论列表,这个功能的实现跟前面获取文章列 ...
- Android开发:ScrollView嵌套GridView的解决办法
Android开发:ScrollView嵌套GridView的解决办法 前些日子在开发中用到了需要ScrollView嵌套GridView的情况,由于这两款控件都自带滚动条,当他们碰到一起的时候便 ...
- Android开发工程师文集-Fragment,适配器,轮播图,ScrollView,Gallery 图片浏览器,Android常用布局样式
Android开发工程师文集-Fragment,适配器,轮播图,ScrollView,Gallery 图片浏览器,Android常用布局样式 Fragment FragmentManager frag ...
随机推荐
- ML 徒手系列 拉格朗日乘子法
拉格朗日乘子法是解决极值问题的方法. 本方法是计算多元函数在约束条件下的极值问题的方法. 1.多元函数与约束问题 如下图所示,f(x,y)为多元函数,g(x,y)=c为约束条件.目的是计算在约束条件下 ...
- Uvalive 4865 Data Recovery 最大流
题意就是 给一个50 * 50的矩阵 然后给出每行每列元素的和 和一个初始矩阵 矩阵中有些是未知,有些是已知 然后我们求目标矩阵就是把能确定的元素的值求出来,实在不能确定的就置为-1 所有矩阵元素的值 ...
- 关于IE开发人员工具(F12)找不到的问题
关于IE开发人员工具(F12)找不到的问题 解决方案:第一步,像往常一样F12或者,工具->开发人员工具,点击后,这个时候你是看不到工具界面(当然,如果你正好遇到了找不到这个问题);第二步,这个 ...
- AFNetworking上传文件
-(void)upload{ AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; NSD ...
- JVM的内存管理机制
在做Java开发的时候常用的JVM内存管理有两种,一种是堆内存,一种是栈内存.堆内存主要用来存储程序在运行时创建或实例化的对象与变量,例如:我们通过new MyClass()创建的类MyClass的对 ...
- jquery ajax 序列化表单传参提交实体对象到后台action
========action后台我这里使用的是SpringMVC如果用ssh用法一致=============== @Controller@RequestMapping("PubjobCon ...
- Java数据结构之树和二叉树
从这里开始将要进行Java数据结构的相关讲解,Are you ready?Let's go~~ Java中的数据结构模型可以分为一下几部分: 1.线性结构 2.树形结构 3.图形或者网状结构 接下来的 ...
- Linux 卸载Oracle 11G
卸载oracle11G数据 1.使用SQL*PLUS停止数据库[oracle@OracleTest oracle]$ sqlplus /nologSQL> connect / as sysdba ...
- GridView实现多表头合并[转]
1.这里先介绍单纯的GridView多表头合并,先上图: 可以看到,上图就是生成的多表头,具体的后台代码是在Row_Created事件中创建的.先看创建代码: protected void GridV ...
- jQuery Mobile 手动显示ajax加载器,提示加载中...
在使用jQuery Mobile开发时,有时候我们需要在请求ajax期间,显示加载提示框(例如:一个旋转图片+一个提示:加载中...).这个时候,我们可以手动显示jQuery Mobile的加载器,大 ...