现在的位置: 首页 > 综合 > 正文

开源中国APP下拉刷新控件实现

2018年02月05日 ⁄ 综合 ⁄ 共 11514字 ⁄ 字号 评论关闭

      开源中国的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>

 

   

抱歉!评论已关闭.