下拉刷新

最近学习了下拉刷新的方法,写在这里做个笔记,也跟大家分享一下。



<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2011 Johan Nilsson <http://markupartist.com>

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center"
android:paddingBottom="15dip"
android:paddingTop="10dip" >

<!-- 小型圆形进度条,初始为不可见 -->

<ProgressBar
android:id="@+id/pull_to_refresh_progress"
style="?android:attr/progressBarStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="30dip"
android:layout_marginRight="20dip"
android:layout_marginTop="10dip"
android:indeterminate="true"
android:visibility="gone" />
<!-- 下拉刷新的那个箭头 -->

<ImageView
android:id="@+id/pull_to_refresh_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="30dip"
android:layout_marginRight="20dip"
android:gravity="center"
android:src="@drawable/ic_pulltorefresh_arrow"
android:visibility="gone" />
<!-- 下拉刷新的提示文本 -->

<TextView
android:id="@+id/pull_to_refresh_text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:paddingTop="5dip"
android:text="@string/pull_to_refresh_tap_label"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textStyle="bold" />

<TextView
android:id="@+id/pull_to_refresh_updated_at"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/pull_to_refresh_text"
android:layout_gravity="center"
android:gravity="center"
android:textAppearance="?android:attr/textAppearanceSmall"
android:visibility="gone" />

</RelativeLayout>





<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="5sp"
android:layout_marginRight="5sp"
android:orientation="horizontal" >

<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:orientation="vertical" >

<TextView
android:id="@+id/mycourse_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:singleLine="true"
android:text="001"
android:visibility="gone"
android:textSize="14sp" />

<TextView
android:id="@+id/mycourse_class_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="小苹果速成2班"
android:textColor="#475de0"
android:textSize="12sp" />
</LinearLayout>

<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical" >

<TextView
android:id="@+id/mycourse_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:text="《小苹果是怎么炼成的10》"
android:textSize="22sp" />

<TextView
android:id="@+id/mycourese_active"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:layout_marginRight="22sp"
android:text="已购"
android:textColor="#9ec762"
android:textSize="10sp" />
</LinearLayout>

<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:orientation="vertical" >

<TextView
android:id="@+id/mycourse_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_gravity="center"
android:layout_marginTop="4sp"
android:gravity="center"
android:text="每周三下午第7节"
android:textColor="#e09647"
android:textSize="12sp" />
</LinearLayout>
</LinearLayout>

</RelativeLayout>






<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/loadmore_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:paddingBottom="15dip"
android:paddingTop="10dip" >

<!-- <Button
android:id="@+id/loadmore_btn"
android:layout_width="match_parent"
android:layout_height="60.0dip"
android:layout_centerHorizontal="true"
android:layout_marginTop="0.0dip"
android:background="@drawable/weibo_list_item_selector"
android:text="@string/loadmore_label"
android:textColor="@color/loadmore_btn_selector"
android:textSize="18.0sp" />
-->
<ProgressBar
android:id="@+id/loadmore_progress"
style="?android:attr/progressBarStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="30dip"
android:layout_marginRight="20dip"
android:layout_marginTop="10dip"
android:indeterminate="true"
android:visibility="gone" />

<TextView
android:id="@+id/loadmore_text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:paddingTop="5dip"
android:text="@string/loadmore_label"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textStyle="bold" />

</RelativeLayout>





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

<com.example.testpulltorefreshlistview.views.PullToRefreshListView
android:id="@+id/academy_mycourse_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:cacheColorHint="#00000000"
android:divider="#19000000"
android:dividerHeight="4dp"
android:fadingEdge="none"
android:fastScrollEnabled="false"
android:footerDividersEnabled="true"
android:headerDividersEnabled="false"
android:smoothScrollbar="true" />

</LinearLayout>



MainActivity 类



package com.example.testpulltorefreshlistview;

import java.util.List;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Menu;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Toast;

import com.example.testpulltorefreshlistview.adapter.MyCourseAdapter;
import com.example.testpulltorefreshlistview.bean.MyCourseBean;
import com.example.testpulltorefreshlistview.constants.Constants;
import com.example.testpulltorefreshlistview.util.GetTime;
import com.example.testpulltorefreshlistview.views.PullToRefreshListView;
import com.example.testpulltorefreshlistview.views.PullToRefreshListView.OnRefreshListener;

/**
* 主界面
*@author Changel
*@version 2014.07.22.1
*
*/

public class MainActivity extends Activity {

private PullToRefreshListView myListView = null;
private List<MyCourseBean> myList = null;
private MyCourseAdapter myAdapter = null;
private Handler mHandler;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

mHandler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case 0x123:
myList = (List<MyCourseBean>) msg.obj;
//设置适配器,刷新列表
myAdapter = new MyCourseAdapter(MainActivity.this, myList);
myListView.setAdapter(myAdapter);
break;

case 0x124:
myList = (List<MyCourseBean>) msg.obj;
//设置适配器,刷新列表
myAdapter = new MyCourseAdapter(MainActivity.this, myList);
myListView.setAdapter(myAdapter);
Toast.makeText(MainActivity.this, "刷新成功", Toast.LENGTH_SHORT).show();
myListView.onRefreshComplete(GetTime.getLocalTime());
break;
case 0x125:
myList = (List<MyCourseBean>) msg.obj;
//设置适配器,刷新列表
myAdapter = new MyCourseAdapter(MainActivity.this, myList);
myListView.setAdapter(myAdapter);
Toast.makeText(MainActivity.this, "加载成功", Toast.LENGTH_SHORT).show();
myListView.onRefreshComplete(GetTime.getLocalTime());
myListView.onLoadMoreComplete();
break;
}
}
};
//初始化界面
initListView();
//启动异步线程加载数据
new LoadMyCourseAsyncTask(MainActivity.this, Constants.FIRST_LOAD, mHandler).execute();

}

/**
* 初始化界面
* 绑定下拉刷新和加载更多的监听器
*
* */

public void initListView() {
myListView = (PullToRefreshListView) findViewById(R.id.academy_mycourse_list);
myListView.setOnItemClickListener(new OnItemClickListener() {

@Override
public void onItemClick(AdapterView<?> parent, View view,
int positon, long arg3) {
//点击每一项触发的方法
Toast.makeText(MainActivity.this, "单项点击!", positon-1).show();
}

});

myListView.setOnRefreshListener(new OnRefreshListener() {

@Override
//下拉时触发的方法
public void onRefresh() {

new LoadMyCourseAsyncTask(MainActivity.this, Constants.REFRESH, mHandler).execute();

}

@Override
//点击加载更多触发的方法
public void onLoadMore() {

new LoadMyCourseAsyncTask(MainActivity.this, Constants.MORE_LOAD, mHandler).execute();

}
});
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}

}



LoadMyCourseAsyncTask 类



package com.example.testpulltorefreshlistview;

import java.util.List;

import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;

import com.example.testpulltorefreshlistview.bean.MyCourseBean;
import com.example.testpulltorefreshlistview.constants.Constants;
import com.example.testpulltorefreshlistview.util.InitData;

/**
*
* 继承AsyncTask类,用异步线程来加载数据,在向主界面发送加载的信息
*
* @author Changel<373386733@qq.com>
* @version 2014.07.22.1
*
*/

public class LoadMyCourseAsyncTask extends
AsyncTask<String, Integer, List<MyCourseBean>> {
private Context context;
private int flag;
private Handler mHandler;
private ProgressDialog progressDialog;

public LoadMyCourseAsyncTask(Context context, int flag, Handler mHandler) {
this.context = context;
this.flag = flag;
this.mHandler = mHandler;
}

@Override
protected void onPostExecute(List<MyCourseBean> result) {

Message msg = Message.obtain();

msg.obj = result;
msg.what = flag;
mHandler.sendMessage(msg);

if (flag == Constants.FIRST_LOAD) {
progressDialog.dismiss();
}

}

@Override
protected void onPreExecute() {
if (flag == Constants.FIRST_LOAD) {

progressDialog = new ProgressDialog(context);
progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);// 设置进度条的模型,有矩形,圆圈等
progressDialog.setMessage("正在获取数据");
progressDialog.onStart();
progressDialog.show();
}
}

@Override
protected List<MyCourseBean> doInBackground(String... params) {
List<MyCourseBean> myCourseList = new InitData().getCourseData();
return myCourseList;

}
}



InitData 类



package com.example.testpulltorefreshlistview.util;

import java.util.ArrayList;
import java.util.List;
import com.example.testpulltorefreshlistview.bean.MyCourseBean;


/**
*
* 模拟数据
*
* @author Changel<373386733@qq.com>
* @version 2014.07.22.1
*
*/
public class InitData {

private static int i,isum;

public List<MyCourseBean> getCourseData(){

List<MyCourseBean> list ;
list = new ArrayList<MyCourseBean>();
isum = isum + 15;
for (i=1; i < isum; i++) {
MyCourseBean myCourseBean = new MyCourseBean();
myCourseBean.setmClassName("速成班"+i+"班");
myCourseBean.setmCourseActive("已购买");
myCourseBean.setmCourseDate("每周三"+"第"+i+"节");
myCourseBean.setmCourseName("《"+"小苹果是怎么炼成的"+i+"》");
myCourseBean.setmCourseId(" "+i);
list.add(myCourseBean);
}

//模拟网络加载过程
for (int i = 0; i < 2; i++) {

try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

return list;
}

}


MyCourseAdapter类



package com.example.testpulltorefreshlistview.adapter;

import java.util.List;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import com.example.testpulltorefreshlistview.R;
import com.example.testpulltorefreshlistview.bean.MyCourseBean;


/**
*
* 继承BaseAdapter基类,构造一个Adapter来显示list的内容
*
* @author Changel<373386733@qq.com>
* @version 2014.07.22.1
*
*/

public class MyCourseAdapter extends BaseAdapter{

private List<MyCourseBean> list ;
private LayoutInflater inflater;
private Context context;

public MyCourseAdapter(Context context ,List<MyCourseBean> list){

this.context = context;
this.list = list;
inflater=LayoutInflater.from(context);
}

@Override
public int getCount() {
// TODO Auto-generated method stub
return list.size();
}

@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return list.get(position);
}

@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
ViewHolder viewHolder;
if(convertView==null){
convertView=inflater.inflate(R.layout.my_course_item, null);
viewHolder = new ViewHolder(convertView);
convertView.setTag(viewHolder);
}else{
viewHolder=(ViewHolder) convertView.getTag();
}
//将myCourseBean的信息显示在list上
MyCourseBean myCourseBean = list.get(position);
viewHolder.getCourseIdTextView().setText(myCourseBean.getmCourseId());
viewHolder.getDateTextView().setText(myCourseBean.getmCourseDate());
viewHolder.getClassNameTextView().setText(myCourseBean.getmClassName());
viewHolder.getCourseNameTextView().setText(myCourseBean.getmCourseName());
viewHolder.getActiveTextView().setText(myCourseBean.getmCourseActive());

return convertView;
}

/**
*
* 初始化MyCourseAdapter
*
*/

class ViewHolder{

TextView idTextView;
TextView dateTextView;
TextView courseNameTextView;
TextView classNameTextView;
TextView activeTextView;
ImageView image;
View view;

public ViewHolder(View view){

this.view = view;
}

public TextView getCourseIdTextView(){
if(idTextView == null){
idTextView = (TextView)view.findViewById(R.id.mycourse_id);
}
return idTextView;
}
public TextView getDateTextView(){
if(dateTextView == null){
dateTextView = (TextView)view.findViewById(R.id.mycourse_date);
}
return dateTextView;
}
public TextView getCourseNameTextView(){
if(courseNameTextView == null){
courseNameTextView = (TextView)view.findViewById(R.id.mycourse_name);
}
return courseNameTextView;
}
public TextView getClassNameTextView(){
if(classNameTextView == null){
classNameTextView = (TextView)view.findViewById(R.id.mycourse_class_name);
}
return classNameTextView;
}
public TextView getActiveTextView(){
if(activeTextView == null){
activeTextView = (TextView)view.findViewById(R.id.mycourese_active);
}
return activeTextView;
}
}
}




GetTime类


package com.example.testpulltorefreshlistview.util;

import java.net.URL;
import java.net.URLConnection;
import java.text.SimpleDateFormat;
import java.util.Date;


/**
*
* 创建一个获取时间的Util,用于获取更新的时间
*
* @author Changel<373386733@qq.com>
* @version 2014.07.22.1
*
*/
public class GetTime {

private static String timeString = null;
//获取网络时间
public static String getNetTime() throws Exception{
//取得资源对象
URL url = new URL("http://www.bjtime.cn");
//生成连接对象
URLConnection uc = url.openConnection();
//发出连接
uc.connect();
long time = uc.getDate();
Date date = new Date(time);
timeString = new SimpleDateFormat("yyyy-MM-dd").format(date).toString();
return timeString;
}

//获取本地时间
public static String getLocalTime(){

SimpleDateFormat sm=new SimpleDateFormat("yyyy-MM-dd");
timeString = sm.format(new Date()).toString();
System.out.println(timeString);
return timeString;
}
}



Constants类



package com.example.testpulltorefreshlistview.constants;

public class Constants {

public final static int FIRST_LOAD = 0x123;
public final static int REFRESH = 0x124;
public final static int MORE_LOAD = 0x125;

}



PullToRefreshListView类 (此类不是自己写的)


package com.example.testpulltorefreshlistview.views;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

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.AbsListView.OnScrollListener;
import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.example.testpulltorefreshlistview.R;

/**
* 自定义ListView,实现OnScrollListener接口
* 此ListView是为实现"下拉刷新"和"上拉加载更多"而定制的,具体效果可参考新浪微博、腾讯微博
*
*/
public class PullToRefreshListView extends ListView implements OnScrollListener {

private static final int TAP_TO_REFRESH = 1; // (未刷新)
private static final int PULL_TO_REFRESH = 2; // 下拉刷新
private static final int RELEASE_TO_REFRESH = 3; // 释放刷新
private static final int REFRESHING = 4; // 正在刷新
private static final int TAP_TO_LOADMORE = 5; // 未加载更多
private static final int LOADING = 6; // 正在加载

private static final String TAG = "PullToRefreshListView";

private OnRefreshListener mOnRefreshListener; // 刷新监听器

/**
* Listener that will receive notifications every time the list scrolls.
*/
private OnScrollListener mOnScrollListener; // 列表滚动监听器
private LayoutInflater mInflater; // 用于加载布局文件

private RelativeLayout mRefreshHeaderView; // 刷新视图(也就是头部那部分)
private TextView mRefreshViewText; // 刷新提示文本
private ImageView mRefreshViewImage; // 刷新向上向下的那个图片
private ProgressBar mRefreshViewProgress; // 这里是圆形进度条
private TextView mRefreshViewLastUpdated; // 最近更新的文本

private RelativeLayout mLoadMoreFooterView; // 加载更多
private TextView mLoadMoreText; // 提示文本
private ProgressBar mLoadMoreProgress; // 加载更多进度条

private int mCurrentScrollState; // 当前滚动位置
private int mRefreshState; // 刷新状态
private int mLoadState; // 加载状态

private RotateAnimation mFlipAnimation; // 下拉动画
private RotateAnimation mReverseFlipAnimation; // 恢复动画

private int mRefreshViewHeight; // 刷新视图高度
private int mRefreshOriginalTopPadding; // 原始上部间隙
private int mLastMotionY; // 记录点击位置

public PullToRefreshListView(Context context) {
super(context);
init(context);
}

public PullToRefreshListView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}

public PullToRefreshListView(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
init(context);
}

private void init(Context context) {
// Load all of the animations we need in code rather than through XML
/** 定义旋转动画 **/
// 参数:1.旋转开始的角度 2.旋转结束的角度 3. X轴伸缩模式 4.X坐标的伸缩值 5.Y轴的伸缩模式 6.Y坐标的伸缩值
mFlipAnimation = new RotateAnimation(0, -180,
RotateAnimation.RELATIVE_TO_SELF, 0.5f,
RotateAnimation.RELATIVE_TO_SELF, 0.5f);
mFlipAnimation.setInterpolator(new LinearInterpolator());
mFlipAnimation.setDuration(250); // 设置持续时间
mFlipAnimation.setFillAfter(true); // 动画执行完是否停留在执行完的状态
mReverseFlipAnimation = new RotateAnimation(-180, 0,
RotateAnimation.RELATIVE_TO_SELF, 0.5f,
RotateAnimation.RELATIVE_TO_SELF, 0.5f);
mReverseFlipAnimation.setInterpolator(new LinearInterpolator());
mReverseFlipAnimation.setDuration(250);
mReverseFlipAnimation.setFillAfter(true);

// 获取LayoutInflater实例对象
mInflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

// 加载下拉刷新的头部视图
mRefreshHeaderView = (RelativeLayout) mInflater.inflate(
R.layout.pull_to_refresh_header, this, false);
mRefreshViewText = (TextView) mRefreshHeaderView
.findViewById(R.id.pull_to_refresh_text);
mRefreshViewImage = (ImageView) mRefreshHeaderView
.findViewById(R.id.pull_to_refresh_image);
mRefreshViewProgress = (ProgressBar) mRefreshHeaderView
.findViewById(R.id.pull_to_refresh_progress);
mRefreshViewLastUpdated = (TextView) mRefreshHeaderView
.findViewById(R.id.pull_to_refresh_updated_at);
mLoadMoreFooterView = (RelativeLayout) mInflater.inflate(
R.layout.loadmore_footer, this, false);
mLoadMoreText = (TextView) mLoadMoreFooterView
.findViewById(R.id.loadmore_text);
mLoadMoreProgress = (ProgressBar) mLoadMoreFooterView
.findViewById(R.id.loadmore_progress);

mRefreshViewImage.setMinimumHeight(50); // 设置图片最小高度
mRefreshHeaderView.setOnClickListener(new OnClickRefreshListener());
mRefreshOriginalTopPadding = mRefreshHeaderView.getPaddingTop();
mLoadMoreFooterView.setOnClickListener(new OnClickLoadMoreListener());

mRefreshState = TAP_TO_REFRESH; // 初始刷新状态
mLoadState = TAP_TO_LOADMORE;

addHeaderView(mRefreshHeaderView); // 增加头部视图
addFooterView(mLoadMoreFooterView); // 增加尾部视图

super.setOnScrollListener(this);

measureView(mRefreshHeaderView); // 测量视图
mRefreshViewHeight = mRefreshHeaderView.getMeasuredHeight(); // 得到视图的高度
}

@Override
protected void onAttachedToWindow() {
setSelection(1); // 设置当前选中的项
}

@Override
public void setAdapter(ListAdapter adapter) {
super.setAdapter(adapter);

setSelection(1);
}

/**
* Set the listener that will receive notifications every time the list
* scrolls.
*
* @param l
* The scroll listener.
*/
@Override
public void setOnScrollListener(AbsListView.OnScrollListener l) {
mOnScrollListener = l;
}

/**
* Register a callback to be invoked when this list should be refreshed.
* 注册监听器
*
* @param onRefreshListener
* The callback to run.
*/
public void setOnRefreshListener(OnRefreshListener onRefreshListener) {
mOnRefreshListener = onRefreshListener;
}

/**
* Set a text to represent when the list was last updated.
* 设置一个文本来表示最近更新的列表,显示的是最近更新列表的时间
*
* @param lastUpdated
* Last updated at.
*/
public void setLastUpdated(CharSequence lastUpdated) {
if (lastUpdated != null) {
mRefreshViewLastUpdated.setVisibility(View.VISIBLE);
mRefreshViewLastUpdated.setText("更新于: " + lastUpdated);
} else {
mRefreshViewLastUpdated.setVisibility(View.GONE);
}
}

@Override
public boolean onTouchEvent(MotionEvent event) {
final int y = (int) event.getY(); // 获取点击位置的Y坐标

switch (event.getAction()) {
case MotionEvent.ACTION_UP: // 手指抬起
if (!isVerticalScrollBarEnabled()) {
setVerticalScrollBarEnabled(true);
}
if (getFirstVisiblePosition() == 0 && mRefreshState != REFRESHING) {
if ((mRefreshHeaderView.getBottom() > mRefreshViewHeight || mRefreshHeaderView
.getTop() >= 0) && mRefreshState == RELEASE_TO_REFRESH) {
// Initiate the refresh
mRefreshState = REFRESHING; // 刷新状态
prepareForRefresh();
onRefresh();
} else if (mRefreshHeaderView.getBottom() < mRefreshViewHeight
|| mRefreshHeaderView.getTop() < 0) {
// Abort refresh and scroll down below the refresh view
resetHeader();
setSelection(1);
}
}
break;
case MotionEvent.ACTION_DOWN:
mLastMotionY = y;
break;
case MotionEvent.ACTION_MOVE:
applyHeaderPadding(event);
break;
}
return super.onTouchEvent(event);
}

private void applyHeaderPadding(MotionEvent ev) {
final int historySize = ev.getHistorySize();

// Workaround for getPointerCount() which is unavailable in 1.5
// (it's always 1 in 1.5)
int pointerCount = 1;
try {
Method method = MotionEvent.class.getMethod("getPointerCount");
pointerCount = (Integer) method.invoke(ev);
} catch (NoSuchMethodException e) {
pointerCount = 1;
} catch (IllegalArgumentException e) {
throw e;
} catch (IllegalAccessException e) {
System.err.println("unexpected " + e);
} catch (InvocationTargetException e) {
System.err.println("unexpected " + e);
}

for (int h = 0; h < historySize; h++) {
for (int p = 0; p < pointerCount; p++) {
if (mRefreshState == RELEASE_TO_REFRESH) {
if (isVerticalFadingEdgeEnabled()) {
setVerticalScrollBarEnabled(false);
}

int historicalY = 0;
try {
// For Android > 2.0
Method method = MotionEvent.class.getMethod(
"getHistoricalY", Integer.TYPE, Integer.TYPE);
historicalY = ((Float) method.invoke(ev, p, h))
.intValue();
} catch (NoSuchMethodException e) {
// For Android < 2.0
historicalY = (int) (ev.getHistoricalY(h));
} catch (IllegalArgumentException e) {
throw e;
} catch (IllegalAccessException e) {
System.err.println("unexpected " + e);
} catch (InvocationTargetException e) {
System.err.println("unexpected " + e);
}

// Calculate the padding to apply, we divide by 1.7 to
// simulate a more resistant effect during pull.
int topPadding = (int) (((historicalY - mLastMotionY) - mRefreshViewHeight) / 1.7);

// 设置上、下、左、右四个位置的间隙间隙
mRefreshHeaderView.setPadding(
mRefreshHeaderView.getPaddingLeft(), topPadding,
mRefreshHeaderView.getPaddingRight(),
mRefreshHeaderView.getPaddingBottom());
}
}
}
}

/**
* Sets the header padding back to original size. 设置头部填充会原始大小
*/
private void resetHeaderPadding() {
mRefreshHeaderView.setPadding(mRefreshHeaderView.getPaddingLeft(),
mRefreshOriginalTopPadding,
mRefreshHeaderView.getPaddingRight(),
mRefreshHeaderView.getPaddingBottom());
}

/**
* Resets the header to the original state. 重新设置头部为原始状态
*/
private void resetHeader() {
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(R.drawable.ic_pulltorefresh_arrow);
// Clear the full rotation animation
mRefreshViewImage.clearAnimation();
// Hide progress bar and arrow.
mRefreshViewImage.setVisibility(View.GONE);
mRefreshViewProgress.setVisibility(View.GONE);
}
}

/**
* 重设ListView尾部视图为初始状态
*/
private void resetFooter() {
if (mLoadState != TAP_TO_LOADMORE) {
mLoadState = TAP_TO_LOADMORE;

// 进度条设置为不可见
mLoadMoreProgress.setVisibility(View.GONE);
// 按钮的文本替换为“加载更多”
mLoadMoreText.setText(R.string.loadmore_label);
}

}

/**
* 测量视图的大小
*
* @param child
*/
private void measureView(View child) {
ViewGroup.LayoutParams p = child.getLayoutParams();
if (p == null) {
p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_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);
}

@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
// When the refresh view is completely visible, change the text to say
// "Release to refresh..." and flip the arrow drawable.
if (mCurrentScrollState == SCROLL_STATE_TOUCH_SCROLL
&& mRefreshState != REFRESHING) {
if (firstVisibleItem == 0) { // 如果第一个可见条目为0
mRefreshViewImage.setVisibility(View.VISIBLE); // 让指示箭头变得可见
/** 如果头部视图相对与父容器的位置大于其自身高度+20或者头部视图的顶部位置>0,并且要在刷新状态不等于"释放以刷新" **/
if ((mRefreshHeaderView.getBottom() > mRefreshViewHeight + 20 || mRefreshHeaderView
.getTop() >= 0) && mRefreshState != RELEASE_TO_REFRESH) {
mRefreshViewText
.setText(R.string.pull_to_refresh_release_label);// 设置刷新文本为"Release to refresh..."
mRefreshViewImage.clearAnimation(); // 清除动画
mRefreshViewImage.startAnimation(mFlipAnimation); // 启动动画
mRefreshState = RELEASE_TO_REFRESH; // 更改刷新状态为“释放以刷新"
} else if (mRefreshHeaderView.getBottom() < mRefreshViewHeight + 20
&& mRefreshState != PULL_TO_REFRESH) {
mRefreshViewText
.setText(R.string.pull_to_refresh_pull_label);// 设置刷新文本为"Pull to refresh..."
if (mRefreshState != TAP_TO_REFRESH) {
mRefreshViewImage.clearAnimation();
mRefreshViewImage.startAnimation(mReverseFlipAnimation);
}
mRefreshState = PULL_TO_REFRESH;
}
} else {
mRefreshViewImage.setVisibility(View.GONE); // 让刷新箭头不可见
resetHeader(); // 重新设置头部为原始状态
}
} else if (mCurrentScrollState == SCROLL_STATE_FLING
&& firstVisibleItem == 0 && mRefreshState != REFRESHING) {
setSelection(1);
}

if (mOnScrollListener != null) {
mOnScrollListener.onScroll(view, firstVisibleItem,
visibleItemCount, totalItemCount);
}
}

@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
mCurrentScrollState = scrollState;

if (mOnScrollListener != null) {
mOnScrollListener.onScrollStateChanged(view, scrollState);
}
}

/** 为刷新做准备 **/
public void prepareForRefresh() {
resetHeaderPadding();

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;
}

/** 为加载更多做准备 **/
public void prepareForLoadMore() {
mLoadMoreProgress.setVisibility(View.VISIBLE);
mLoadMoreText.setText(R.string.loading_label);
mLoadState = LOADING;
}

public void onRefresh() {
Log.d(TAG, "onRefresh");

if (mOnRefreshListener != null) {
mOnRefreshListener.onRefresh();
}
}

public void OnLoadMore() {
Log.d(TAG, "onLoadMore");
if (mOnRefreshListener != null) {
mOnRefreshListener.onLoadMore();
}
}

/**
* Resets the list to a normal state after a refresh.
*
* @param lastUpdated
* Last updated at.
*/
public void onRefreshComplete(CharSequence lastUpdated) {
setLastUpdated(lastUpdated); // 显示更新时间
onRefreshComplete();
}

/**
* Resets the list to a normal state after a refresh.
*/
public void onRefreshComplete() {
Log.d(TAG, "onRefreshComplete");

resetHeader();

// If refresh view is visible when loading completes, scroll down to
// the next item.
if (mRefreshHeaderView.getBottom() > 0) {
invalidateViews();
setSelection(1);
}
}

public void onLoadMoreComplete() {
Log.d(TAG, "onLoadMoreComplete");
resetFooter();
}

/**
* Invoked when the refresh view is clicked on. This is mainly used when
* there's only a few items in the list and it's not possible to drag the
* list. 点击刷新
*/
private class OnClickRefreshListener implements OnClickListener {

@Override
public void onClick(View v) {
if (mRefreshState != REFRESHING) {
prepareForRefresh();
onRefresh();
}
}

}

/**
*
* 加载更多
*/
private class OnClickLoadMoreListener implements OnClickListener {

@Override
public void onClick(View v) {
if (mLoadState != LOADING) {
prepareForLoadMore();
OnLoadMore();
}
}
}

/**
* Interface definition for a callback to be invoked when list should be
* refreshed. 接口定义一个回调方法当列表应当被刷新
*/
public interface OnRefreshListener {
/**
* Called when the list should be refreshed. 当列表应当被刷新是调用这个方法
* <p>
* A call to {@link PullToRefreshListView #onRefreshComplete()} is
* expected to indicate that the refresh has completed.
*/
public void onRefresh();

public void onLoadMore();
}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值