Android XListView实现原理讲解及分析

采得百花成蜜后,为谁辛苦为谁甜。这篇文章主要讲述Android XListView实现原理讲解及分析相关的知识,希望能为你提供帮助。
XListview是一个非常受欢迎的下拉刷新控件,但是已经停止维护了。之前写过一篇XListview的使用介绍,用起来非常简单,这两天放假无聊,研究了下XListview的实现原理,学到了很多,今天分享给大家。
    提前声明,为了让代码更好的理解,我对代码进行了部分删减和重构,如果大家想看原版代码,请去github自行下载。
    Xlistview项目主要是三部分:XlistView,XListViewHeader,XListViewFooter,分别是XListView主体、header、footer的实现。下面我们分开来介绍。
    下面是修改之后的XListViewHeader代码
 
[java]  view plaincopy      

  1. public  class  XListViewHeader  extends  LinearLayout  {   
  2.    
  3.         private  static  final  String  HINT_NORMAL  =  "下拉刷新";    
  4.         private  static  final  String  HINT_READY  =  "松开刷新数据";    
  5.         private  static  final  String  HINT_LOADING  =  "正在加载...";    
  6.    
  7.         //  正常状态   
  8.         public  final  static  int  STATE_NORMAL  =  0;    
  9.         //  准备刷新状态,也就是箭头方向发生改变之后的状态   
  10.         public  final  static  int  STATE_READY  =  1;    
  11.         //  刷新状态,箭头变成了progressBar   
  12.         public  final  static  int  STATE_REFRESHING  =  2;    
  13.         //  布局容器,也就是根布局   
  14.         private  LinearLayout  container;    
  15.         //  箭头图片   
  16.         private  ImageView  mArrowImageView;    
  17.         //  刷新状态显示   
  18.         private  ProgressBar  mProgressBar;    
  19.         //  说明文本   
  20.         private  TextView  mHintTextView;    
  21.         //  记录当前的状态   
  22.         private  int  mState;    
  23.         //  用于改变箭头的方向的动画   
  24.         private  Animation  mRotateUpAnim;    
  25.         private  Animation  mRotateDownAnim;    
  26.         //  动画持续时间   
  27.         private  final  int  ROTATE_ANIM_DURATION  =  180;    
  28.    
  29.         public  XListViewHeader(Context  context)  {   
  30.                 super(context);    
  31.                 initView(context);    
  32.         }   
  33.    
  34.         public  XListViewHeader(Context  context,  AttributeSet  attrs)  {   
  35.                 super(context,  attrs);    
  36.                 initView(context);    
  37.         }   
  38.    
  39.         private  void  initView(Context  context)  {   
  40.                 mState  =  STATE_NORMAL;    
  41.                 //  初始情况下,设置下拉刷新view高度为0   
  42.                 LinearLayout.LayoutParams  lp  =  new  LinearLayout.LayoutParams(   
  43.                                 LayoutParams.MATCH_PARENT,  0);    
  44.                 container  =  (LinearLayout)  LayoutInflater.from(context)www.qinlinyule.cn  .inflate(   
  45.                                 R.layout.xlistview_header,  null);    
  46.                 addView(container,  lp);    
  47.                 //  初始化控件   
  48.                 mArrowImageView  =  (ImageView)  findViewById(R.id.xlistview_header_arrow);    
  49.                 mHintTextView  =  (TextView)  findViewById(R.id.xlistview_header_hint_textview);    
  50.                 mProgressBar  =  (ProgressBar)  findViewById(R.id.xlistview_header_progressbar);    
  51.                 //  初始化动画   
  52.                 mRotateUpAnim  =  new  RotateAnimation(0.0f,  -180.0f,   
  53.                                 Animation.RELATIVE_TO_SELF,  0.5f,  Animation.RELATIVE_TO_SELF,   
  54.                                 0.5f);    
  55.                 mRotateUpAnim.setDuration(ROTATE_ANIM_DURATION);    
  56.                 mRotateUpAnim.setFillAfter(true);    
  57.                 mRotateDownAnim  =  new  RotateAnimation(-180.0f,  0.0f,   
  58.                                 Animation.RELATIVE_TO_SELF,  0.5f,  Animation.RELATIVE_TO_SELF,   
  59.                                 0.5f);    
  60.                 mRotateDownAnim.setDuration(ROTATE_www.thd178.com/ ANIM_DURATION);    
  61.                 mRotateDownAnim.setFillAfter(true);    
  62.         }   
  63.    
  64.         //  设置header的状态   
  65.         public  void  setState(int  state)  {   
  66.                 if  (state  ==  mState)   
  67.                         return;    
  68.    
  69.                 //  显示进度   
  70.                 if  (state  ==  STATE_REFRESHING)  www.taohuayuan178.com{   
  71.                         mArrowImageView.clearAnimation(www.feifanyule.cn);    
  72.                         mArrowImageView.setVisibility(View.INVISIBLE);    
  73.                         mProgressBar.setVisibility(www.120xh.cn   View.VISIBLE);    
  74.                 }  else  {   
  75.                         //  显示箭头   
  76.                         mArrowImageView.setVisibility(View.VISIBLE);    
  77.                         mProgressBar.setVisibility(View.www.vboyule66.cn/ INVISIBLE);    
  78.                 }   
  79.    
  80.                 switch  (state)  {   
  81.                 case  STATE_NORMAL:   
  82.                         if  (mState  ==  STATE_READY)  {   
  83.                                 mArrowImageView.startAnimation(mRotateDownAnim);    
  84.                         }   
  85.                         if  (mState  ==  STATE_REFRESHING)  {   
  86.                                 mArrowImageView.clearAnimation();    
  87.                         }   
  88.                         mHintTextView.setText(HINT_NORMAL);    
  89.                         break;    
  90.                 case  STATE_READY:   
  91.                         if  (mState  !=  STATE_READY)  {   
  92.                                 mArrowImageView.clearAnimation();    
  93.                                 mArrowImageView.startAnimation(mRotateUpAnim);    
  94.                                 mHintTextView.setText(HINT_READY);    
  95.                         }   
  96.                         break;    
  97.                 case  STATE_REFRESHING:   
  98.                         mHintTextView.setText(HINT_LOADING);    
  99.                         break;    
  100.                 }   
  101.    
  102.                 mState  =  state;    
  103.         }   
  104.    
  105.         public  void  setVisiableHeight(int  height)  {   
  106.                 if  (height  <   0)   
  107.                         height  =  0;    
  108.                 LinearLayout.LayoutParams  lp  =  (LinearLayout.LayoutParams)  container   
  109.                                 .getLayoutParams();    
  110.                 lp.height  =  height;    
  111.                 container.setLayoutParams(lp);    
  112.         }   
  113.    
  114.         public  int  getVisiableHeight()  {   
  115.                 return  container.getHeight();    
  116.         }   
  117.    
  118.         public  void  show()  {   
  119.                 container.setVisibility(View.VISIBLE);    
  120.         }   
  121.    
  122.         public  void  hide()  {   
  123.                 container.setVisibility(View.INVISIBLE);    
  124.         }   
  125.    
  126. }   

    XListViewHeader继承自linearLayout,用来实现下拉刷新时的界面展示,可以分为三种状态:正常、准备刷新、正在加载。
 
    在Linearlayout布局里面,主要有指示箭头、说明文本、圆形加载条三个控件。在构造函数中,调用了initView()进行控件的初始化操作。在添加布局文件的时候,指定高度为0,这是为了隐藏header,然后初始化动画,是为了完成箭头的旋转动作。
    setState()是设置header的状态,因为header需要根据不同的状态,完成控件隐藏、显示、改变文字等操作,这个方法主要是在XListView里面调用。除此之外,还有setVisiableHeight()和getVisiableHeight(),这两个方法是为了设置和获取Header中根布局文件的高度属性,从而完成拉伸和收缩的效果,而show()和hide()则显然就是完成显示和隐藏的效果。
    下面是Header的布局文件
【Android XListView实现原理讲解及分析】 
[html]  view plaincopy      
    1. < ?xml  version="1.0"  encoding="utf-8"?>    
    2. < LinearLayout  xmlns:android="http://schemas.android.com/apk/res/android"   
    3.         xmlns:tools="http://schemas.android.com/tools"   
    4.         android:layout_width="match_parent"   
    5.         android:layout_height="wrap_content"   
    6.         android:gravity="bottom"  >    
    7.    
    8.         < RelativeLayout   
    9.                 android:id="@+id/xlistview_header_content"   
    10.                 android:layout_width="match_parent"   
    11.                 android:layout_height="60dp"   
    12.                 tools:ignore="UselessParent"  >    
    13.    
    14.                 < TextView   
    15.                         android:id="@+id/xlistview_header_hint_textview"   
    16.                         android:layout_width="100dp"   
    17.                         android:layout_height="wrap_content"   
    18.                         android:layout_centerInParent="true"   
    19.                         android:gravity="center"   
    20.                         android:text="正在加载"   
    21.                         android:textColor="@android:color/black"   
    22.                         android:textSize="14sp"  />    
    23.    
    24.                 < ImageView   
    25.                         android:id="@+id/xlistview_header_arrow"   
    26.                         android:layout_width="30dp"   
    27.                         android:layout_height="wrap_content"   
    28.                         android:layout_centerVertical="true"   
    29.                         android:layout_toLeftOf="@id/xlistview_header_hint_textview"   
    30.                         android:src="https://www.songbingjia.com/android/@drawable/xlistview_arrow"  />    
    31.    
    32.                 < ProgressBar   
    33.                         android:id="@+id/xlistview_header_progressbar"   
    34.                         style="@style/progressbar_style"   
    35.                         android:layout_width="30dp"   
    36.                         android:layout_height="30dp"   
    37.                         android:layout_centerVertical="true"   
    38.                         android:layout_toLeftOf="@id/xlistview_header_hint_textview"   
    39.                         android:visibility="invisible"  />    
    40.         < /RelativeLayout>    
    41.    
    42. < /LinearLayout>    


    推荐阅读