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的布局文件

[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="@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>  

猜你喜欢

转载自www.cnblogs.com/qwangxiao/p/9080104.html
今日推荐