Android 自定义组件之 带有悬浮header的listview

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

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

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

  

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

  关键代码如下:

  

 1   list.setOnScrollListener(new AbsListView.OnScrollListener() {
 2             @Override
 3             public void onScrollStateChanged(AbsListView view, int scrollState) {
 4                 if(AbsListView.OnScrollListener.SCROLL_STATE_IDLE == scrollState){
 5                      play(false,y);
 6                 }
 7                 if(AbsListView.OnScrollListener.SCROLL_STATE_FLING == scrollState){
 8                     play(true,y);
 9                 }
10                 if(AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL == scrollState) {
11                    
12                 }
13             }

  其中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还解决,代码如下。

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

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

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

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

  

 1 private void deal()
 2     {
 3         View c = list.getChildAt(0);
 4        int first  = list.getFirstVisiblePosition();
 5         int top = c.getTop();
 6         int hight = c.getHeight();
 7         int distance =   first*hight - top;
 8         if(distance < hight)
 9         {
10             int i = textview.getLayoutParams().height;
11             list.setPadding(0,i,0,0);
12         }
13 
14     }

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

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

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

  布局:

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     tools:context=".MainActivity">
 6 
 7     <TextView
 8         android:id="@+id/txt"
 9         android:gravity="center"
10         android:background="#000"
11         android:text="Hello World!"
12         android:textColor="#0cbdb7"
13         android:textSize="40sp"
14         android:layout_width="match_parent"
15         android:layout_height="50dp" />
16     <ListView
17         android:id="@+id/listview"
18         android:layout_width="match_parent"
19         android:layout_height="match_parent"/>
20 
21 </FrameLayout>

  代码:

  1 package com.example.administrator.listviewtest;
  2 
  3 import android.app.Activity;
  4 import android.support.v7.app.AppCompatActivity;
  5 import android.os.Bundle;
  6 import android.util.Log;
  7 import android.view.View;
  8 import android.view.ViewGroup;
  9 import android.view.animation.AlphaAnimation;
 10 import android.view.animation.Animation;
 11 import android.widget.AbsListView;
 12 import android.widget.ArrayAdapter;
 13 import android.widget.BaseAdapter;
 14 import android.widget.ListView;
 15 import android.widget.SimpleAdapter;
 16 import android.widget.TextView;
 17 
 18 import java.util.ArrayList;
 19 import java.util.List;
 20 
 21 public class MainActivity extends Activity {
 22     TextView textview;
 23     ListView list;
 24     boolean y = false;
 25     @Override
 26     protected void onCreate(Bundle savedInstanceState) {
 27         super.onCreate(savedInstanceState);
 28         setContentView(R.layout.activity_main);
 29          list = (ListView)findViewById(R.id.listview);
 30          textview = (TextView)findViewById(R.id.txt);
 31         List<String> list1 = new ArrayList<>();
 32         for(int i = 0;i < 100;i++)
 33         {
 34             list1.add("record"+(i+1));
 35         }
 36         ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_expandable_list_item_1,list1);
 37         list.setAdapter(adapter);
 38 
 39         list.setOnScrollListener(new AbsListView.OnScrollListener() {
 40             @Override
 41             public void onScrollStateChanged(AbsListView view, int scrollState) {
 42                 if(AbsListView.OnScrollListener.SCROLL_STATE_IDLE == scrollState){
 43                      play(false,y);
 44                 }
 45                 if(AbsListView.OnScrollListener.SCROLL_STATE_FLING == scrollState){
 46                     play(true,y);
 47                 }
 48                 if(AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL == scrollState) {
 49                    // play(true, y);
 50                 }
 51             }
 52 
 53             @Override
 54             public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
 55                     if(firstVisibleItem == 0)
 56                     {
 57                         Log.i("list","top");
 58                         y = true;
 59                         int i = textview.getLayoutParams().height;
 60                         list.setPadding(0,i,0,0);
 61                     }
 62                 else
 63                     {
 64                         y = false;
 65                     }
 66             }
 67         });
 68     }
 69     private void play(boolean x,boolean y)
 70     {
 71         Animation animation;
 72         if(x){
 73          animation = new AlphaAnimation(1,0);
 74             animation.setDuration(1000);
 75             textview.startAnimation(animation);
 76             textview.setVisibility(View.GONE);
 77             if(!y){
 78             list.setPadding(0,0,0,0);
 79                 deal();
 80             }
 81         }
 82         else{
 83             textview.setVisibility(View.VISIBLE);
 84             animation = new AlphaAnimation(0,1);
 85             animation.setDuration(2000);
 86             textview.startAnimation(animation);
 87             View view = new View(this);
 88         }
 89     }
 90     private void deal()
 91     {
 92         View c = list.getChildAt(0);
 93        int first  = list.getFirstVisiblePosition();
 94         int top = c.getTop();
 95         int hight = c.getHeight();
 96         int distance =   first*hight - top;
 97         if(distance < hight)
 98         {
 99             int i = textview.getLayoutParams().height;
100             list.setPadding(0,i,0,0);
101         }
102 
103     }
104 }

 

posted @ 2015-11-02 09:55  u3  阅读(510)  评论(0编辑  收藏  举报