values包下面
strings修改
"1.0" encoding="utf-8"?><string name="app_name">Pullstring> <string name="hello_world">Hello world!string> <string name="menu_settings">Settingsstring> <string name="head">这里是HeadViewstring> 下拉刷新 释放立即刷新 正在刷新... 刷新成功 刷新失败 上拉加载更多 释放立即加载 正在加载... 加载成功 加载失败
添一个color.xml 在这可以修改颜色
"1.0" encoding="utf-8"?>"white">#FFFFFF "black">#000000 "gray">#f00 "light_blue">#f00
在res文件夹下创个anim文件夹添加动画(两个)
/MainActivity/res/anim/reverse_anim.xml
"1.0" encoding="utf-8"?>"http://schemas.android.com/apk/res/android" android:duration="100" android:fillAfter="true" android:fromDegrees="0" android:pivotX="50%" android:pivotY="50%" android:repeatCount="0" android:toDegrees="180" >
/MainActivity/res/anim/rotating.xml
"1.0" encoding="utf-8"?>"http://schemas.android.com/apk/res/android" android:duration="1500" android:fillAfter="true" android:fromDegrees="0" android:pivotX="50%" android:pivotY="50%" android:repeatCount="-1" android:toDegrees="360" >
在res下layout下添加两部局
/MainActivity/res/layout/load_more.xml
"1.0" encoding="utf-8"?>"http://schemas.android.com/apk/res/android" android:id="@+id/loadmore_view" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/gray" > <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:paddingBottom="20dp" android:paddingTop="20dp" > <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerInParent="true" > <ImageView android:id="@+id/pullup_icon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_marginLeft="60dp" android:background="@drawable/pullup_icon_big" /> <ImageView android:id="@+id/loading_icon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_marginLeft="60dp" android:background="@drawable/loading" android:visibility="gone" /> <TextView android:id="@+id/loadstate_tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:text="@string/pullup_to_load" android:textColor="@color/black" android:textSize="16sp" /> <ImageView android:id="@+id/loadstate_iv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_marginRight="8dp" android:layout_toLeftOf="@id/loadstate_tv" android:visibility="gone" />
/MainActivity/res/layout/refresh_head.xml
"1.0" encoding="utf-8"?>"http://schemas.android.com/apk/res/android" android:id="@+id/head_view" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/light_blue" > <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:paddingBottom="20dp" android:paddingTop="20dp" > <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerInParent="true" > <ImageView android:id="@+id/pull_icon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_marginLeft="60dp" android:background="@drawable/pull_icon_big" /> <ImageView android:id="@+id/refreshing_icon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_marginLeft="60dp" android:background="@drawable/refreshing" android:visibility="gone" /> <TextView android:id="@+id/state_tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:text="@string/pull_to_refresh" android:textColor="@color/white" android:textSize="16sp" /> <ImageView android:id="@+id/state_iv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_marginRight="8dp" android:layout_toLeftOf="@id/state_tv" android:visibility="gone" />
修改/MainActivity/res/layout/activity_main.xml布局(注意红色包名)
<com.exaple.tong.PullToRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/layout" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" > <include layout="@layout/refresh_head" /> <com.exaple.tong.PullableListView android:id="@+id/listview" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:text="@string/hello_world" /> <include layout="@layout/load_more" /> com.exaple.tong.PullToRefreshLayout>
/MainActivity/res/layout/base.xml 子布局
"1.0" encoding="utf-8"?>"http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" > <ImageView android:id="@+id/image" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_launcher" /> <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="hhh" />
下面在src文件夹下
先创个com.exaple.tong包里面有三个类(固定的直接粘)
/MainActivity/src/com/exaple/tong/Pullable.java (1)
package com.exaple.tong; public interface Pullable { /** * 判断是否可以下拉,如果不需要下拉功能可以直接return false * * @return true如果可以下拉否则返回false */ boolean canPullDown(); /** * 判断是否可以上拉,如果不需要上拉功能可以直接return false * * @return true如果可以上拉否则返回false */ boolean canPullUp(); }
/MainActivity/src/com/exaple/tong/PullableListView.java (2)
package com.exaple.tong; import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.widget.ListView; public class PullableListView extends ListView implements Pullable { public PullableListView(Context context) { super(context); } public PullableListView(Context context, AttributeSet attrs) { super(context, attrs); } public PullableListView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override public boolean canPullDown() { if (getCount() == 0) { // 娌℃湁item鐨勬椂鍊欎篃鍙互涓嬫媺鍒锋柿 return true; } else if (getFirstVisiblePosition() == 0 && getChildAt(0).getTop() >= 0) { // 婊戝埌ListView鐨勯《閮ㄤ簡 return true; } else return false; } @Override public boolean canPullUp() { if (getCount() == 0) { // 娌℃湁item鐨勬椂鍊欎篃鍙互涓婃媺鍔犺浿 return true; } else if (getLastVisiblePosition() == (getCount() - 1)) { // 婊戝埌搴曢儴浜� if (getChildAt(getLastVisiblePosition() - getFirstVisiblePosition()) != null && getChildAt( getLastVisiblePosition() - getFirstVisiblePosition()).getBottom() <= getMeasuredHeight()) return true; } return false; } }
/MainActivity/src/com/exaple/tong/PullToRefreshLayout.java (3)
package com.exaple.tong; import java.util.Timer; import java.util.TimerTask; import com.exmple.pull.R; import android.app.Activity; import android.content.Context; import android.os.AsyncTask; import android.os.Handler; import android.os.Message; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.animation.AnimationUtils; import android.view.animation.LinearInterpolator; import android.view.animation.RotateAnimation; import android.widget.RelativeLayout; import android.widget.TextView; /** * 閼奉亜鐣炬稊澶屾畱鐢啫鐪敍宀�暏閺夈儳顓搁悶鍡曠瑏娑擃亜鐡欓幒褌娆㈤敍灞藉従娑擃厺绔存稉顏呮Ц娑撳濯烘径杈剧礉娑擄拷閲滈弰顖氬瘶閸氼偄鍞寸�鍦 * 畱pullableView閿涘牆褰叉禒銉︽Ц鐎圭偟骞嘝ullable閹恒儱褰涢惃鍕畱娴犺缍峍iew閿涘绱� * 鏉╂ɑ婀佹稉锟介嚋娑撳﹥濯烘径杈剧礉閺囨潙顦跨拠锕佇掔憴浣稿触鐎诡晭ttp * ://blog.csdn.net/zhongkejingwang/article/details/38868463 * * @author 闂勫牓娼� */ public class PullToRefreshLayout extends RelativeLayout { public static final String TAG = "PullToRefreshLayout"; // 閸掓繂顫愰悩鑸碉拷 public static final int INIT = 0; // 闁插﹥鏂侀崚閿嬫煀 public static final int RELEASE_TO_REFRESH = 1; // 濮濓絽婀崚閿嬫煀 public static final int REFRESHING = 2; // 闁插﹥鏂侀崝鐘烘祰 public static final int RELEASE_TO_LOAD = 3; // 濮濓絽婀崝鐘烘祰 public static final int LOADING = 4; // 閹垮秳缍旂�灞剧槸 public static final int DONE = 5; // 瑜版挸澧犻悩鑸碉拷 private int state = INIT; // 閸掗攱鏌婇崶鐐剁殶閹恒儱褰� private OnRefreshListener mListener; // 閸掗攱鏌婇幋鎰 public static final int SUCCEED = 0; // 閸掗攱鏌婃径杈Е public static final int FAIL = 1; // 閹稿绗匶閸ф劖鐖i敍灞肩瑐娑擄拷閲滄禍瀣╂閻愮瓬閸ф劖鐖� private float downY, lastY; // 娑撳濯洪惃鍕獩缁傛眹锟藉▔銊﹀壈閿涙ullDownY閸滃ullUpY娑撳秴褰查懗钘夋倱閺冩湹绗夋稉锟� public float pullDownY = 0; // 娑撳﹥濯洪惃鍕獩缁傦拷 private float pullUpY = 0; // 闁插﹥鏂侀崚閿嬫煀閻ㄥ嫯绐涚粋锟� private float refreshDist = 200; // 闁插﹥鏂侀崝鐘烘祰閻ㄥ嫯绐涚粋锟� private float loadmoreDist = 200; private MyTimer timer; // 閸ョ偞绮撮柅鐔峰 public float MOVE_SPEED = 8; // 缁楊兛绔村▎鈩冨⒔鐞涘苯绔风仦锟� private boolean isLayout = false; // 閸︺劌鍩涢弬鎷岀箖缁嬪鑵戝鎴濆З閹垮秳缍� private boolean isTouch = false; // 閹靛瀵氬鎴濆З鐠烘繄顬囨稉搴濈瑓閹峰銇旈惃鍕拨閸斻劏绐涚粋缁樼槷閿涘奔鑵戦梻缈犵窗闂呭繑顒滈崚鍥у毐閺佹澘褰夐崠锟� private float radio = 2; // 娑撳濯虹粻顓炪仈閻ㄥ嫯娴�80鎺抽崝銊ф暰 private RotateAnimation rotateAnimation; // 閸у洤瀵戦弮瀣祮閸斻劎鏁� private RotateAnimation refreshingAnimation; // 娑撳濯烘径锟� private View refreshView; // 娑撳濯洪惃鍕唲婢讹拷 private View pullView; // 濮濓絽婀崚閿嬫煀閻ㄥ嫬娴橀弽锟� private View refreshingView; // 閸掗攱鏌婄紒鎾寸亯閸ョ偓鐖� private View refreshStateImageView; // 閸掗攱鏌婄紒鎾寸亯閿涙碍鍨氶崝鐔稿灗婢惰精瑙� private TextView refreshStateTextView; // 娑撳﹥濯烘径锟� private View loadmoreView; // 娑撳﹥濯洪惃鍕唲婢讹拷 private View pullUpView; // 濮濓絽婀崝鐘烘祰閻ㄥ嫬娴橀弽锟� private View loadingView; // 閸旂姾娴囩紒鎾寸亯閸ョ偓鐖� private View loadStateImageView; // 閸旂姾娴囩紒鎾寸亯閿涙碍鍨氶崝鐔稿灗婢惰精瑙� private TextView loadStateTextView; // 鐎圭偟骞囨禍鍝杣llable閹恒儱褰涢惃鍒卛ew private View pullableView; // 鏉╁洦鎶ゆ径姘卞仯鐟欙妇顫� private int mEvents; // 鏉╂瑤琚辨稉顏勫綁闁插繒鏁ら弶銉﹀付閸掔ull閻ㄥ嫭鏌熼崥鎴礉婵″倹鐏夋稉宥呭閹貉冨煑閿涘苯缍嬮幆鍛枌濠娐ゅ喕閸欘垯绗傞幏澶婂嫉閸欘垯绗呴幏澶嬫濞屸剝纭舵稉瀣 private boolean canPullDown = true; private boolean canPullUp = true; private Context mContext; /** * 閹笛嗩攽閼奉亜濮╅崶鐐寸泊閻ㄥ埅andler */ Handler updateHandler = new Handler() { @Override public void handleMessage(Message msg) { // 閸ョ偛鑴婇柅鐔峰闂呭繋绗呴幏澶庣獩缁傜北oveDeltaY婢х偛銇囬懓灞筋杻婢讹拷 MOVE_SPEED = (float) (8 + 5 * Math.tan(Math.PI / 2 / getMeasuredHeight() * (pullDownY + Math.abs(pullUpY)))); if (!isTouch) { // 濮濓絽婀崚閿嬫煀閿涘奔绗栧▽鈩冩箒瀵帮拷绗傞幒銊ф畱鐠囨繂鍨幃顒�粻閿涘本妯夌粈锟藉锝呮躬閸掗攱鏌�.." if (state == REFRESHING && pullDownY <= refreshDist) { pullDownY = refreshDist; timer.cancel(); } else if (state == LOADING && -pullUpY <= loadmoreDist) { pullUpY = -loadmoreDist; timer.cancel(); } } if (pullDownY > 0) pullDownY -= MOVE_SPEED; else if (pullUpY < 0) pullUpY += MOVE_SPEED; if (pullDownY < 0) { // 瀹告彃鐣幋鎰礀瀵拷 pullDownY = 0; pullView.clearAnimation(); // 闂呮劘妫屾稉瀣婢跺瓨妞傞張澶婂讲閼冲�绻曢崷銊ュ煕閺傚府绱濋崣顏呮箒瑜版挸澧犻悩鑸碉拷娑撳秵妲稿锝呮躬閸掗攱鏌婇弮鑸靛閺�懓褰夐悩鑸碉拷 if (state != REFRESHING && state != LOADING) changeState(INIT); timer.cancel(); requestLayout(); } if (pullUpY > 0) { // 瀹告彃鐣幋鎰礀瀵拷 pullUpY = 0; pullUpView.clearAnimation(); // 闂呮劘妫屾稉濠冨婢跺瓨妞傞張澶婂讲閼冲�绻曢崷銊ュ煕閺傚府绱濋崣顏呮箒瑜版挸澧犻悩鑸碉拷娑撳秵妲稿锝呮躬閸掗攱鏌婇弮鑸靛閺�懓褰夐悩鑸碉拷 if (state != REFRESHING && state != LOADING) changeState(INIT); timer.cancel(); requestLayout(); } Log.d("handle", "handle"); // 閸掗攱鏌婄敮鍐ㄧ湰,娴兼俺鍤滈崝銊ㄧ殶閻⑩暙nLayout requestLayout(); // 濞屸剝婀侀幏鏍ㄥ閹存牞锟介崶鐐茶剨鐎瑰本鍨� if (pullDownY + Math.abs(pullUpY) == 0) timer.cancel(); } }; public void setOnRefreshListener(OnRefreshListener listener) { mListener = listener; } public PullToRefreshLayout(Context context) { super(context); initView(context); } public PullToRefreshLayout(Context context, AttributeSet attrs) { super(context, attrs); initView(context); } public PullToRefreshLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); initView(context); } private void initView(Context context) { mContext = context; timer = new MyTimer(updateHandler); rotateAnimation = (RotateAnimation) AnimationUtils.loadAnimation( context, R.anim.reverse_anim); refreshingAnimation = (RotateAnimation) AnimationUtils.loadAnimation( context, R.anim.rotating); // 濞h濮為崠锟斤拷鏉烆剙濮╅崝銊ф暰 LinearInterpolator lir = new LinearInterpolator(); rotateAnimation.setInterpolator(lir); refreshingAnimation.setInterpolator(lir); } private void hide() { timer.schedule(5); } /** * 鐎瑰本鍨氶崚閿嬫煀閹垮秳缍旈敍灞炬▔缁�搫鍩涢弬鎵波閺嬫嚎锟藉▔銊﹀壈閿涙艾鍩涢弬鏉跨暚閹存劕鎮楁稉锟界暰鐟曚浇鐨熼悽銊ㄧ箹娑擃亝鏌熷▔锟� */ /** * @param refreshResult * PullToRefreshLayout.SUCCEED娴狅綀銆冮幋鎰閿涘ullToRefreshLayout. * FAIL娴狅綀銆冩径杈Е */ public void refreshFinish(int refreshResult) { refreshingView.clearAnimation(); refreshingView.setVisibility(View.GONE); switch (refreshResult) { case SUCCEED: // 閸掗攱鏌婇幋鎰 refreshStateImageView.setVisibility(View.VISIBLE); refreshStateTextView.setText(R.string.refresh_succeed); refreshStateImageView .setBackgroundResource(R.drawable.refresh_succeed); break; case FAIL: default: // 閸掗攱鏌婃径杈Е refreshStateImageView.setVisibility(View.VISIBLE); refreshStateTextView.setText(R.string.refresh_fail); refreshStateImageView .setBackgroundResource(R.drawable.refresh_failed); break; } if (pullDownY > 0) { // 閸掗攱鏌婄紒鎾寸亯閸嬫粎鏆�缁夛拷 new Handler() { @Override public void handleMessage(Message msg) { changeState(DONE); hide(); } }.sendEmptyMessageDelayed(0, 1000); } else { changeState(DONE); hide(); } } /** * 閸旂姾娴囩�灞剧槸閿涘本妯夌粈鍝勫鏉炵晫绮ㄩ弸婧匡拷濞夈劍鍓伴敍姘鏉炶棄鐣幋鎰倵娑擄拷鐣剧憰浣界殶閻€劏绻栨稉顏呮煙濞夛拷 * * @param refreshResult * PullToRefreshLayout.SUCCEED娴狅綀銆冮幋鎰閿涘ullToRefreshLayout. * FAIL娴狅綀銆冩径杈Е */ public void loadmoreFinish(int refreshResult) { loadingView.clearAnimation(); loadingView.setVisibility(View.GONE); switch (refreshResult) { case SUCCEED: // 閸旂姾娴囬幋鎰 loadStateImageView.setVisibility(View.VISIBLE); loadStateTextView.setText(R.string.load_succeed); loadStateImageView.setBackgroundResource(R.drawable.load_succeed); break; case FAIL: default: // 閸旂姾娴囨径杈Е loadStateImageView.setVisibility(View.VISIBLE); loadStateTextView.setText(R.string.load_fail); loadStateImageView.setBackgroundResource(R.drawable.load_failed); break; } if (pullUpY < 0) { // 閸掗攱鏌婄紒鎾寸亯閸嬫粎鏆�缁夛拷 new Handler() { @Override public void handleMessage(Message msg) { changeState(DONE); hide(); } }.sendEmptyMessageDelayed(0, 1000); } else { changeState(DONE); hide(); } } private void changeState(int to) { state = to; switch (state) { case INIT: // 娑撳濯虹敮鍐ㄧ湰閸掓繂顫愰悩鑸碉拷 refreshStateImageView.setVisibility(View.GONE); refreshStateTextView.setText(R.string.pull_to_refresh); pullView.clearAnimation(); pullView.setVisibility(View.VISIBLE); // 娑撳﹥濯虹敮鍐ㄧ湰閸掓繂顫愰悩鑸碉拷 loadStateImageView.setVisibility(View.GONE); loadStateTextView.setText(R.string.pullup_to_load); pullUpView.clearAnimation(); pullUpView.setVisibility(View.VISIBLE); break; case RELEASE_TO_REFRESH: // 闁插﹥鏂侀崚閿嬫煀閻樿埖锟� refreshStateTextView.setText(R.string.release_to_refresh); pullView.startAnimation(rotateAnimation); break; case REFRESHING: // 濮濓絽婀崚閿嬫煀閻樿埖锟� pullView.clearAnimation(); refreshingView.setVisibility(View.VISIBLE); pullView.setVisibility(View.INVISIBLE); refreshingView.startAnimation(refreshingAnimation); refreshStateTextView.setText(R.string.refreshing); break; case RELEASE_TO_LOAD: // 闁插﹥鏂侀崝鐘烘祰閻樿埖锟� loadStateTextView.setText(R.string.release_to_load); pullUpView.startAnimation(rotateAnimation); break; case LOADING: // 濮濓絽婀崝鐘烘祰閻樿埖锟� pullUpView.clearAnimation(); loadingView.setVisibility(View.VISIBLE); pullUpView.setVisibility(View.INVISIBLE); loadingView.startAnimation(refreshingAnimation); loadStateTextView.setText(R.string.loading); break; case DONE: // 閸掗攱鏌婇幋鏍у鏉炶棄鐣В鏇礉閸熴儵鍏樻稉宥呬粵 break; } } /** * 娑撳秹妾洪崚鏈电瑐閹峰鍨ㄦ稉瀣 */ private void releasePull() { canPullDown = true; canPullUp = true; } /* * 閿涘牓娼�Javadoc閿涘鏁遍悥鑸靛付娴犺泛鍠呯�姘Ц閸氾箑鍨庨崣鎴滅皑娴犺绱濋梼鍙夘剾娴滃娆㈤崘鑼崐 * * @see android.view.ViewGroup#dispatchTouchEvent(android.view.MotionEvent) */ @Override public boolean dispatchTouchEvent(MotionEvent ev) { switch (ev.getActionMasked()) { case MotionEvent.ACTION_DOWN: downY = ev.getY(); lastY = downY; timer.cancel(); mEvents = 0; releasePull(); break; case MotionEvent.ACTION_POINTER_DOWN: case MotionEvent.ACTION_POINTER_UP: // 鏉╁洦鎶ゆ径姘卞仯鐟欙妇顫� mEvents = -1; break; case MotionEvent.ACTION_MOVE: if (mEvents == 0) { if (pullDownY > 0 || (((Pullable) pullableView).canPullDown() && canPullDown && state != LOADING)) { // 閸欘垯浜掓稉瀣閿涘本顒滈崷銊ュ鏉炶姤妞傛稉宥堝厴娑撳濯� // 鐎电懓鐤勯梽鍛拨閸斻劏绐涚粋璇蹭粵缂傗晛鐨敍宀勶拷閹存劗鏁ら崝娑欏閻ㄥ嫭鍔呯憴锟� pullDownY = pullDownY + (ev.getY() - lastY) / radio; if (pullDownY < 0) { pullDownY = 0; canPullDown = false; canPullUp = true; } if (pullDownY > getMeasuredHeight()) pullDownY = getMeasuredHeight(); if (state == REFRESHING) { // 濮濓絽婀崚閿嬫煀閻ㄥ嫭妞傞崐娆捫曢幗鍝バ╅崝锟� isTouch = true; } } else if (pullUpY < 0 || (((Pullable) pullableView).canPullUp() && canPullUp && state != REFRESHING)) { // 閸欘垯浜掓稉濠冨閿涘本顒滈崷銊ュ煕閺傜増妞傛稉宥堝厴娑撳﹥濯� pullUpY = pullUpY + (ev.getY() - lastY) / radio; if (pullUpY > 0) { pullUpY = 0; canPullDown = true; canPullUp = false; } if (pullUpY < -getMeasuredHeight()) pullUpY = -getMeasuredHeight(); if (state == LOADING) { // 濮濓絽婀崝鐘烘祰閻ㄥ嫭妞傞崐娆捫曢幗鍝バ╅崝锟� isTouch = true; } } else releasePull(); } else mEvents = 0; lastY = ev.getY(); // 閺嶈宓佹稉瀣鐠烘繄顬囬弨鐟板綁濮f柧绶� radio = (float) (2 + 2 * Math.tan(Math.PI / 2 / getMeasuredHeight() * (pullDownY + Math.abs(pullUpY)))); if (pullDownY > 0 || pullUpY < 0) requestLayout(); if (pullDownY > 0) { if (pullDownY <= refreshDist && (state == RELEASE_TO_REFRESH || state == DONE)) { // 婵″倹鐏夋稉瀣鐠烘繄顬囧▽陇鎻崚鏉垮煕閺傛壆娈戠捄婵堫瀲娑撴柨缍嬮崜宥囧Ц閹焦妲搁柌濠冩杹閸掗攱鏌婇敍灞炬暭閸欐濮搁幀浣疯礋娑撳濯洪崚閿嬫煀 changeState(INIT); } if (pullDownY >= refreshDist && state == INIT) { // 婵″倹鐏夋稉瀣鐠烘繄顬囨潏鎯у煂閸掗攱鏌婇惃鍕獩缁傝绗栬ぐ鎾冲閻樿埖锟介弰顖氬灥婵濮搁幀浣稿煕閺傚府绱濋弨鐟板綁閻樿埖锟芥稉娲櫞閺�儳鍩涢弬锟� changeState(RELEASE_TO_REFRESH); } } else if (pullUpY < 0) { // 娑撳娼伴弰顖氬灲閺傤厺绗傞幏澶婂鏉炵晫娈戦敍灞芥倱娑撳绱濆▔銊﹀壈pullUpY閺勵垵绀嬮崐锟� if (-pullUpY <= loadmoreDist && (state == RELEASE_TO_LOAD || state == DONE)) { changeState(INIT); } // 娑撳﹥濯洪幙宥勭稊 if (-pullUpY >= loadmoreDist && state == INIT) { changeState(RELEASE_TO_LOAD); } } // 閸ョ姳璐熼崚閿嬫煀閸滃苯濮炴潪鑺ユ惙娴f粈绗夐懗钘夋倱閺冩儼绻樼悰宀嬬礉閹碉拷浜抪ullDownY閸滃ullUpY娑撳秳绱伴崥灞炬娑撳秳璐�閿涘苯娲滃銈堢箹闁插瞼鏁�pullDownY // + // Math.abs(pullUpY))鐏忓崬褰叉禒銉ょ瑝鐎电懓缍嬮崜宥囧Ц閹椒缍旈崠鍝勫瀻娴滐拷 if ((pullDownY + Math.abs(pullUpY)) > 8) { // 闂冨弶顒涙稉瀣鏉╁洨鈻兼稉顓☆嚖鐟欙箑褰傞梹鎸庡瘻娴滃娆㈤崪宀�仯閸戣绨ㄦ禒锟� ev.setAction(MotionEvent.ACTION_CANCEL); } break; case MotionEvent.ACTION_UP: if (pullDownY > refreshDist || -pullUpY > loadmoreDist) // 濮濓絽婀崚閿嬫煀閺冭泛绶氭稉瀣閿涘牊顒滈崷銊ュ鏉炶姤妞傚锟界瑐閹峰绱氶敍宀勫櫞閺�儳鎮楁稉瀣婢惰揪绱欐稉濠冨婢惰揪绱氭稉宥夋閽橈拷 { isTouch = false; } if (state == RELEASE_TO_REFRESH) { changeState(REFRESHING); // 閸掗攱鏌婇幙宥勭稊 if (mListener != null) mListener.onRefresh(this); } else if (state == RELEASE_TO_LOAD) { changeState(LOADING); // 閸旂姾娴囬幙宥勭稊 if (mListener != null) mListener.onLoadMore(this); } hide(); default: break; } // 娴滃娆㈤崚鍡楀絺娴溿倗绮伴悥鍓佽 super.dispatchTouchEvent(ev); return true; } /** * @author chenjing 閼奉亜濮╁Ο鈩冨珯閹靛瀵氬鎴濆З閻ㄥ墖ask * */ private class AutoRefreshAndLoadTask extends AsyncTask{ @Override protected String doInBackground(Integer... params) { while (pullDownY < 4 / 3 * refreshDist) { pullDownY += MOVE_SPEED; publishProgress(pullDownY); try { Thread.sleep(params[0]); } catch (InterruptedException e) { e.printStackTrace(); } } return null; } @Override protected void onPostExecute(String result) { changeState(REFRESHING); // 閸掗攱鏌婇幙宥勭稊 if (mListener != null) mListener.onRefresh(PullToRefreshLayout.this); hide(); } @Override protected void onProgressUpdate(Float... values) { if (pullDownY > refreshDist) changeState(RELEASE_TO_REFRESH); requestLayout(); } } /** * 閼奉亜濮╅崚閿嬫煀 */ public void autoRefresh() { AutoRefreshAndLoadTask task = new AutoRefreshAndLoadTask(); task.execute(20); } /** * 閼奉亜濮╅崝鐘烘祰 */ public void autoLoad() { pullUpY = -loadmoreDist; requestLayout(); changeState(LOADING); // 閸旂姾娴囬幙宥勭稊 if (mListener != null) mListener.onLoadMore(this); } private void initView() { // 閸掓繂顫愰崠鏍︾瑓閹峰绔风仦锟� pullView = refreshView.findViewById(R.id.pull_icon); refreshStateTextView = (TextView) refreshView .findViewById(R.id.state_tv); refreshingView = refreshView.findViewById(R.id.refreshing_icon); refreshStateImageView = refreshView.findViewById(R.id.state_iv); // 閸掓繂顫愰崠鏍︾瑐閹峰绔风仦锟� pullUpView = loadmoreView.findViewById(R.id.pullup_icon); loadStateTextView = (TextView) loadmoreView .findViewById(R.id.loadstate_tv); loadingView = loadmoreView.findViewById(R.id.loading_icon); loadStateImageView = loadmoreView.findViewById(R.id.loadstate_iv); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { Log.d("Test", "Test"); if (!isLayout) { // 鏉╂瑩鍣烽弰顖滎儑娑擄拷顐兼潻娑欐降閻ㄥ嫭妞傞崐娆忎粵娑擄拷绨洪崚婵嗩潗閸栵拷 refreshView = getChildAt(0); pullableView = getChildAt(1); loadmoreView = getChildAt(2); isLayout = true; initView(); refreshDist = ((ViewGroup) refreshView).getChildAt(0) .getMeasuredHeight(); loadmoreDist = ((ViewGroup) loadmoreView).getChildAt(0) .getMeasuredHeight(); } // 閺�懓褰夌�鎰付娴犲墎娈戠敮鍐ㄧ湰閿涘矁绻栭柌宀�纯閹恒儳鏁�pullDownY + // pullUpY)娴f粈璐熼崑蹇曅╅柌蹇ョ礉鏉╂瑦鐗辩亸鍗炲讲娴犮儰绗夌�鐟扮秼閸撳秶濮搁幀浣风稊閸栧搫鍨� refreshView.layout(0, (int) (pullDownY + pullUpY) - refreshView.getMeasuredHeight(), refreshView.getMeasuredWidth(), (int) (pullDownY + pullUpY)); pullableView.layout(0, (int) (pullDownY + pullUpY), pullableView.getMeasuredWidth(), (int) (pullDownY + pullUpY) + pullableView.getMeasuredHeight()); loadmoreView.layout(0, (int) (pullDownY + pullUpY) + pullableView.getMeasuredHeight(), loadmoreView.getMeasuredWidth(), (int) (pullDownY + pullUpY) + pullableView.getMeasuredHeight() + loadmoreView.getMeasuredHeight()); } class MyTimer { private Handler handler; private Timer timer; private MyTask mTask; public MyTimer(Handler handler) { this.handler = handler; timer = new Timer(); } public void schedule(long period) { if (mTask != null) { mTask.cancel(); mTask = null; } mTask = new MyTask(handler); timer.schedule(mTask, 0, period); } public void cancel() { if (mTask != null) { mTask.cancel(); mTask = null; } } class MyTask extends TimerTask { private Handler handler; public MyTask(Handler handler) { this.handler = handler; } @Override public void run() { handler.obtainMessage().sendToTarget(); } } } /** * 閸掗攱鏌婇崝鐘烘祰閸ョ偠鐨熼幒銉ュ經 * * @author chenjing * */ public interface OnRefreshListener { /** * 閸掗攱鏌婇幙宥勭稊 */ void onRefresh(PullToRefreshLayout pullToRefreshLayout); /** * 閸旂姾娴囬幙宥勭稊 */ void onLoadMore(PullToRefreshLayout pullToRefreshLayout); } }
下面是MainActivity
/MainActivity/src/com/exmple/pull/MainActivity.java
package com.exmple.pull; import java.util.ArrayList; import java.util.List; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.Log; import android.view.Window; import com.chen.listTongyong.Base1; import com.eample.vo.MyData; import com.eample.vo.Super; import com.exaple.tong.PullToRefreshLayout; import com.exaple.tong.PullableListView; import com.exaple.tong.PullToRefreshLayout.OnRefreshListener; import com.google.gson.Gson; public class MainActivity extends Activity { Handler h = new Handler() { public void handleMessage(Message msg) { if (msg.what == 1) { String result = (String) msg.obj; Gson g = new Gson(); Super ms = g.fromJson(result, Super.class); Listdata = ms.getData(); list = data; ba = new Base1(MainActivity.this, list); plistview.setAdapter(ba); } if (msg.what == 2) { String result = (String) msg.obj; Gson g = new Gson(); Super ms = g.fromJson(result, Super.class); List data = ms.getData(); list.addAll(data); ba.notifyDataSetChanged(); } } }; int page = 1; String url = "http://api.expoon.com/AppNews/getNewsList/type/1/p/"; private List list = new ArrayList (); private Base1 ba; private PullableListView plistview; private PullToRefreshLayout layout; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 设置隐藏标题 requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main); //找控件 plistview = (PullableListView) findViewById(R.id.listview); layout = (PullToRefreshLayout) findViewById(R.id.layout);
//刚进去显示数据 setJson(page); layout.setOnRefreshListener(new OnRefreshListener() { //下拉刷新 @Override public void onRefresh(PullToRefreshLayout pullToRefreshLayout) { h.postDelayed(new Runnable() { @Override public void run() { int page = 1; setJson(page); layout.refreshFinish(PullToRefreshLayout.SUCCEED); } }, 10); } //加载更多 @Override public void onLoadMore(PullToRefreshLayout pullToRefreshLayout) { h.postDelayed(new Runnable() { @Override public void run() { page++; new Thread() { public void run() { String string = NetUtil.getData(url + page); h.sendMessage(h.obtainMessage(2, string)); } }.start(); layout.loadmoreFinish(PullToRefreshLayout.SUCCEED); } }, 10); } }); } private void setJson(final int pa) { new Thread() { public void run() { String string = NetUtil.getData(url + pa); h.sendMessage(h.obtainMessage(1, string)); } }.start(); } }
/MainActivity/src/com/exmple/pull/NetUtil.java 请求数据
package com.exmple.pull; import java.io.IOException; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.params.BasicHttpParams; import org.apache.http.params.DefaultedHttpParams; import org.apache.http.params.HttpConnectionParams; import org.apache.http.params.HttpParams; import org.apache.http.util.EntityUtils; public class NetUtil { public static String getData(String str){ String str1=""; HttpGet get=new HttpGet(str); HttpParams parmas=new BasicHttpParams(); HttpConnectionParams.setConnectionTimeout(parmas, 5000); HttpConnectionParams.setSoTimeout(parmas, 5000); HttpClient client=new DefaultHttpClient(parmas); try { HttpResponse execute = client.execute(get); if(execute.getStatusLine().getStatusCode()==200) { HttpEntity entity=execute.getEntity(); str1=EntityUtils.toString(entity, "UTF-8"); } } catch (ClientProtocolException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return str1; } }
下面是list集合的vo包(两个)
/MainActivity/src/com/eample/vo/Super.java (1)
package com.eample.vo; import java.util.List; public class Super { Listdata; String info; int status; public List getData() { return data; } public void setData(List data) { this.data = data; } public String getInfo() { return info; } public void setInfo(String info) { this.info = info; } public int getStatus() { return status; } public void setStatus(int status) { this.status = status; } @Override public String toString() { return "Super [data=" + data + ", info=" + info + ", status=" + status + "]"; } public Super(List data, String info, int status) { super(); this.data = data; this.info = info; this.status = status; } public Super() { super(); // TODO Auto-generated constructor stub } }
/MainActivity/src/com/eample/vo/MyData.java (2)
package com.eample.vo; public class MyData { String news_id; String news_summary; String news_title; String pic_url; public String getNews_id() { return news_id; } public void setNews_id(String news_id) { this.news_id = news_id; } public String getNews_summary() { return news_summary; } public void setNews_summary(String news_summary) { this.news_summary = news_summary; } public String getNews_title() { return news_title; } public void setNews_title(String news_title) { this.news_title = news_title; } public String getPic_url() { return pic_url; } public void setPic_url(String pic_url) { this.pic_url = pic_url; } @Override public String toString() { return "MyData [news_id=" + news_id + ", news_summary=" + news_summary + ", news_title=" + news_title + ", pic_url=" + pic_url + "]"; } public MyData(String news_id, String news_summary, String news_title, String pic_url) { super(); this.news_id = news_id; this.news_summary = news_summary; this.news_title = news_title; this.pic_url = pic_url; } public MyData() { super(); // TODO Auto-generated constructor stub } }
下面是listview适配器
/MainActivity/src/com/chen/listTongyong/Base1.java
package com.chen.listTongyong; import java.util.List; import com.eample.vo.MyData; import com.exaple.tong.PullToRefreshLayout; import com.exaple.tong.PullToRefreshLayout.OnRefreshListener; import com.exmple.pull.R; import com.lidroid.xutils.BitmapUtils; import android.content.Context; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.PopupWindow; import android.widget.TextView; public class Base1 extends BaseAdapter { Context co; Listlist; private View view; private ViewHolder vh; public Base1(Context co, List list) { super(); this.co = co; this.list = list; } @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 0; } @Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { view = View.inflate(co, R.layout.base, null); vh = new ViewHolder(); vh.image = (ImageView) view.findViewById(R.id.image); vh.text = (TextView) view.findViewById(R.id.text); view.setTag(vh); } else { view = convertView; vh = (ViewHolder) view.getTag(); } vh.text.setText(list.get(position).getNews_title()); BitmapUtils bit = new BitmapUtils(co); bit.display(vh.image, list.get(position).getPic_url()); return view; } public class ViewHolder { TextView text; ImageView image; } }