zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    dig命令不能使用(-bash: dig: command not found)
    linux系统中的一些典型问题汇总
    Django运行项目时候出现DisallowedHost at / Invalid HTTP_HOST header:
    Grafana添加Zabbix为数据源(二)
    Grafana添加Zabbix为数据源(一)
    linux go环境安装
    centos6里面装zabbix(五)
    centos6里面装zabbix(二)
    HTTP状态码分类及异常状态码处理
    超详细 Linux 下编译安装Redis 以及php配套使用
  • 原文地址:https://www.cnblogs.com/u3shadow/p/4929318.html
Copyright © 2011-2022 走看看