• [强悍]listview下拉刷新,上拉加载更多组件版


    感谢作者,原项目地址:https://github.com/wedcel/PullToRefresh_MoreLoad_PerfectVersion

    当然,也弄到了网盘分享,下载更便捷:链接: http://pan.baidu.com/s/1sjv5T05 密码: j34s

    首先先贴上组件CustomListView的源码:

      1 package com.maomao.beautymovie.widget;
      2 
      3 import java.text.SimpleDateFormat;
      4 import java.util.Date;
      5 import java.util.Locale;
      6 
      7 import com.maomao.beautymovie.R;
      8 
      9 import android.content.Context;
     10 import android.util.AttributeSet;
     11 import android.util.Log;
     12 import android.view.LayoutInflater;
     13 import android.view.MotionEvent;
     14 import android.view.View;
     15 import android.view.ViewGroup;
     16 import android.view.animation.Interpolator;
     17 import android.view.animation.LinearInterpolator;
     18 import android.view.animation.RotateAnimation;
     19 import android.widget.AbsListView;
     20 import android.widget.AbsListView.OnScrollListener;
     21 import android.widget.BaseAdapter;
     22 import android.widget.ImageView;
     23 import android.widget.LinearLayout;
     24 import android.widget.ListView;
     25 import android.widget.ProgressBar;
     26 import android.widget.TextView;
     27 
     28 /**
     29  * ListView下拉刷新和加载更多<p>
     30  * 
     31  * <strong>变更说明:</strong>
     32  * <p>默认如果设置了OnRefreshListener接口和OnLoadMoreListener接口,<br>并且不为null,则打开这两个功能了。
     33  * <p>剩余两个Flag:mIsAutoLoadMore(是否自动加载更多)和
     34  * <br>mIsMoveToFirstItemAfterRefresh(下拉刷新后是否显示第一条Item)
     35  * 
     36  * <p><strong>有改进意见,请发送到俺的邮箱哈~ 多谢各位小伙伴了!^_^</strong>
     37  * 
     38  * @date 2013-11-11 下午10:09:26
     39  * @change JohnWatson 
     40  * @mail xxzhaofeng5412@gmail.com
     41  * @version 1.0
     42  */
     43 public class CustomListView extends ListView implements OnScrollListener {
     44 
     45     /**  显示格式化日期模板   */
     46     private final static String DATE_FORMAT_STR = "yyyy年MM月dd日 HH:mm";
     47     
     48     /**  实际的padding的距离与界面上偏移距离的比例   */
     49     private final static int RATIO = 3;
     50     
     51     private final static int RELEASE_TO_REFRESH = 0;
     52     private final static int PULL_TO_REFRESH = 1;
     53     private final static int REFRESHING = 2;
     54     private final static int DONE = 3;
     55     private final static int LOADING = 4;
     56     
     57     /**  加载中   */
     58     private final static int ENDINT_LOADING = 1;
     59     /**  手动完成刷新   */
     60     private final static int ENDINT_MANUAL_LOAD_DONE = 2;
     61     /**  自动完成刷新   */
     62     private final static int ENDINT_AUTO_LOAD_DONE = 3;
     63     
     64     /**    0:RELEASE_TO_REFRESH;
     65      * <p> 1:PULL_To_REFRESH;
     66      * <p> 2:REFRESHING;
     67      * <p> 3:DONE;
     68      * <p> 4:LOADING */
     69     private int mHeadState;
     70     /**    0:完成/等待刷新 ;
     71      * <p> 1:加载中  */
     72     private int mEndState;
     73     
     74     // ================================= 功能设置Flag ================================
     75     
     76     /**  可以加载更多?   */
     77     private boolean mCanLoadMore = false;
     78     /**  可以下拉刷新?   */
     79     private boolean mCanRefresh = false;
     80     /**  可以自动加载更多吗?(注意,先判断是否有加载更多,如果没有,这个flag也没有意义)   */
     81     private boolean mIsAutoLoadMore = true;
     82     /** 下拉刷新后是否显示第一条Item    */
     83     private boolean mIsMoveToFirstItemAfterRefresh = false;
     84     
     85     public boolean isCanLoadMore() {
     86         return mCanLoadMore;
     87     }
     88     
     89     public void setCanLoadMore(boolean pCanLoadMore) {
     90         mCanLoadMore = pCanLoadMore;
     91         if(mCanLoadMore && getFooterViewsCount() == 0){
     92             addFooterView();
     93         }
     94     }
     95     
     96     public boolean isCanRefresh() {
     97         return mCanRefresh;
     98     }
     99     
    100     public void setCanRefresh(boolean pCanRefresh) {
    101         mCanRefresh = pCanRefresh;
    102     }
    103     
    104     public boolean isAutoLoadMore() {
    105         return mIsAutoLoadMore;
    106     }
    107 
    108     public void setAutoLoadMore(boolean pIsAutoLoadMore) {
    109         mIsAutoLoadMore = pIsAutoLoadMore;
    110     }
    111         
    112     public boolean isMoveToFirstItemAfterRefresh() {
    113         return mIsMoveToFirstItemAfterRefresh;
    114     }
    115 
    116     public void setMoveToFirstItemAfterRefresh(
    117             boolean pIsMoveToFirstItemAfterRefresh) {
    118         mIsMoveToFirstItemAfterRefresh = pIsMoveToFirstItemAfterRefresh;
    119     }
    120     
    121     // ============================================================================
    122 
    123     private LayoutInflater mInflater;
    124 
    125     private LinearLayout mHeadView;
    126     private TextView mTipsTextView;
    127     private TextView mLastUpdatedTextView;
    128     private ImageView mArrowImageView;
    129     private ProgressBar mProgressBar;
    130     
    131     private View mEndRootView;
    132     private ProgressBar mEndLoadProgressBar;
    133     private TextView mEndLoadTipsTextView;
    134 
    135     /**  headView动画   */
    136     private RotateAnimation mArrowAnim;
    137     /**  headView反转动画   */
    138     private RotateAnimation mArrowReverseAnim;
    139  
    140     /** 用于保证startY的值在一个完整的touch事件中只被记录一次    */
    141     private boolean mIsRecored;
    142 
    143     private int mHeadViewWidth;
    144     private int mHeadViewHeight;
    145 
    146     private int mStartY;
    147     private boolean mIsBack;
    148     
    149     private int mFirstItemIndex;
    150     private int mLastItemIndex;
    151     private int mCount;
    152     private boolean mEnoughCount;//足够数量充满屏幕? 
    153     
    154     private OnRefreshListener mRefreshListener;
    155     private OnLoadMoreListener mLoadMoreListener;
    156 
    157     public CustomListView(Context pContext, AttributeSet pAttrs) {
    158         super(pContext, pAttrs);
    159         init(pContext);
    160     }
    161 
    162     public CustomListView(Context pContext) {
    163         super(pContext);
    164         init(pContext);
    165     }
    166 
    167     public CustomListView(Context pContext, AttributeSet pAttrs, int pDefStyle) {
    168         super(pContext, pAttrs, pDefStyle);
    169         init(pContext);
    170     }
    171 
    172     /**
    173      * 初始化操作
    174      * @param pContext 
    175      * @date 2013-11-20 下午4:10:46
    176      * @change JohnWatson
    177      * @version 1.0
    178      */
    179     private void init(Context pContext) {
    180         setCacheColorHint(pContext.getResources().getColor(R.color.transparent));
    181         mInflater = LayoutInflater.from(pContext);
    182 
    183         addHeadView();
    184         
    185         setOnScrollListener(this);
    186 
    187         initPullImageAnimation(0);
    188     }
    189 
    190     /**
    191      * 添加下拉刷新的HeadView 
    192      * @date 2013-11-11 下午9:48:26
    193      * @change JohnWatson
    194      * @version 1.0
    195      */
    196     private void addHeadView() {
    197         mHeadView = (LinearLayout) mInflater.inflate(R.layout.listview_header, null);
    198 
    199         mArrowImageView = (ImageView) mHeadView
    200                 .findViewById(R.id.head_arrowImageView);
    201         mArrowImageView.setMinimumWidth(70);
    202         mArrowImageView.setMinimumHeight(50);
    203         mProgressBar = (ProgressBar) mHeadView
    204                 .findViewById(R.id.head_progressBar);
    205         mTipsTextView = (TextView) mHeadView.findViewById(
    206                 R.id.head_tipsTextView);
    207         mLastUpdatedTextView = (TextView) mHeadView
    208                 .findViewById(R.id.head_lastUpdatedTextView);
    209 
    210         measureView(mHeadView);
    211         mHeadViewHeight = mHeadView.getMeasuredHeight();
    212         mHeadViewWidth = mHeadView.getMeasuredWidth();
    213         
    214         mHeadView.setPadding(0, -1 * mHeadViewHeight, 0, 0);
    215         mHeadView.invalidate();
    216 
    217         Log.v("size", "" + mHeadViewWidth + " height:"
    218                 + mHeadViewHeight);
    219 
    220         addHeaderView(mHeadView, null, false);
    221         
    222         mHeadState = DONE;
    223     }
    224     
    225     /**
    226      * 添加加载更多FootView
    227      * @date 2013-11-11 下午9:52:37
    228      * @change JohnWatson
    229      * @version 1.0
    230      */
    231     private void addFooterView() {
    232         mEndRootView = mInflater.inflate(R.layout.listfooter_more, null);
    233         mEndRootView.setVisibility(View.VISIBLE);
    234         mEndLoadProgressBar = (ProgressBar) mEndRootView
    235                 .findViewById(R.id.pull_to_refresh_progress);
    236         mEndLoadTipsTextView = (TextView) mEndRootView.findViewById(R.id.load_more);
    237         mEndRootView.setOnClickListener(new View.OnClickListener() {
    238 
    239             @Override
    240             public void onClick(View v) {
    241                 if(mCanLoadMore){
    242                     if(mCanRefresh){
    243                         // 当可以下拉刷新时,如果FootView没有正在加载,并且HeadView没有正在刷新,才可以点击加载更多。
    244                         if(mEndState != ENDINT_LOADING && mHeadState != REFRESHING){
    245                             mEndState = ENDINT_LOADING;
    246                             onLoadMore();
    247                         }
    248                     }else if(mEndState != ENDINT_LOADING){
    249                         // 当不能下拉刷新时,FootView不正在加载时,才可以点击加载更多。
    250                         mEndState = ENDINT_LOADING;
    251                         onLoadMore();
    252                     }
    253                 }
    254             }
    255         });
    256         
    257         addFooterView(mEndRootView);
    258         
    259         if(mIsAutoLoadMore){
    260             mEndState = ENDINT_AUTO_LOAD_DONE;
    261         }else{
    262             mEndState = ENDINT_MANUAL_LOAD_DONE;
    263         }
    264     }
    265 
    266     /**
    267      * 实例化下拉刷新的箭头的动画效果 
    268      * @param pAnimDuration 动画运行时长
    269      * @date 2013-11-20 上午11:53:22
    270      * @change JohnWatson
    271      * @version 1.0
    272      */
    273     private void initPullImageAnimation(final int pAnimDuration) {
    274         
    275         int _Duration;
    276         
    277         if(pAnimDuration > 0){
    278             _Duration = pAnimDuration;
    279         }else{
    280             _Duration = 250;
    281         }
    282 //        Interpolator _Interpolator;
    283 //        switch (pAnimType) {
    284 //        case 0:
    285 //            _Interpolator = new AccelerateDecelerateInterpolator();
    286 //            break;
    287 //        case 1:
    288 //            _Interpolator = new AccelerateInterpolator();
    289 //            break;
    290 //        case 2:
    291 //            _Interpolator = new AnticipateInterpolator();
    292 //            break;
    293 //        case 3:
    294 //            _Interpolator = new AnticipateOvershootInterpolator();
    295 //            break;
    296 //        case 4:
    297 //            _Interpolator = new BounceInterpolator();
    298 //            break;
    299 //        case 5:
    300 //            _Interpolator = new CycleInterpolator(1f);
    301 //            break;
    302 //        case 6:
    303 //            _Interpolator = new DecelerateInterpolator();
    304 //            break;
    305 //        case 7:
    306 //            _Interpolator = new OvershootInterpolator();
    307 //            break;
    308 //        default:
    309 //            _Interpolator = new LinearInterpolator();
    310 //            break;
    311 //        }
    312         
    313         Interpolator _Interpolator = new LinearInterpolator();
    314         
    315         mArrowAnim = new RotateAnimation(0, -180,
    316                 RotateAnimation.RELATIVE_TO_SELF, 0.5f,
    317                 RotateAnimation.RELATIVE_TO_SELF, 0.5f);
    318         mArrowAnim.setInterpolator(_Interpolator);
    319         mArrowAnim.setDuration(_Duration);
    320         mArrowAnim.setFillAfter(true);
    321 
    322         mArrowReverseAnim = new RotateAnimation(-180, 0,
    323                 RotateAnimation.RELATIVE_TO_SELF, 0.5f,
    324                 RotateAnimation.RELATIVE_TO_SELF, 0.5f);
    325         mArrowReverseAnim.setInterpolator(_Interpolator);
    326         mArrowReverseAnim.setDuration(_Duration);
    327         mArrowReverseAnim.setFillAfter(true);
    328     }
    329 
    330     /**
    331      * 测量HeadView宽高(注意:此方法仅适用于LinearLayout,请读者自己测试验证。)
    332      * @param pChild 
    333      * @date 2013-11-20 下午4:12:07
    334      * @change JohnWatson
    335      * @version 1.0
    336      */
    337     private void measureView(View pChild) {
    338         ViewGroup.LayoutParams p = pChild.getLayoutParams();
    339         if (p == null) {
    340             p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
    341                     ViewGroup.LayoutParams.WRAP_CONTENT);
    342         }
    343         int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0 + 0, p.width);
    344         int lpHeight = p.height;
    345 
    346         int childHeightSpec;
    347         if (lpHeight > 0) {
    348             childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight,
    349                     MeasureSpec.EXACTLY);
    350         } else {
    351             childHeightSpec = MeasureSpec.makeMeasureSpec(0,
    352                     MeasureSpec.UNSPECIFIED);
    353         }
    354         pChild.measure(childWidthSpec, childHeightSpec);
    355     }
    356     
    357     /**
    358      *为了判断滑动到ListView底部没
    359      */
    360     @Override
    361     public void onScroll(AbsListView pView, int pFirstVisibleItem,
    362             int pVisibleItemCount, int pTotalItemCount) {
    363         mFirstItemIndex = pFirstVisibleItem;
    364         mLastItemIndex = pFirstVisibleItem + pVisibleItemCount - 2;
    365         mCount = pTotalItemCount - 2;
    366         if (pTotalItemCount > pVisibleItemCount ) {
    367             mEnoughCount = true;
    368 //            endingView.setVisibility(View.VISIBLE);
    369         } else {
    370             mEnoughCount = false;
    371         }
    372     }
    373 
    374     /**
    375      *这个方法,可能有点乱,大家多读几遍就明白了。
    376      */
    377     @Override
    378     public void onScrollStateChanged(AbsListView pView, int pScrollState) {
    379         if(mCanLoadMore){// 存在加载更多功能
    380             if (mLastItemIndex ==  mCount && pScrollState == SCROLL_STATE_IDLE) {
    381                 //SCROLL_STATE_IDLE=0,滑动停止
    382                 if (mEndState != ENDINT_LOADING) {
    383                     if(mIsAutoLoadMore){// 自动加载更多,我们让FootView显示 “更    多”
    384                         if(mCanRefresh){
    385                             // 存在下拉刷新并且HeadView没有正在刷新时,FootView可以自动加载更多。
    386                             if(mHeadState != REFRESHING){
    387                                 // FootView显示 : 更    多  ---> 加载中...
    388                                 mEndState = ENDINT_LOADING;
    389                                 onLoadMore();
    390                                 changeEndViewByState();
    391                             }
    392                         }else{// 没有下拉刷新,我们直接进行加载更多。
    393                             // FootView显示 : 更    多  ---> 加载中...
    394                             mEndState = ENDINT_LOADING;
    395                             onLoadMore();
    396                             changeEndViewByState();
    397                         }
    398                     }else{// 不是自动加载更多,我们让FootView显示 “点击加载”
    399                         // FootView显示 : 点击加载  ---> 加载中...
    400                         mEndState = ENDINT_MANUAL_LOAD_DONE;
    401                         changeEndViewByState();
    402                     }
    403                 }
    404             }
    405         }else if(mEndRootView != null && mEndRootView.getVisibility() == VISIBLE){
    406             // 突然关闭加载更多功能之后,我们要移除FootView。
    407             System.out.println("this.removeFooterView(endRootView);...");
    408             mEndRootView.setVisibility(View.GONE);
    409             this.removeFooterView(mEndRootView);
    410         }
    411     }
    412 
    413     /**
    414      * 改变加载更多状态
    415      * @date 2013-11-11 下午10:05:27
    416      * @change JohnWatson
    417      * @version 1.0
    418      */
    419     private void  changeEndViewByState() {
    420         if (mCanLoadMore) {
    421             //允许加载更多
    422             switch (mEndState) {
    423             case ENDINT_LOADING://刷新中
    424                 
    425                 // 加载中...
    426                 if(mEndLoadTipsTextView.getText().equals(
    427                         R.string.p2refresh_doing_end_refresh)){
    428                     break;
    429                 }
    430                 mEndLoadTipsTextView.setText(R.string.p2refresh_doing_end_refresh);
    431                 mEndLoadTipsTextView.setVisibility(View.VISIBLE);
    432                 mEndLoadProgressBar.setVisibility(View.VISIBLE);
    433                 break;
    434             case ENDINT_MANUAL_LOAD_DONE:// 手动刷新完成
    435                 
    436                 // 点击加载
    437                 mEndLoadTipsTextView.setText(R.string.p2refresh_end_click_load_more);
    438                 mEndLoadTipsTextView.setVisibility(View.VISIBLE);
    439                 mEndLoadProgressBar.setVisibility(View.GONE);
    440                 
    441                 mEndRootView.setVisibility(View.VISIBLE);
    442                 break;
    443             case ENDINT_AUTO_LOAD_DONE:// 自动刷新完成
    444                 
    445                 // 更    多
    446                 mEndLoadTipsTextView.setText(R.string.p2refresh_end_load_more);
    447                 mEndLoadTipsTextView.setVisibility(View.VISIBLE);
    448                 mEndLoadProgressBar.setVisibility(View.GONE);
    449                 
    450                 mEndRootView.setVisibility(View.VISIBLE);
    451                 break;
    452             default:
    453                 // 原来的代码是为了: 当所有item的高度小于ListView本身的高度时,
    454                 // 要隐藏掉FootView,大家自己去原作者的代码参考。
    455                 
    456 //                if (enoughCount) {                    
    457 //                    endRootView.setVisibility(View.VISIBLE);
    458 //                } else {
    459 //                    endRootView.setVisibility(View.GONE);
    460 //                }
    461                 break;
    462             }
    463         }
    464     }
    465     
    466     /**
    467      *原作者的,我没改动,请读者自行优化。
    468      */
    469     public boolean onTouchEvent(MotionEvent event) {
    470         
    471         if (mCanRefresh) {
    472             if(mCanLoadMore && mEndState == ENDINT_LOADING){
    473                 // 如果存在加载更多功能,并且当前正在加载更多,默认不允许下拉刷新,必须加载完毕后才能使用。
    474                 return super.onTouchEvent(event);
    475             }
    476             
    477             switch (event.getAction()) {
    478             
    479             case MotionEvent.ACTION_DOWN:
    480                 if (mFirstItemIndex == 0 && !mIsRecored) {
    481                     mIsRecored = true;
    482                     mStartY = (int) event.getY();
    483                 }
    484                 break;
    485 
    486             case MotionEvent.ACTION_UP:
    487 
    488                 if (mHeadState != REFRESHING && mHeadState != LOADING) {
    489                     if (mHeadState == DONE) {
    490                         
    491                     }
    492                     if (mHeadState == PULL_TO_REFRESH) {
    493                         mHeadState = DONE;
    494                         changeHeaderViewByState();
    495                     }
    496                     if (mHeadState == RELEASE_TO_REFRESH) {
    497                         mHeadState = REFRESHING;
    498                         changeHeaderViewByState();
    499                         onRefresh();
    500                     }
    501                 }
    502 
    503                 mIsRecored = false;
    504                 mIsBack = false;
    505 
    506                 break;
    507 
    508             case MotionEvent.ACTION_MOVE:
    509                 int tempY = (int) event.getY();
    510 
    511                 if (!mIsRecored && mFirstItemIndex == 0) {
    512                     mIsRecored = true;
    513                     mStartY = tempY;
    514                 }
    515 
    516                 if (mHeadState != REFRESHING && mIsRecored && mHeadState != LOADING) {
    517 
    518                     // 保证在设置padding的过程中,当前的位置一直是在head,
    519                     // 否则如果当列表超出屏幕的话,当在上推的时候,列表会同时进行滚动
    520                     // 可以松手去刷新了
    521                     if (mHeadState == RELEASE_TO_REFRESH) {
    522 
    523                         setSelection(0);
    524 
    525                         // 往上推了,推到了屏幕足够掩盖head的程度,但是还没有推到全部掩盖的地步
    526                         if (((tempY - mStartY) / RATIO < mHeadViewHeight)
    527                                 && (tempY - mStartY) > 0) {
    528                             mHeadState = PULL_TO_REFRESH;
    529                             changeHeaderViewByState();
    530                         }
    531                         // 一下子推到顶了
    532                         else if (tempY - mStartY <= 0) {
    533                             mHeadState = DONE;
    534                             changeHeaderViewByState();
    535                         }
    536                         // 往下拉了,或者还没有上推到屏幕顶部掩盖head的地步
    537                     }
    538                     // 还没有到达显示松开刷新的时候,DONE或者是PULL_To_REFRESH状态
    539                     if (mHeadState == PULL_TO_REFRESH) {
    540 
    541                         setSelection(0);
    542 
    543                         // 下拉到可以进入RELEASE_TO_REFRESH的状态
    544                         if ((tempY - mStartY) / RATIO >= mHeadViewHeight) {
    545                             mHeadState = RELEASE_TO_REFRESH;
    546                             mIsBack = true;
    547                             changeHeaderViewByState();
    548                         } else if (tempY - mStartY <= 0) {
    549                             mHeadState = DONE;
    550                             changeHeaderViewByState();
    551                         }
    552                     }
    553 
    554                     if (mHeadState == DONE) {
    555                         if (tempY - mStartY > 0) {
    556                             mHeadState = PULL_TO_REFRESH;
    557                             changeHeaderViewByState();
    558                         }
    559                     }
    560 
    561                     if (mHeadState == PULL_TO_REFRESH) {
    562                         mHeadView.setPadding(0, -1 * mHeadViewHeight
    563                                 + (tempY - mStartY) / RATIO, 0, 0);
    564 
    565                     }
    566 
    567                     if (mHeadState == RELEASE_TO_REFRESH) {
    568                         mHeadView.setPadding(0, (tempY - mStartY) / RATIO
    569                                 - mHeadViewHeight, 0, 0);
    570                     }
    571                 }
    572                 break;
    573             }
    574         }
    575 
    576         return super.onTouchEvent(event);
    577     }
    578 
    579     /**
    580      * 当HeadView状态改变时候,调用该方法,以更新界面
    581      * @date 2013-11-20 下午4:29:44
    582      * @change JohnWatson
    583      * @version 1.0
    584      */
    585     private void changeHeaderViewByState() {
    586         switch (mHeadState) {
    587         case RELEASE_TO_REFRESH:
    588             mArrowImageView.setVisibility(View.VISIBLE);
    589             mProgressBar.setVisibility(View.GONE);
    590             mTipsTextView.setVisibility(View.VISIBLE);
    591             mLastUpdatedTextView.setVisibility(View.VISIBLE);
    592 
    593             mArrowImageView.clearAnimation();
    594             mArrowImageView.startAnimation(mArrowAnim);
    595             // 松开刷新
    596             mTipsTextView.setText(R.string.p2refresh_release_refresh);
    597 
    598             break;
    599         case PULL_TO_REFRESH:
    600             mProgressBar.setVisibility(View.GONE);
    601             mTipsTextView.setVisibility(View.VISIBLE);
    602             mLastUpdatedTextView.setVisibility(View.VISIBLE);
    603             mArrowImageView.clearAnimation();
    604             mArrowImageView.setVisibility(View.VISIBLE);
    605             // 是由RELEASE_To_REFRESH状态转变来的
    606             if (mIsBack) {
    607                 mIsBack = false;
    608                 mArrowImageView.clearAnimation();
    609                 mArrowImageView.startAnimation(mArrowReverseAnim);
    610                 // 下拉刷新
    611                 mTipsTextView.setText(R.string.p2refresh_pull_to_refresh);
    612             } else {
    613                 // 下拉刷新
    614                 mTipsTextView.setText(R.string.p2refresh_pull_to_refresh);
    615             }
    616             break;
    617 
    618         case REFRESHING:
    619             mHeadView.setPadding(0, 0, 0, 0);
    620             
    621             // 华生的建议: 实际上这个的setPadding可以用动画来代替。我没有试,但是我见过。其实有的人也用Scroller可以实现这个效果,
    622             // 我没时间研究了,后期再扩展,这个工作交给小伙伴你们啦~ 如果改进了记得发到我邮箱噢~
    623             // 本人邮箱: xxzhaofeng5412@gmail.com
    624             
    625             mProgressBar.setVisibility(View.VISIBLE);
    626             mArrowImageView.clearAnimation();
    627             mArrowImageView.setVisibility(View.GONE);
    628             // 正在刷新...
    629             mTipsTextView.setText(R.string.p2refresh_doing_head_refresh);
    630             mLastUpdatedTextView.setVisibility(View.VISIBLE);
    631 
    632             break;
    633         case DONE:
    634             mHeadView.setPadding(0, -1 * mHeadViewHeight, 0, 0);
    635             
    636             // 此处可以改进,同上所述。
    637             
    638             mProgressBar.setVisibility(View.GONE);
    639             mArrowImageView.clearAnimation();
    640             mArrowImageView.setImageResource(R.drawable.arrow);
    641             // 下拉刷新
    642             mTipsTextView.setText(R.string.p2refresh_pull_to_refresh);
    643             mLastUpdatedTextView.setVisibility(View.VISIBLE);
    644 
    645             break;
    646         }
    647     }
    648 
    649     /**
    650      * 下拉刷新监听接口
    651      * @date 2013-11-20 下午4:50:51
    652      * @change JohnWatson
    653      * @version 1.0
    654      */
    655     public interface OnRefreshListener {
    656         public void onRefresh();
    657     }
    658     
    659     /**
    660      * 加载更多监听接口
    661      * @date 2013-11-20 下午4:50:51
    662      * @change JohnWatson
    663      * @version 1.0
    664      */
    665     public interface OnLoadMoreListener {
    666         public void onLoadMore();
    667     }
    668     
    669     public void setOnRefreshListener(OnRefreshListener pRefreshListener) {
    670         if(pRefreshListener != null){
    671             mRefreshListener = pRefreshListener;
    672             mCanRefresh = true;
    673         }
    674     }
    675 
    676     public void setOnLoadListener(OnLoadMoreListener pLoadMoreListener) {
    677         if(pLoadMoreListener != null){
    678             mLoadMoreListener = pLoadMoreListener;
    679             mCanLoadMore = true;
    680             if(mCanLoadMore && getFooterViewsCount() == 0){
    681                 addFooterView();
    682             }
    683         }
    684     }
    685     
    686     /**
    687      * 正在下拉刷新
    688      * @date 2013-11-20 下午4:45:47
    689      * @change JohnWatson
    690      * @version 1.0
    691      */
    692     private void onRefresh() {
    693         if (mRefreshListener != null) {
    694             mRefreshListener.onRefresh();
    695         }
    696     }
    697     
    698     /**
    699      * 下拉刷新完成
    700      * @date 2013-11-20 下午4:44:12
    701      * @change JohnWatson
    702      * @version 1.0
    703      */
    704     public void onRefreshComplete() {
    705         // 下拉刷新后是否显示第一条Item 
    706         if(mIsMoveToFirstItemAfterRefresh)setSelection(0);
    707         
    708         mHeadState = DONE;
    709         // 最近更新: Time
    710         mLastUpdatedTextView.setText(
    711                 getResources().getString(R.string.p2refresh_refresh_lasttime) + 
    712                 new SimpleDateFormat(DATE_FORMAT_STR, Locale.CHINA).format(new Date()));
    713         changeHeaderViewByState();
    714     }
    715 
    716     /**
    717      * 正在加载更多,FootView显示 : 加载中...
    718      * @date 2013-11-20 下午4:35:51
    719      * @change JohnWatson
    720      * @version 1.0
    721      */
    722     private void onLoadMore() {
    723         if (mLoadMoreListener != null) {
    724             // 加载中...
    725             mEndLoadTipsTextView.setText(R.string.p2refresh_doing_end_refresh);
    726             mEndLoadTipsTextView.setVisibility(View.VISIBLE);
    727             mEndLoadProgressBar.setVisibility(View.VISIBLE);
    728             
    729             mLoadMoreListener.onLoadMore();
    730         }
    731     }
    732 
    733     /**
    734      * 加载更多完成 
    735      * @date 2013-11-11 下午10:21:38
    736      * @change JohnWatson
    737      * @version 1.0
    738      */
    739     public void onLoadMoreComplete() {
    740         if(mIsAutoLoadMore){
    741             mEndState = ENDINT_AUTO_LOAD_DONE;
    742         }else{
    743             mEndState = ENDINT_MANUAL_LOAD_DONE;
    744         }
    745         changeEndViewByState();
    746     }
    747     
    748     /**
    749      * 主要更新一下刷新时间啦!
    750      * @param adapter
    751      * @date 2013-11-20 下午5:35:51
    752      * @change JohnWatson
    753      * @version 1.0
    754      */
    755     public void setAdapter(BaseAdapter adapter) {
    756         // 最近更新: Time
    757         mLastUpdatedTextView.setText(
    758                 getResources().getString(R.string.p2refresh_refresh_lasttime) + 
    759                 new SimpleDateFormat(DATE_FORMAT_STR, Locale.CHINA).format(new Date()));
    760         super.setAdapter(adapter);
    761     }
    762 
    763 }
    View Code

    在布局里添加即可:

     1 <android.support.v4.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
     2     xmlns:tools="http://schemas.android.com/tools"
     3     android:id="@+id/swipe_container"
     4     android:layout_width="match_parent"
     5     android:layout_height="match_parent"
     6     tools:context=".MainActivity" >
     7 
     8 
     9     <com.maomao.beautymovie.widget.CustomListView
    10         android:id="@+id/movielistview"
    11         android:layout_width="match_parent"
    12         android:layout_height="match_parent"
    13         android:choiceMode="singleChoice"
    14         android:descendantFocusability="blocksDescendants"
    15         android:divider="@null"
    16         android:scrollbars="none" >
    17     </com.maomao.beautymovie.widget.CustomListView>
    18 
    19 </android.support.v4.widget.SwipeRefreshLayout>

    在activity或fragment使用:

     1 package com.maomao.beautymovie.fragment;
     2 
     3 public class AllMovieFragment extends Fragment{
     4 
     5     private static final String TAG = "movieFragment";
     6     private SwipeRefreshLayout swipeLayout;
     7     private CustomListView movieListView;
     8     private MovieListAdapter movieListAdapter;
     9     private List<MovieBean> moviesLsit;
    10     
    11     public AllMovieFragment()
    12     {
    13     }
    14 
    15     public AllMovieFragment(List<MovieBean> moviesLsit)
    16     {
    17         this.moviesLsit = moviesLsit;
    18     }
    19     
    20 
    21     
    22     @Override
    23     public void onCreate(Bundle savedInstanceState) {
    24         super.onCreate(savedInstanceState);
    25 
    26     }
    27 
    28     @SuppressLint("InlinedApi")
    29     @Override
    30     public View onCreateView(LayoutInflater inflater, ViewGroup container,
    31             Bundle savedInstanceState) {
    32         View view            = inflater.inflate(R.layout.allmoviefrag, container, false);
    33         movieListView = (CustomListView)view.findViewById(R.id.movielistview);
    34 
    35         movieListAdapter = new MovieListAdapter(getActivity(), moviesLsit);
    36         
    37         movieListView.setAdapter(movieListAdapter); 
    38         initListView();
    39 
    40         
    41         
    42         return view;
    43     }
    44 
    45     
    46     
    47     public void initListView()
    48     {
    49         movieListView.setOnItemClickListener(new OnItemClickListener() {
    50             
    51 
    52             @Override
    53             public void onItemClick(AdapterView<?> parent, View view, int position,
    54                     long id) {
    55                 // 此处传回来的position和mAdapter.getItemId()获取的一致;
    56                 //parent.getAdapter().getItem(position)
    57                 MovieBean movieBean = (MovieBean)parent.getAdapter().getItem(position);
    58                 Toast.makeText(getActivity(), movieBean.getMovieName(), Toast.LENGTH_SHORT).show();
    59                 //Toast.makeText(getActivity(), "位置"+Integer.toString(position), Toast.LENGTH_SHORT).show();
    60                 
    61             }
    62         });
    63         
    64         
    65         movieListView.setOnLoadListener(new OnLoadMoreListener() {
    66 
    67             @Override
    68             public void onLoadMore() {
    69                 // TODO 加载更多
    70                 Log.e(TAG, "onLoad");
    71                 Toast.makeText(getActivity(), "load", Toast.LENGTH_SHORT).show();
    72                 
    73                 movieListView.postDelayed(new Runnable() {
    74                 
    75                                 @Override
    76                                 public void run() {
    77                                       moviesLsit.addAll(MyDataSource.addMovieDataSource());
    78                                       movieListAdapter.notifyDataSetChanged();
    79                               // 加载完后调用该方法
    80                                       movieListView.onLoadMoreComplete();    //加载更多完成
    81                                 }
    82                             }, 5000);
    83                 
    84                         
    85             }
    86         });
    87         
    88         
    89         //CustomListView简单易用,如下代码即可说明,可选择性的开关下拉刷新和加载更多,同时可在设置界面设置是否启动自动加载更多
    90         //关闭下拉刷新
    91         movieListView.setCanRefresh(false);
    92         //启动加载更多
    93         movieListView.setCanLoadMore(true);
    94         //启动自动加载更多
    95         movieListView.setAutoLoadMore(false);
    96         
    97     }
    98     
    99 }

    感谢作者。

  • 相关阅读:
    手把手教你写vue插件并发布(一)
    npm 换源
    ajax上传文件显示进度
    angularjs的表单验证
    利用公钥认证登录远程服务器
    centos 搭建 leanote
    读书笔记-JavaScript高级程序设计(1)
    C++读写TXT文件中的string或者int型数据以及string流的用法
    不相交集ADT--链表实现
    不相交集ADT--数组实现
  • 原文地址:https://www.cnblogs.com/ning1121/p/4377807.html
Copyright © 2020-2023  润新知