zoukankan      html  css  js  c++  java
  • 开源中国APP下拉刷新控件实现

          开源中国的APP做得还是挺玄的,并且发布了源码,有兴趣的朋友可以到百度上搜索下载研究。

          因项目需要,特地研究了开源中国的自定义下拉组件,对它也有了一定的了解。代码中我做了详细的注释,它只是个控件,

     非要看效果的话需要建议下载它的APP进行研究。这个Demo实例下载地址见:

        

    package com.example.myui.widget;
    
    import android.content.Context;
    import android.util.AttributeSet;
    import android.util.Log;
    import android.view.LayoutInflater;
    import android.view.MotionEvent;
    import android.view.View;
    import android.view.ViewGroup;
    import android.view.animation.LinearInterpolator;
    import android.view.animation.RotateAnimation;
    import android.widget.AbsListView;
    import android.widget.ImageView;
    import android.widget.LinearLayout;
    import android.widget.TextView;
    import android.widget.AbsListView.OnScrollListener;
    import android.widget.ListView;
    import android.widget.ProgressBar;
    
    import com.example.myui.R;
    
    /**
     * RefreshListView.java
     * 工程:MyUI
     * 功能:下拉刷新/上拉加载
     *
     * author    		date          	time      
     * ─────────────────────────────────────────────
     * fengwh          2014-11-6   	  下午下午2:53:08
     *
     * Copyright (c) 2014, KEYTOP All Rights Reserved.
     */
    public class RefreshListView extends ListView implements OnScrollListener{
    	private final static String TAG = "PullToRefreshListView";  
        // 下拉刷新标志   
        private final static int PULL_To_REFRESH = 0; 
        // 松开刷新标志   
        private final static int RELEASE_To_REFRESH = 1; 
        // 正在刷新标志   
        private final static int REFRESHING = 2;  
        // 刷新完成标志   
        private final static int DONE = 3;  
        //状态标志
        private int state;
        
       private RotateAnimation mAnimation; //旋转动画 
        private RotateAnimation reverseAnimation; //反旋转动画 
        //填充器
        private LayoutInflater inflater; 
       //加载头文件界面
       private LinearLayout headView;
       //箭头图标
       private ImageView arrowImage; //arrow image
       //正在加载进度条
       private ProgressBar mProgressBar; 
       //提示语
        private TextView tipsTextview;
        //更新时间
        private TextView lastUpdatedTextView;  
        //最大高度
        private int headContentHeight;
        //保存高度
        private int headContentOriginalTopPadding;
        //第一项Index
        private int firstItemIndex;
        //当前滑动条状态
        private int currentScrollState;
        //开始高度
        private int startY;
        //是否返回
        private boolean isBack;
        //刷新监听器
        public OnRefreshListener refreshListener;
        
        //是否记录过   
        private boolean isRecored; 
    
        //初始化
    	public RefreshListView(Context context, AttributeSet attrs, int defStyle) {
    		super(context, attrs, defStyle);
    		init(context);
    	}
    	//初始化
    	public RefreshListView(Context context, AttributeSet attrs) {
    		super(context, attrs);
    		init(context);
    	}
    	//监听滑动状态
    	@Override
    	public void onScrollStateChanged(AbsListView view, int scrollState) {
    		currentScrollState = scrollState;
    	}
    	//显示的第一条记录索引号
    	@Override
    	public void onScroll(AbsListView view, int firstVisibleItem,
    			int visibleItemCount, int totalItemCount) {
    		firstItemIndex=firstVisibleItem;
    		
    	}
    	
    	/**
    	 * 初始化控件
    	 * @param context
    	 */
    	private void init(Context context){
    		//动画 
    		mAnimation = new RotateAnimation(0, -180, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f);
    		mAnimation.setInterpolator(new LinearInterpolator()); //匀速变动
    		mAnimation.setFillAfter(true); 
    		mAnimation.setDuration(100);
    		reverseAnimation = new RotateAnimation(-180, 0, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f);
    		reverseAnimation.setInterpolator(new LinearInterpolator()); //匀速变动
    		reverseAnimation.setFillAfter(true); //顺时针转动画
    		reverseAnimation.setDuration(100);
    		//----------------------Separator---------------
    		inflater = LayoutInflater.from(context);
    		headView=(LinearLayout) inflater.inflate(R.layout.pull_to_refresh_head, null);
    		arrowImage = (ImageView) headView.findViewById(R.id.head_arrowImageView);
    		mProgressBar = (ProgressBar) headView.findViewById(R.id.head_progressBar);
    		tipsTextview = (TextView) headView.findViewById(R.id.head_tipsTextView);
    		lastUpdatedTextView=(TextView) headView.findViewById(R.id.head_lastUpdatedTextView);
    		
    		headContentOriginalTopPadding = headView.getPaddingTop();  
    		
    		
    		measureView(headView); //计算显示headView宽高
    		headContentHeight = headView.getMeasuredHeight();
    		headView.setPadding(headView.getPaddingLeft(), -1*headContentOriginalTopPadding, headView.getPaddingRight(), headView.getPaddingBottom());
    		headView.invalidate(); //无效化
    		
    		addHeaderView(headView);
    		this.setOnScrollListener(this);
    		
    		
    	}
    	
    	@Override
    	public boolean onTouchEvent(MotionEvent ev) {
    		switch (ev.getAction()) {
    		case MotionEvent.ACTION_DOWN: //手势向下滑动
    			if (0==firstItemIndex&&!isRecored) {
    				startY=(int) ev.getY(); //鼠标点击的Y值
    				isRecored=true; //是否已经记录过
    				System.out.println("记录首次点击的Y值="+startY);
    			}
    			break;
    		case MotionEvent.ACTION_CANCEL:
    		case MotionEvent.ACTION_UP: //手势抬起
    			if (state!=REFRESHING) { 
    				if (state==DONE) { 
    //					System.out.println("?-->Done");
    				}else if (state==PULL_To_REFRESH) {//向下可刷新-->已经完成
    					state=DONE;
    					changeHeaderViewByState(); 
    					System.out.println("向下可刷新-->已经完成");
    				}else if (state==RELEASE_To_REFRESH) { //松开刷新-->刷新
    					state=REFRESHING;
    					changeHeaderViewByState();  
    					onRefresh(); 
    					System.out.println("松开刷新-->刷新");
    				}
    			}
    			isRecored=false;
    			isBack = false;
    			break;
    		case MotionEvent.ACTION_MOVE:
    			int tempY = (int) ev.getY(); //滑动的Y值
    			System.out.println("滑动的Y值为="+tempY);
    			if (!isRecored&&0==firstItemIndex) {
    				isRecored=true;
    				startY=tempY;
    				System.out.println("记录StartY=tempY="+startY);
    			}
    			//如果当前状态不是 “刷新”
    			if (state!=REFRESHING&&isRecored) {
    				if (state==RELEASE_To_REFRESH) { //松开刷新
    					if ((tempY-startY<headContentHeight+20)&&tempY>startY) {
    						state = PULL_To_REFRESH;  
    						changeHeaderViewByState();  
    						System.out.println("Move:松开刷新状态-->下拉刷新状态");
    					}else if (tempY-startY<=0) { //往上推到顶
    						state = DONE;
    						changeHeaderViewByState();  
    						System.out.println("松开刷新状态-->done状态");
    					}else {
    						System.out.println("往下拉,或者还没有上推到屏幕顶部掩盖head");
    					}
    				}else if (state==PULL_To_REFRESH) {
    					//change state pull_ro_refresh-->release_to_refresh
    					if ((tempY-startY>=headContentHeight+20) && currentScrollState == SCROLL_STATE_TOUCH_SCROLL) {
    						state=RELEASE_To_REFRESH;
    						changeHeaderViewByState();  
    						System.out.println("由done或者下拉刷新状态转-->松开刷新");
    					}else if (tempY-startY<=0) { //推到顶
    						state=DONE;
    						changeHeaderViewByState();  
    						System.out.println("下拉刷新状态转-->Done刷新");
    					}
    				}else if (state == DONE) {
    					if (tempY-startY>0) {
    						state=PULL_To_REFRESH;
    						changeHeaderViewByState();  
    						System.out.println("Move:由done状态-->下拉刷新状态");
    					}
    				}
    				
    				//update headView state
    				if (state==PULL_To_REFRESH) {
    					int topPadding = (int)((-1 * headContentHeight + (tempY - startY)));
                    	headView.setPadding(headView.getPaddingLeft(), topPadding, headView.getPaddingRight(), headView.getPaddingBottom());   
                        headView.invalidate(); 
                        System.out.println("下拉刷新-TopPadding:"+topPadding);
    				}
    				
    				if (state==RELEASE_To_REFRESH) {
    					int topPadding = (int)((tempY - startY - headContentHeight));
                    	headView.setPadding(headView.getPaddingLeft(), topPadding, headView.getPaddingRight(), headView.getPaddingBottom());    
                        headView.invalidate();  
                        System.out.println("释放刷新-TopPadding:"+topPadding);
    				}
    			}
    			break;
    		default:
    			break;
    		}
    		return super.onTouchEvent(ev);
    	}
        //点击刷新
        public void clickRefresh() {
        	setSelection(0);
        	state = REFRESHING;  
            changeHeaderViewByState();  
            onRefresh(); 
        }
        
        //个性化刷新:重新显示数据
        private void onRefresh() {  
            if (refreshListener != null) {  
                refreshListener.onRefresh();  
            }  
        }
        
       // 当状态改变时候,调用该方法,以更新界面   
        private void changeHeaderViewByState() {  
            switch (state) {  
            case RELEASE_To_REFRESH:  
            	
                arrowImage.setVisibility(View.VISIBLE);  
                mProgressBar.setVisibility(View.GONE);  
                tipsTextview.setVisibility(View.VISIBLE);  
                lastUpdatedTextView.setVisibility(View.VISIBLE);  
      
                arrowImage.clearAnimation();  
                arrowImage.startAnimation(mAnimation);  
      
                tipsTextview.setText(R.string.pull_to_refresh_release_label);  
      
                Log.v(TAG, "当前状态,松开刷新");  
                break;  
            case PULL_To_REFRESH:
            	
                mProgressBar.setVisibility(View.GONE);  
                tipsTextview.setVisibility(View.VISIBLE);  
                lastUpdatedTextView.setVisibility(View.VISIBLE);  
                arrowImage.clearAnimation();  
                arrowImage.setVisibility(View.VISIBLE);  
                if (isBack) {  
                    isBack = false;  
                    arrowImage.clearAnimation();  
                    arrowImage.startAnimation(reverseAnimation);  
                } 
                tipsTextview.setText(R.string.pull_to_refresh_pull_label);  
    
                Log.v(TAG, "当前状态,下拉刷新");  
                break;  
      
            case REFRESHING:   
            	System.out.println("刷新REFRESHING-TopPad:"+headContentOriginalTopPadding);
            	headView.setPadding(headView.getPaddingLeft(), headContentOriginalTopPadding, headView.getPaddingRight(), headView.getPaddingBottom());   
                headView.invalidate();  
      
                mProgressBar.setVisibility(View.VISIBLE);  
                arrowImage.clearAnimation();  
                arrowImage.setVisibility(View.GONE);  
                tipsTextview.setText(R.string.pull_to_refresh_refreshing_label);  
                lastUpdatedTextView.setVisibility(View.GONE);  
      
                Log.v(TAG, "当前状态,正在刷新...");  
                break;  
            case DONE:  
            	System.out.println("完成DONE-TopPad:"+(-1 * headContentHeight));
            	headView.setPadding(headView.getPaddingLeft(), -1 * headContentHeight, headView.getPaddingRight(), headView.getPaddingBottom());  
                headView.invalidate();  
      
                mProgressBar.setVisibility(View.GONE);  
                arrowImage.clearAnimation();  
                // 此处更换图标   
                arrowImage.setImageResource(R.drawable.ic_pulltorefresh_arrow);  
      
                tipsTextview.setText(R.string.pull_to_refresh_pull_label);  
                lastUpdatedTextView.setVisibility(View.VISIBLE);  
                Log.v(TAG, "Done..."); 
                break;  
            }  
        }  
        
        /**
         * 回调函数
         * @param refreshListener
         */
        public void setOnRefreshListener(OnRefreshListener refreshListener) {  
            this.refreshListener = refreshListener;  
        }  
      
        public interface OnRefreshListener {  
            public void onRefresh();  
        }
        
        /**
         * 主要在handler中进行调用 松开刷新-->DONE
         * @param update
         */
        public void onRefreshComplete(String update) {  
            lastUpdatedTextView.setText(update);  
            onRefreshComplete();
        } 
        
        public void onRefreshComplete() {  
            state = DONE;  
            changeHeaderViewByState();  
        } 
    	/**
    	 * 计算headView的宽高
    	 * @param child
    	 */
    	private void measureView(View child){
    		ViewGroup.LayoutParams lp = child.getLayoutParams();
    		if (null==lp) {
    			lp = new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
    		}
    		int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0+0, lp.width);
    		int lpHeight = lp.height;
    		int childHeightSpec;
    		if (lpHeight>0) {
    			childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY);
    		}else {
    			childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
    		}
    		child.measure(childWidthSpec, childHeightSpec);
    	}
    
    }
    

    headView的布局:

    <?xml version="1.0" encoding="utf-8"?>  
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
        android:layout_width="fill_parent"  
        android:layout_height="fill_parent"  
        android:orientation="vertical">  
      
        <RelativeLayout  
            android:id="@+id/head_contentLayout"  
            android:layout_width="fill_parent"  
            android:layout_height="fill_parent" 
            android:paddingTop="10dip"
        	android:paddingBottom="15dip">  
      
            <FrameLayout  
                android:layout_width="wrap_content"  
                android:layout_height="fill_parent"  
                android:layout_alignParentLeft="true"  
                android:layout_centerVertical="true"
            	android:layout_marginLeft="30dip"
            	android:layout_marginRight="20dip">  
    
                <ImageView  
                    android:id="@+id/head_arrowImageView"  
                    android:layout_width="wrap_content"  
                    android:layout_height="wrap_content"  
                    android:layout_gravity="center"  
                    android:src="@drawable/ic_pulltorefresh_arrow" />  
      
            </FrameLayout> 
      
            <FrameLayout  
                android:layout_width="wrap_content"  
                android:layout_height="fill_parent"  
                android:layout_alignParentLeft="true"  
                android:layout_centerVertical="true"
                android:paddingTop="10dip"
        		android:paddingBottom="15dip"
            	android:layout_marginLeft="100dip"
            	android:layout_marginRight="10dip">  
      
    	        <ProgressBar  
    	            android:id="@+id/head_progressBar"
    				style="@style/loading_small"
    				android:visibility="gone"/>
      
            </FrameLayout>
      
            <LinearLayout  
                android:layout_width="wrap_content"  
                android:layout_height="wrap_content"  
                android:layout_centerInParent="true"
                android:gravity="center_horizontal"  
                android:orientation="vertical">  
      
                <TextView  
                    android:id="@+id/head_tipsTextView"  
                    android:layout_width="wrap_content"  
                    android:layout_height="wrap_content"  
                    android:text="@string/pull_to_refresh_pull_label"  
                    android:textColor="@color/black"/>  
      
                <TextView  
                    android:id="@+id/head_lastUpdatedTextView"  
                    android:layout_width="wrap_content"  
                    android:layout_height="wrap_content" 
                    android:textColor="@color/black"  
                    android:textSize="10sp" />  
                  
            </LinearLayout>  
        </RelativeLayout>  
      
      
    </LinearLayout> 
    


    loading文件加载:需要相应的文件资源

    <?xml version="1.0" encoding="utf-8"?>
    <animation-list android:oneshot="false" 
        xmlns:android="http://schemas.android.com/apk/res/android" >
        	<item android:duration="100" android:drawable="@drawable/loading_0" />
    		<item android:duration="100" android:drawable="@drawable/loading_1" />
    		<item android:duration="100" android:drawable="@drawable/loading_2" />
    		<item android:duration="100" android:drawable="@drawable/loading_3" />
    		<item android:duration="100" android:drawable="@drawable/loading_4" />
    		<item android:duration="100" android:drawable="@drawable/loading_5" />
    		<item android:duration="100" android:drawable="@drawable/loading_6" />
    		<item android:duration="100" android:drawable="@drawable/loading_7" />
    </animation-list>
    



     

       

  • 相关阅读:
    ARC109C Large RPS Tournament 机智
    ABC186F Rook on Grid 树状数组
    二分查找
    CF1445D. Divide and Sum 组合数
    APP测试方法分享
    面试常见问题
    接口测试基础知识
    接口测试一
    web端测试
    Jmeter简介
  • 原文地址:https://www.cnblogs.com/IntelligentBrain/p/5111282.html
Copyright © 2011-2022 走看看