mysql下拉刷新加载数据_listView下拉刷新加载数据

后面的很多例子应该都是仿照这个写的,下面的这个例子就是对这个例子的修改,先看下一个点击的效果,我看到其他的分析博客里面没有谈到这一点,在这个代码中,我们一直看到是listview的第二项,而listview的第一项被遮挡了起来,滑动至第一项:

0_1331022985QLFF.gif

点击头条,头条会变成以下:

0_1331023226H0b1.gif

然后,过一段时间,刷新完成以后,listview又setSelection(1),增加一条数据,同时,把顶部给遮挡住:

0_13310234776IAH.gif

这是点击刷新,然后是下拉刷新:

0_1331023647u02O.gif

0_1331023712dNH3.gif

最后结果和点击刷新相同。那现在开始看下代码:

首先看下所用到的控件和变量:

// 状态

privatestaticfinalintTAP_TO_REFRESH =1;//点击刷新

privatestaticfinalintPULL_TO_REFRESH =2;//拉动刷新

privatestaticfinalintRELEASE_TO_REFRESH =3;//释放刷新

privatestaticfinalintREFRESHING =4;//正在刷新

// 当前滑动状态

privateintmCurrentScrollState;

// 当前刷新状态

privateintmRefreshState;

//头视图的高度

privateintmRefreshViewHeight;

//头视图 原始的top padding 属性值

privateintmRefreshOriginalTopPadding;

privateintmLastMotionY;

// 监听对listview的滑动动作

privateOnRefreshListener mOnRefreshListener;

//箭头图片

privatestaticintREFRESHICON = R.drawable.goicon;

//listview 滚动监听器

privateOnScrollListener mOnScrollListener;

privateLayoutInflater mInflater;

privateRelativeLayout mRefreshView;

//顶部刷新时出现的控件

privateTextView mRefreshViewText;

privateImageView mRefreshViewImage;

privateProgressBar mRefreshViewProgress;

privateTextView mRefreshViewLastUpdated;

// 箭头动画效果

//变为向下的箭头

privateRotateAnimation mFlipAnimation;

//变为逆向的箭头

privateRotateAnimation mReverseFlipAnimation;

//是否反弹

privatebooleanmBounceHack;

看下点击刷新的代码过程:

在init()方法中初始化各个控件及设置监听:

privatevoidinit(Context context) {

// Load all of the animations we need in code rather than through XML

mFlipAnimation = newRotateAnimation(0, -180,RotateAnimation.RELATIVE_TO_SELF,

0.5f,RotateAnimation.RELATIVE_TO_SELF,0.5f);

mFlipAnimation.setInterpolator(newLinearInterpolator());

mFlipAnimation.setDuration(250);

mFlipAnimation.setFillAfter(true);

mReverseFlipAnimation = newRotateAnimation(-180,0,RotateAnimation.RELATIVE_TO_SELF,0.5f,RotateAnimation.RELATIVE_TO_SELF,0.5f);

mReverseFlipAnimation.setInterpolator(newLinearInterpolator());

mReverseFlipAnimation.setDuration(250);

mReverseFlipAnimation.setFillAfter(true);

mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

mRefreshView = (RelativeLayout) mInflater.inflate(R.layout.pull_to_refresh_header, this,false);

mRefreshViewText =(TextView) mRefreshView.findViewById(R.id.pull_to_refresh_text);

mRefreshViewImage =(ImageView) mRefreshView.findViewById(R.id.pull_to_refresh_image);

mRefreshViewProgress =(ProgressBar) mRefreshView.findViewById(R.id.pull_to_refresh_progress);

mRefreshViewLastUpdated =(TextView) mRefreshView.findViewById(R.id.pull_to_refresh_updated_at);

mRefreshViewImage.setMinimumHeight(50);

mRefreshView.setOnClickListener(newOnClickRefreshListener());

mRefreshOriginalTopPadding = mRefreshView.getPaddingTop();

mRefreshState = TAP_TO_REFRESH;

//为listview头部增加一个view

addHeaderView(mRefreshView);

super.setOnScrollListener(this);

measureView(mRefreshView);

mRefreshViewHeight = mRefreshView.getMeasuredHeight();

}

我们看到,mRefreshView控件既是listview用于刷新的头控件,这里它设置了监听事件:

mRefreshView.setOnClickListener(newOnClickRefreshListener());

我们再来看下监听事件的定义:

privateclassOnClickRefreshListenerimplementsOnClickListener {

@Override

publicvoidonClick(View v) {

if(mRefreshState != REFRESHING) {

prepareForRefresh();

onRefresh();

}

}

}

调用了preparForRefresh()(准备刷新)和onRefresh()(刷新)两个方法,然后在查看这两个方法的定义:

publicvoidprepareForRefresh() {

resetHeaderPadding();   // 恢复header的边距

mRefreshViewImage.setVisibility(View.GONE);

// We need this hack, otherwise it will keep the previous drawable.

// 注意加上,否则仍然显示之前的图片

mRefreshViewImage.setImageDrawable(null);

mRefreshViewProgress.setVisibility(View.VISIBLE);

// Set refresh view text to the refreshing label

mRefreshViewText.setText(R.string.pull_to_refresh_refreshing_label);

mRefreshState = REFRESHING;

}

publicvoidonRefresh() {

if(mOnRefreshListener !=null) {

mOnRefreshListener.onRefresh();

}

}

其中,后者还是回调方法。

我们看下preparForRefresh()方法中,引用了resetHeadPadding()方法:

/**

* Sets the header padding back to original size.

* 将head的边距重置为初始的数值

*/

privatevoidresetHeaderPadding() {

mRefreshView.setPadding(

mRefreshView.getPaddingLeft(),

mRefreshOriginalTopPadding,

mRefreshView.getPaddingRight(),

mRefreshView.getPaddingBottom());

}

从新设置下header距上下左右的距离。

最重要的方法应该是:onScroll()和onTouchEvent()方法,先看下onTouchEvent()方法:

@Override

publicbooleanonTouchEvent(MotionEvent event) {

//当前手指的Y值

finalinty = (int) event.getY();

mBounceHack = false;

switch(event.getAction()) {

caseMotionEvent.ACTION_UP:

//将垂直滚动条设置为可用状态

if(!isVerticalScrollBarEnabled()) {

setVerticalScrollBarEnabled(true);

}

if(getFirstVisiblePosition() ==0&& mRefreshState != REFRESHING) {

// 拖动距离达到刷新需要

if((mRefreshView.getBottom() >= mRefreshViewHeight

|| mRefreshView.getTop() >= 0)

&& mRefreshState == RELEASE_TO_REFRESH) {

// 把状态设置为正在刷新

// Initiate the refresh

mRefreshState = REFRESHING; //将标量设置为,正在刷新

// 准备刷新

prepareForRefresh();

// 刷新

onRefresh();

} elseif(mRefreshView.getBottom() 

|| mRefreshView.getTop() <= 0) {

// Abort refresh and scroll down below the refresh view

//停止刷新,并且滚动到头部刷新视图的下一个视图

resetHeader();

setSelection(1);//定位在第二个列表项

}

}

break;

caseMotionEvent.ACTION_DOWN:

// 获得按下y轴位置

mLastMotionY = y;

break;

caseMotionEvent.ACTION_MOVE:

//更行头视图的toppadding 属性

applyHeaderPadding(event);

break;

}

returnsuper.onTouchEvent(event);

}

当按下的时候,记录按下y轴的位置,然后在move中调用了applyHeaderPadding()方法,我们再看下这个方法:

// 获得header距离

privatevoidapplyHeaderPadding(MotionEvent ev) {

//获取累积的动作数

intpointerCount = ev.getHistorySize();

for(intp =0; p 

//如果是释放将要刷新状态

if(mRefreshState == RELEASE_TO_REFRESH) {

if(isVerticalFadingEdgeEnabled()) {

setVerticalScrollBarEnabled(false);

}

//历史累积的高度

inthistoricalY = (int) ev.getHistoricalY(p);

// Calculate the padding to apply, we divide by 1.7 to

// simulate a more resistant effect during pull.

// 计算申请的边距,除以1.7使得拉动效果更好

inttopPadding = (int) (((historicalY - mLastMotionY)- mRefreshViewHeight) /1.7);

mRefreshView.setPadding(

mRefreshView.getPaddingLeft(),

topPadding,

mRefreshView.getPaddingRight(),

mRefreshView.getPaddingBottom());

}

}

}

通过记录滑动距离,实时变化头部mRefreshView的上下左右的距离。

最后,看下手指松开的ACTION_UP:

caseMotionEvent.ACTION_UP:

//将垂直滚动条设置为可用状态

if(!isVerticalScrollBarEnabled()) {

setVerticalScrollBarEnabled(true);

}

if(getFirstVisiblePosition() ==0&& mRefreshState != REFRESHING) {

// 拖动距离达到刷新需要

if((mRefreshView.getBottom() >= mRefreshViewHeight

|| mRefreshView.getTop() >= 0)

&& mRefreshState == RELEASE_TO_REFRESH) {

// 把状态设置为正在刷新

// Initiate the refresh

mRefreshState = REFRESHING; //将标量设置为:正在刷新

// 准备刷新

prepareForRefresh();

// 刷新

onRefresh();

} elseif(mRefreshView.getBottom() 

|| mRefreshView.getTop() <= 0) {

// Abort refresh and scroll down below the refresh view

//停止刷新,并且滚动到头部刷新视图的下一个视图

resetHeader();

setSelection(1);//定位在第二个列表项

}

}

break;

当滑动距离大于一个item的距离时,添加一个item,否则,弹回。

看完onTouchEvent(),然后再看一下onScroll()方法:

@Override

publicvoidonScroll(AbsListView view,intfirstVisibleItem,intvisibleItemCount,inttotalItemCount) {

// When the refresh view is completely visible, change the text to say

// "Release to refresh..." and flip the arrow drawable.

// 在refreshview完全可见时,设置文字为松开刷新,同时翻转箭头

//如果是接触滚动状态,并且不是正在刷新的状态

if(mCurrentScrollState == SCROLL_STATE_TOUCH_SCROLL&& mRefreshState != REFRESHING) {

if(firstVisibleItem ==0) {

//如果显示出来了第一个列表项,显示刷新图片

mRefreshViewImage.setVisibility(View.VISIBLE);

//如果下拉了listiview,则显示上拉刷新动画

if((mRefreshView.getBottom() >= mRefreshViewHeight +20|| mRefreshView.getTop() >=0)

&& mRefreshState != RELEASE_TO_REFRESH) {

mRefreshViewText.setText(R.string.pull_to_refresh_release_label);

mRefreshViewImage.clearAnimation();

mRefreshViewImage.startAnimation(mFlipAnimation);

mRefreshState = RELEASE_TO_REFRESH;

//如果下拉距离不够,则回归原来的状态

} elseif(mRefreshView.getBottom() 

&& mRefreshState != PULL_TO_REFRESH) {

mRefreshViewText.setText(R.string.pull_to_refresh_pull_label);

if(mRefreshState != TAP_TO_REFRESH) {

mRefreshViewImage.clearAnimation();

mRefreshViewImage.startAnimation(mReverseFlipAnimation);

}

mRefreshState = PULL_TO_REFRESH;

}

} else{

mRefreshViewImage.setVisibility(View.GONE);

resetHeader();

}

//如果是滚动状态+ 第一个视图已经显示+ 不是刷新状态

} elseif(mCurrentScrollState == SCROLL_STATE_FLING  && firstVisibleItem ==0

&& mRefreshState != REFRESHING) {

setSelection(1);

mBounceHack = true;

} elseif(mBounceHack && mCurrentScrollState == SCROLL_STATE_FLING) {

setSelection(1);

}

if(mOnScrollListener !=null) {

mOnScrollListener.onScroll(view, firstVisibleItem,visibleItemCount, totalItemCount);

}

}

该方法是在滑动过程中,各种状况的处理。

onScroll()方法和onTouchEvent()方法的执行过程应该是,先onTouchEvent()的ACTION_DOWN,然后是ACTION_MOVE和onScroll()方法同时进行,最后是onTouchEvent()的ACTION_UP。也可以自己打log看一下。这样在onTouchEvent()处理header,就是mRefreshView的外部的各个熟悉,onScroll()里面处理header(mRefreshView)里面内部的控件变化,从逻辑上来说比较清晰。

在onScroll()中,引用方法resetHeader()方法:

/**

* Resets the header to the original state.

* 重置header为之前的状态

*/

privatevoidresetHeader() {

if(mRefreshState != TAP_TO_REFRESH) {

mRefreshState = TAP_TO_REFRESH;

resetHeaderPadding();

// 将刷新图标换成箭头

// Set refresh view text to the pull label

mRefreshViewText.setText(R.string.pull_to_refresh_tap_label);

// Replace refresh drawable with arrow drawable

// 清除动画

mRefreshViewImage.setImageResource(REFRESHICON);

// Clear the full rotation animation

mRefreshViewImage.clearAnimation();

// Hide progress bar and arrow.

// 隐藏图标和进度条

mRefreshViewImage.setVisibility(View.GONE);

mRefreshViewProgress.setVisibility(View.GONE);

}

}

resetHead就是header(mRefreshView)的内部的具体操作。

当一切都完成以后,就可以调用onRefreshComplete()方法:

/**

* Resets the list to a normal state after a refresh.

* 重置listview为普通的listview

* @param lastUpdated

* Last updated at.

*/

publicvoidonRefreshComplete(CharSequence lastUpdated) {

setLastUpdated(lastUpdated);

onRefreshComplete();

}

/**

* Resets the list to a normal state after a refresh.

* 重置listview为普通的listview,

*/

publicvoidonRefreshComplete() {

resetHeader();

// If refresh view is visible when loading completes, scroll down to

// the next item.

if(mRefreshView.getBottom() >0) {

invalidateViews();  //重绘视图

setSelection(1);

}

}

重新绘制listivew,然后setSelection(1)。完成!

来源:http://www.bozhiyue.com/anroid/boke/2016/0318/3589.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值