2013-05-20 小结

RefreshView下拉刷新问题

public class RefreshListView extends ListView implements OnScrollListener, OnClickListener{

    public interface IListViewState
    {
        int LVS_NORMAL = 0;                    //  普通状态
        int LVS_PULL_REFRESH = 1;            //  下拉刷新状态
        int LVS_RELEASE_REFRESH = 2;        //  松开刷新状态
        int LVS_LOADING = 3;                //  加载状态
    }
    
    
    public interface IOnRefreshListener
    {
        void onRefresh();
    }
    
    
    private View mHeadView;                
    private TextView mRefreshTextview;
    private TextView mLastUpdateTextView;
    private ImageView mArrowImageView;
    private ProgressBar mHeadProgressBar;
    
    private int mHeadContentWidth;
    private int mHeadContentHeight;

    private IOnRefreshListener mOnRefreshListener;            // 头部刷新监听器
    
    // 用于保证startY的坐标在一个完整的touch事件中只被记录一次
    private boolean mIsRecord = false;
    // 标记的Y坐标值
    private int mStartY = 0;
    // 当前视图能看到的第一个项的索引
    private int mFirstItemIndex = -1;
    // MOVE时保存的Y坐标值
    private int mMoveY = 0;
    // LISTVIEW状态
    private int mViewState = IListViewState.LVS_NORMAL;

    private final static int RATIO = 2;
    
    private RotateAnimation animation;
    private RotateAnimation reverseAnimation;//旋转变化动画

    private boolean mBack = false;
    

    
    public RefreshListView(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
        init(context);
    }

    
    public RefreshListView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }
    
    public void setOnRefreshListener(IOnRefreshListener listener)
    {
        mOnRefreshListener = listener;
    }
    
    private void onRefresh()
    {
        if (mOnRefreshListener != null)
        {
            mOnRefreshListener.onRefresh();
        }
    }
    
    public void onRefreshComplete()
    {
        mHeadView.setPadding(0,  -1 * mHeadContentHeight, 0, 0);
        mLastUpdateTextView.setText("上次更新:" + new Date().toLocaleString());
        switchViewState(IListViewState.LVS_NORMAL);
    }
    
    private void init(Context context)
    {
        initHeadView(context);
        
        //initLoadMoreView(context);
        
        setOnScrollListener(this);
    }
    
    
    // 初始化headview试图
    private void initHeadView(Context context)
    {
        mHeadView = LayoutInflater.from(context).inflate(R.layout.head, null);

        mArrowImageView = (ImageView) mHeadView.findViewById(R.id.head_arrowImageView);
        mArrowImageView.setMinimumWidth(60);


        mHeadProgressBar= (ProgressBar) mHeadView.findViewById(R.id.head_progressBar);
        
        mRefreshTextview = (TextView) mHeadView.findViewById(R.id.head_tipsTextView);
        
        mLastUpdateTextView = (TextView) mHeadView.findViewById(R.id.head_lastUpdatedTextView);

        measureView(mHeadView);
        mHeadContentHeight = mHeadView.getMeasuredHeight();
        mHeadContentWidth = mHeadView.getMeasuredWidth();

        mHeadView.setPadding(0, -1 * mHeadContentHeight, 0, 0);
        mHeadView.invalidate();

        addHeaderView(mHeadView, null, false);
        
        animation = new RotateAnimation(0, -180,
                RotateAnimation.RELATIVE_TO_SELF, 0.5f,
                RotateAnimation.RELATIVE_TO_SELF, 0.5f);
        animation.setInterpolator(new LinearInterpolator());
        animation.setDuration(250);
        animation.setFillAfter(true);

        reverseAnimation = new RotateAnimation(-180, 0,
                RotateAnimation.RELATIVE_TO_SELF, 0.5f,
                RotateAnimation.RELATIVE_TO_SELF, 0.5f);
        reverseAnimation.setInterpolator(new LinearInterpolator());
        reverseAnimation.setDuration(200);
        reverseAnimation.setFillAfter(true);
    }
    
    // 初始化footview试图
//    private void initLoadMoreView(Context context)
//    {
//        mFootView= LayoutInflater.from(context).inflate(R.layout.loadmore, null);
//        
//        mLoadMoreView = mFootView.findViewById(R.id.load_more_view);
//        
//        mLoadMoreTextView = (TextView) mFootView.findViewById(R.id.load_more_tv);
//        
//        mLoadingView = mFootView.findViewById(R.id.loading_layout);
//    
//        mLoadMoreView.setOnClickListener(this);
//        
//        addFooterView(mFootView);
//
//    }
    
    // 此方法直接照搬自网络上的�?��下拉刷新的demo,计算headView的width以及height
    private void measureView(View child) {
        ViewGroup.LayoutParams p = child.getLayoutParams();
        if (p == null) {
            p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
                    ViewGroup.LayoutParams.WRAP_CONTENT);
        }
        int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0 + 0, p.width);
        int lpHeight = p.height;
        int childHeightSpec;
        if (lpHeight > 0) {
            childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight,
                    MeasureSpec.EXACTLY);
        } else {
            childHeightSpec = MeasureSpec.makeMeasureSpec(0,
                    MeasureSpec.UNSPECIFIED);
        }
        child.measure(childWidthSpec, childHeightSpec);
    }


    public void onScroll(AbsListView arg0, int firstVisiableItem, int visibleItemCount, int totalItemCount) {
        mFirstItemIndex = firstVisiableItem;

    }

    public void onScrollStateChanged(AbsListView arg0, int arg1) {
        
        
    }

    
    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        // TODO Auto-generated method stub
                
        if (mOnRefreshListener != null)
        {
            switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:        
                doActionDown(ev);
                break;
            case MotionEvent.ACTION_MOVE:
                doActionMove(ev);
                break;
            case MotionEvent.ACTION_UP:
                doActionUp(ev);
                break;
            default:
                break;
            }    
        }
        
                
        return super.onTouchEvent(ev);
    }
    
    private void doActionDown(MotionEvent ev)
    {
        if(mIsRecord == false && mFirstItemIndex == 0)
        {
            mStartY = (int) ev.getY();
            mIsRecord = true;
        }
    }
    
    private void doActionMove(MotionEvent ev)
    {
        mMoveY = (int) ev.getY();
        
        if(mIsRecord == false && mFirstItemIndex == 0)
        {
            mStartY = (int) ev.getY();
            mIsRecord = true;
        }
        
        if (mIsRecord == false || mViewState == IListViewState.LVS_LOADING)
        {
            return ;
        }    
        
        int offset = (mMoveY - mStartY) / RATIO;    
        
        switch(mViewState)
        {
            case IListViewState.LVS_NORMAL:
            {
                if (offset > 0)
                {        
                    mHeadView.setPadding(0, offset - mHeadContentHeight, 0, 0);
                    switchViewState(IListViewState.LVS_PULL_REFRESH);
                }
            }
                break;
            case IListViewState.LVS_PULL_REFRESH:
            {
                setSelection(0);
                mHeadView.setPadding(0, offset - mHeadContentHeight, 0, 0);
                if (offset < 0)
                {
                    switchViewState(IListViewState.LVS_NORMAL);
                }else if (offset > mHeadContentHeight)
                {
                    switchViewState(IListViewState.LVS_RELEASE_REFRESH);
                }
            }
                break;
            case IListViewState.LVS_RELEASE_REFRESH:
            {
                setSelection(0);
                mHeadView.setPadding(0, offset - mHeadContentHeight, 0, 0);
                if (offset >= 0 && offset <= mHeadContentHeight)
                {
                    mBack = true;
                    switchViewState(IListViewState.LVS_PULL_REFRESH);
                }else if (offset < 0)
                {
                    switchViewState(IListViewState.LVS_NORMAL);
                }else{
                
                }
                
            }
                break;
            default:
                return;
        };        
        
    }
    private void doActionUp(MotionEvent ev)
    {
        mIsRecord = false;
        mBack = false;
        
        if (mViewState == IListViewState.LVS_LOADING)
        {
            return ;
        }
        
        switch(mViewState)
        {
        case IListViewState.LVS_NORMAL:
        
            break;
        case IListViewState.LVS_PULL_REFRESH:
            mHeadView.setPadding(0, -1 * mHeadContentHeight, 0, 0);
            switchViewState(IListViewState.LVS_NORMAL);
            break;
        case IListViewState.LVS_RELEASE_REFRESH:
            mHeadView.setPadding(0, 0, 0, 0);
            switchViewState(IListViewState.LVS_LOADING);
            onRefresh();
            break;
        }    
        
    }

    private void switchViewState(int state)
    {    
        
        
        switch(state)
        {
            case IListViewState.LVS_NORMAL:
            {
                Log.e("!!!!!!!!!!!", "convert to IListViewState.LVS_NORMAL");
                mArrowImageView.clearAnimation();
                mArrowImageView.setImageResource(R.drawable.arrow);
            }
                break;
            case IListViewState.LVS_PULL_REFRESH:
            {
                Log.e("!!!!!!!!!!!", "convert to IListViewState.LVS_PULL_REFRESH");
                mHeadProgressBar.setVisibility(View.GONE);
                mArrowImageView.setVisibility(View.VISIBLE);
                mRefreshTextview.setText("下拉可以刷新");
                mArrowImageView.clearAnimation();

                // 是由RELEASE_To_REFRESH状态转变来的
                if (mBack)
                {
                    mBack = false;
                    mArrowImageView.clearAnimation();
                    mArrowImageView.startAnimation(reverseAnimation);
                }
            }
                break;
            case IListViewState.LVS_RELEASE_REFRESH:
            {
                Log.e("!!!!!!!!!!!", "convert to IListViewState.LVS_RELEASE_REFRESH");
                mHeadProgressBar.setVisibility(View.GONE);
                mArrowImageView.setVisibility(View.VISIBLE);
                mRefreshTextview.setText("松开获取更多");
                mArrowImageView.clearAnimation();
                mArrowImageView.startAnimation(animation);
            }
                break;
            case IListViewState.LVS_LOADING:
            {
                Log.e("!!!!!!!!!!!", "convert to IListViewState.LVS_LOADING");
                mHeadProgressBar.setVisibility(View.VISIBLE);
                mArrowImageView.clearAnimation();
                mArrowImageView.setVisibility(View.GONE);
                mRefreshTextview.setText("载入中..");
            }
                break;
                default:
                    return;
        }    
        
        mViewState = state;
        
    }


    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub
        
    }

布局文件

<?xml version="1.0" encoding="utf-8"?>
<!-- ListView的头部 -->

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content" >

    <!-- 内容 -->

    <RelativeLayout
        android:id="@+id/head_contentLayout"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:paddingLeft="30dp" >

        <!-- 箭头图像、进度条 -->

        <FrameLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_centerVertical="true" >

            <!-- 箭头 -->

            <ImageView
                android:id="@+id/head_arrowImageView"
                android:layout_width="20dp"
                android:layout_height="30dp"
                android:layout_gravity="center"
                android:src="@drawable/arrow" />

            <!-- 进度条 -->

            <ProgressBar
                android:id="@+id/head_progressBar"
                style="?android:attr/progressBarStyleSmall"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:visibility="gone" />
        </FrameLayout>

        <!-- 提示、最近更新 -->

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="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="下拉刷新"
                android:textColor="@color/navajowhite"
                android:textSize="15sp" />

            <TextView
                android:id="@+id/head_lastUpdatedTextView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="上次更新"
                android:textColor="@color/gold"
                android:textSize="10sp" />
        </LinearLayout>
    </RelativeLayout>

</LinearLayout>


如何使用:

package com.kalus.aidl;

import java.util.ArrayList;
import java.util.List;

import com.kalus.aidl.RefreshListView.IOnRefreshListener;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.ArrayAdapter;
import android.widget.SimpleAdapter;

public class RefreshActivity extends Activity implements IOnRefreshListener {

    RefreshListView listview;
    ArrayAdapter<String> mAdapter;
    List<String> mData = new ArrayList<String>();
    GHandler handler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.refresh);
        initData();
        handler = new GHandler();
        listview = (RefreshListView) findViewById(R.id.refresh);
        listview.setOnRefreshListener(RefreshActivity.this);
        mAdapter = new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_1, android.R.id.text1,
                mData);
        listview.setAdapter(mAdapter);
    }
    
    private void initData(){
        for(int i=0;i<10;i++){
            mData.add("mRefreshView:"+i);
        }
    }
    
    class GHandler extends Handler{
        @Override
        public void handleMessage(Message msg) {
            if(msg.what == 1){
                mAdapter.notifyDataSetChanged();
                listview.onRefreshComplete();
            }
        }
    }

    @Override
    public void onRefresh() {
        new Thread(){
            @Override
            public void run() {
                for(int i=10;i<20;i++){
                    mData.add(0, "mRefreshView:"+i);
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    
                }
                
                handler.sendEmptyMessage(1);
            }
        }.start();
        
        
    }

}


该activity的布局是一个RefreshView的布局,即继承的那个布局


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值