最近做项目遇到一个需求,要做一个带有悬浮header的listview,即,当listview滑动时,header消失,静止时header浮现。

  这个需求看似简单,实际做起来还是会遇到不少的困难,特此记录过程,以做记录。

  首先,我们来看看需求,如下图。

  

  有了需求,我们就可以开始做具体分析了,首先我们想到的是给listview添加一个滑动监听,在滑动时隐藏header在静止的时候就显示header。

  关键代码如下:

  

   list.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if(AbsListView.OnScrollListener.SCROLL_STATE_IDLE == scrollState){
play(false,y);
}
if(AbsListView.OnScrollListener.SCROLL_STATE_FLING == scrollState){
play(true,y);
}
if(AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL == scrollState) { }
}

  其中play()就是我们的隐藏/显示 header的方法啦

  写好了监听之后我们开始写隐藏/显示的PLAY()方法

  首先我们来写一个简单的版本

 private void play(boolean x,boolean y)
{
Animation animation;
if(x){
animation = new AlphaAnimation(1,0);
animation.setDuration(1000);
textview.startAnimation(animation);
textview.setVisibility(View.GONE);
/* if(!y){
list.setPadding(0,0,0,0);
deal();
}*/
}
else{
textview.setVisibility(View.VISIBLE);
animation = new AlphaAnimation(0,1);
animation.setDuration(2000);
textview.startAnimation(animation);
View view = new View(this);
}
}

  可以看到我们通过第一个布尔参数来判断是隐藏还是显示。

  做到这里看似已经完成了,但是有更多的细节是需要打磨的,由于我们采用的FrameLayout进行布局,当我们在顶部的时候会发现第一条记录被挡住了,这可不行。

  不过我们可以通过设置listview的padding还解决,代码如下。

   int i = textview.getLayoutParams().height;
list.setPadding(0,i,0,0);

  现在运行我们的程序,好像已经完成了,但是这个时候可恶的BUG又出来捣乱了。

  当我们只有少量记录(比屏幕显示多一条)的时候,会出现padding设置了之后无法还原的情况,这是因为虽然第一条记录被隐藏了一部分,但是并不是完全隐藏,所以不会触发listview的top事件。

  这时候我们就需要在每次滑动的时候去检测滑动的距离,来判断是不是需要设置padding了,如果第一条记录都没有被隐藏,那么显然我们是不需要设置padding的。

  

 private void deal()
{
View c = list.getChildAt(0);
int first = list.getFirstVisiblePosition();
int top = c.getTop();
int hight = c.getHeight();
int distance = first*hight - top;
if(distance < hight)
{
int i = textview.getLayoutParams().height;
list.setPadding(0,i,0,0);
} }

  这就是判断滑动距离的函数啦。

  至此,一个简单的悬浮header listview已经完成了。

  接下来是完整的布局和代码

  布局:

 <?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"> <TextView
android:id="@+id/txt"
android:gravity="center"
android:background="#000"
android:text="Hello World!"
android:textColor="#0cbdb7"
android:textSize="40sp"
android:layout_width="match_parent"
android:layout_height="50dp" />
<ListView
android:id="@+id/listview"
android:layout_width="match_parent"
android:layout_height="match_parent"/> </FrameLayout>

  代码:

 package com.example.administrator.listviewtest;

 import android.app.Activity;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.widget.AbsListView;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView; import java.util.ArrayList;
import java.util.List; public class MainActivity extends Activity {
TextView textview;
ListView list;
boolean y = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
list = (ListView)findViewById(R.id.listview);
textview = (TextView)findViewById(R.id.txt);
List<String> list1 = new ArrayList<>();
for(int i = 0;i < 100;i++)
{
list1.add("record"+(i+1));
}
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_expandable_list_item_1,list1);
list.setAdapter(adapter); list.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if(AbsListView.OnScrollListener.SCROLL_STATE_IDLE == scrollState){
play(false,y);
}
if(AbsListView.OnScrollListener.SCROLL_STATE_FLING == scrollState){
play(true,y);
}
if(AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL == scrollState) {
// play(true, y);
}
} @Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if(firstVisibleItem == 0)
{
Log.i("list","top");
y = true;
int i = textview.getLayoutParams().height;
list.setPadding(0,i,0,0);
}
else
{
y = false;
}
}
});
}
private void play(boolean x,boolean y)
{
Animation animation;
if(x){
animation = new AlphaAnimation(1,0);
animation.setDuration(1000);
textview.startAnimation(animation);
textview.setVisibility(View.GONE);
if(!y){
list.setPadding(0,0,0,0);
deal();
}
}
else{
textview.setVisibility(View.VISIBLE);
animation = new AlphaAnimation(0,1);
animation.setDuration(2000);
textview.startAnimation(animation);
View view = new View(this);
}
}
private void deal()
{
View c = list.getChildAt(0);
int first = list.getFirstVisiblePosition();
int top = c.getTop();
int hight = c.getHeight();
int distance = first*hight - top;
if(distance < hight)
{
int i = textview.getLayoutParams().height;
list.setPadding(0,i,0,0);
} }
}

Android 自定义组件之 带有悬浮header的listview的更多相关文章

  1. Android自定义组件系列【7】——进阶实践(4)

    上一篇<Android自定义组件系列[6]--进阶实践(3)>中补充了关于Android中事件分发的过程知识,这一篇我们接着来分析任老师的<可下拉的PinnedHeaderExpan ...

  2. Android自定义组件之自动换行及宽度自适应View:WordWrapView

    目的: 自定义一个ViewGroup,里面的子view都是TextView,每个子view  TextView的宽度随内容自适应且每行的子View的个数自适应,并可以自动换行 一:效果图 二:代码 整 ...

  3. Android自定义组件系列【6】——进阶实践(3)

    上一篇<Android自定义组件系列[5]--进阶实践(2)>继续对任老师的<可下拉的PinnedHeaderExpandableListView的实现>进行了分析,这一篇计划 ...

  4. Android自定义组件系列【5】——进阶实践(2)

    上一篇<Android自定义组件系列[5]--进阶实践(1)>中对任老师的<可下拉的PinnedHeaderExpandableListView的实现>前一部分进行了实现,这一 ...

  5. Android自定义组件系列【4】——自定义ViewGroup实现双侧滑动

    在上一篇文章<Android自定义组件系列[3]--自定义ViewGroup实现侧滑>中实现了仿Facebook和人人网的侧滑效果,这一篇我们将接着上一篇来实现双面滑动的效果. 1.布局示 ...

  6. Android自定义组件

    [参考的原文地址] http://blog.csdn.net/l1028386804/article/details/47101387效果图: 实现方式: 一:自定义一个含有EditText和Butt ...

  7. Android 自定义组件之如何实现自定义组件

    参考链接:http://blog.csdn.net/jjwwmlp456/article/details/41076699 简介 Android提供了用于构建UI的强大的组件模型.两个基类:View和 ...

  8. Android自定义组件系列【3】——自定义ViewGroup实现侧滑

    有关自定义ViewGroup的文章已经很多了,我为什么写这篇文章,对于初学者或者对自定义组件比较生疏的朋友虽然可以拿来主义的用了,但是要一步一步的实现和了解其中的过程和原理才能真真脱离别人的代码,举一 ...

  9. Android 自定义组件,自定义LinearLayout,ListView等样式的组件

    今天讲的其实以前自己用过,就是在网上拿下来的把图片裁剪成圆形的方法,之前的随笔也介绍过的, 用法就是,在布局里写控件或者组件的时候得把从com开始到你写的那个类的所有路径写下来. 至于我们该怎么创建呢 ...

随机推荐

  1. spring 自动扫描组件

    在Spring2.5中,有4种类型的组件自动扫描注释类型 @Component – 指示自动扫描组件. @Repository – 表示在持久层DAO组件. @Service – 表示在业务层服务组件 ...

  2. bzoj1025(SCOI2009)游戏——唯一分解的思路与应用

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1025 可以认为对应的值之间连边,就连成了一个有一个或几个环的图.列数就是每个环里点数的lcm ...

  3. nginx+php测试时显示 502 bad gateway的解决方法

    http://www.apelearn.com/study_v2/chapter18.html 由于阿铭老师的PHP版本是 5.3的   我装了 5.5 测试出现了 502  错误 查看日志   借助 ...

  4. 修改配置文件matplotlibrc,让Matplotlib显示中文

    matplotlib默认不支持中文显示,网上的解决办法有好多种,但是大多数都是通过在代码中指定字体,虽然也能实现,但是多出那么几行代码让人觉得很恶心. 本文介绍一种通过修改配置文件matplotlib ...

  5. redis+php实现微博功能(一)

    (一).微博功能概况 微博用户账号注册 微博用户登录 微博发布 添加微博好友(粉丝) 微博推送 微博冷数据写入mysql数据库 (二).redis数据结构设计 这节分享微博用户注册与登录:我们完全采用 ...

  6. MFC程序如何修改icon图标

    场景: Visual Studio写MFC应用程序,默认的程序左上角图标是自带的(如下图),虽说也不丑,但是对于程序员来说,还是缺乏个性了. 你知道,C.C++.java系程序员最常干的事情就是定义. ...

  7. REST API权限集成设计

    REST API权限集成设计 应用分为两大部分,前端html+后端Rest服务,前端html和后端Rest服务部署完全分离. 目标:可访问资源都处于权限控制之下(意味着通过浏览器地址栏的任意url都会 ...

  8. nginx和php-fpm通信的两种方式 unix socket和TCP

    nginx和fastcgi的通信方式有两种,一种是TCP 一种是unix socket TCP使用的是 127.0.0.1:9000端口,将fastcgi_pass参数修改为127.0.0.1:900 ...

  9. 获取响应数据___JSON Extractor 后置处理器

    对于大部分请求返回的结果,都是json,有一个更方便使用的插件:JSON Extractor 不过得首先下载插件 https://jmeter-plugins.org/wiki/JSONPathExt ...

  10. java代码----------实现创建DataInputStream和DataOutputStream进行读写

    总结: 主要是 捕获异常 package com.a.b; import java.io.*; public class testData { public static void main(Stri ...