├── .classpath
├── .project
├── .settings
└── org.eclipse.jdt.core.prefs
├── AndroidManifest.xml
├── README.md
├── ic_launcher-web.png
├── libs
└── android-support-v4.jar
├── proguard-project.txt
├── project.properties
├── res
├── anim
│ ├── reverse_anim.xml
│ └── rotating.xml
├── drawable-hdpi
│ └── ic_launcher.png
├── drawable-mdpi
│ └── ic_launcher.png
├── drawable-xhdpi
│ ├── h.jpg
│ ├── i.jpg
│ ├── ic_launcher.png
│ ├── j.jpg
│ ├── k.jpg
│ ├── l.jpg
│ ├── load_failed.png
│ ├── load_succeed.png
│ ├── loading.png
│ ├── m.jpg
│ ├── pull_icon_big.png
│ ├── pullup_icon_big.png
│ ├── refresh_failed.png
│ ├── refresh_succeed.png
│ └── refreshing.png
├── drawable-xxhdpi
│ └── ic_launcher.png
├── layout
│ ├── activity_expandablelistview.xml
│ ├── activity_gridview.xml
│ ├── activity_imageview.xml
│ ├── activity_listview.xml
│ ├── activity_main.xml
│ ├── activity_scrollview.xml
│ ├── activity_textview.xml
│ ├── activity_webview.xml
│ ├── list_item_layout.xml
│ ├── load_more.xml
│ └── refresh_head.xml
├── values-sw600dp
│ └── dimens.xml
├── values-sw720dp-land
│ └── dimens.xml
└── values
│ ├── color.xml
│ ├── dimens.xml
│ ├── strings.xml
│ └── styles.xml
├── screenshots
├── ExpandableListView.gif
├── GridView.gif
├── ImageView.gif
├── ListView.gif
├── ScrollView.gif
├── TextView.gif
├── WebView.gif
└── main.gif
└── src
└── com
└── jingchen
└── pulltorefresh
├── MainActivity.java
├── MyAdapter.java
├── MyListener.java
├── PullToRefreshLayout.java
├── activity
├── PullableExpandableListViewActivity.java
├── PullableGridViewActivity.java
├── PullableImageViewActivity.java
├── PullableListViewActivity.java
├── PullableScrollViewActivity.java
├── PullableTextViewActivity.java
└── PullableWebViewActivity.java
└── pullableview
├── Pullable.java
├── PullableExpandableListView.java
├── PullableGridView.java
├── PullableImageView.java
├── PullableListView.java
├── PullableScrollView.java
├── PullableTextView.java
└── PullableWebView.java
/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | PullToRefreshAndLoad
4 |
5 |
6 |
7 |
8 |
9 | com.android.ide.eclipse.adt.ResourceManagerBuilder
10 |
11 |
12 |
13 |
14 | com.android.ide.eclipse.adt.PreCompilerBuilder
15 |
16 |
17 |
18 |
19 | org.eclipse.jdt.core.javabuilder
20 |
21 |
22 |
23 |
24 | com.android.ide.eclipse.adt.ApkBuilder
25 |
26 |
27 |
28 |
29 |
30 | com.android.ide.eclipse.adt.AndroidNature
31 | org.eclipse.jdt.core.javanature
32 |
33 |
34 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.jdt.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
3 | org.eclipse.jdt.core.compiler.compliance=1.6
4 | org.eclipse.jdt.core.compiler.source=1.6
5 |
--------------------------------------------------------------------------------
/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
10 |
11 |
12 |
13 |
17 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | PullToRefreshAndLoad
2 | ====================
3 |
4 | Android下拉刷新上拉加载控件,对所有View通用!
5 | 这是一个演示如何使用通用的下拉刷新上拉加载控件demo,demo中已经实现了常见的需要上下拉功能的控件,其他控件如果需要加入这两个功能可自行扩展,实现Pullable接口即可,
6 | 具体的实现原理分析可以参见我的博客[http://blog.csdn.net/zhongkejingwang/article/details/38868463](http://blog.csdn.net/zhongkejingwang/article/details/38868463)
7 | ##demo截图
8 | ###demo首页也是一个可以上拉下拉的ListView
9 | 
10 | ###ListView:
11 | 
12 | ###GridView:
13 | 
14 | ###ExpandableListView:
15 | 
16 | ###ScrollView:
17 | 
18 | ###WebView:
19 | 
20 | ###ImageView:
21 | 
22 | ###TextView:
23 | 
24 |
--------------------------------------------------------------------------------
/ic_launcher-web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jingchenUSTC/PullToRefreshAndLoad/5e3c283ae548155f18940708ed1042bc24e32723/ic_launcher-web.png
--------------------------------------------------------------------------------
/libs/android-support-v4.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jingchenUSTC/PullToRefreshAndLoad/5e3c283ae548155f18940708ed1042bc24e32723/libs/android-support-v4.jar
--------------------------------------------------------------------------------
/proguard-project.txt:
--------------------------------------------------------------------------------
1 | # To enable ProGuard in your project, edit project.properties
2 | # to define the proguard.config property as described in that file.
3 | #
4 | # Add project specific ProGuard rules here.
5 | # By default, the flags in this file are appended to flags specified
6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt
7 | # You can edit the include path and order by changing the ProGuard
8 | # include property in project.properties.
9 | #
10 | # For more details, see
11 | # http://developer.android.com/guide/developing/tools/proguard.html
12 |
13 | # Add any project specific keep options here:
14 |
15 | # If your project uses WebView with JS, uncomment the following
16 | # and specify the fully qualified class name to the JavaScript interface
17 | # class:
18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
19 | # public *;
20 | #}
21 |
--------------------------------------------------------------------------------
/project.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system edit
7 | # "ant.properties", and override values to adapt the script to your
8 | # project structure.
9 | #
10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
12 |
13 | # Project target.
14 | target=android-8
15 |
--------------------------------------------------------------------------------
/res/anim/reverse_anim.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
--------------------------------------------------------------------------------
/res/anim/rotating.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
--------------------------------------------------------------------------------
/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jingchenUSTC/PullToRefreshAndLoad/5e3c283ae548155f18940708ed1042bc24e32723/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jingchenUSTC/PullToRefreshAndLoad/5e3c283ae548155f18940708ed1042bc24e32723/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-xhdpi/h.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jingchenUSTC/PullToRefreshAndLoad/5e3c283ae548155f18940708ed1042bc24e32723/res/drawable-xhdpi/h.jpg
--------------------------------------------------------------------------------
/res/drawable-xhdpi/i.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jingchenUSTC/PullToRefreshAndLoad/5e3c283ae548155f18940708ed1042bc24e32723/res/drawable-xhdpi/i.jpg
--------------------------------------------------------------------------------
/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jingchenUSTC/PullToRefreshAndLoad/5e3c283ae548155f18940708ed1042bc24e32723/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-xhdpi/j.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jingchenUSTC/PullToRefreshAndLoad/5e3c283ae548155f18940708ed1042bc24e32723/res/drawable-xhdpi/j.jpg
--------------------------------------------------------------------------------
/res/drawable-xhdpi/k.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jingchenUSTC/PullToRefreshAndLoad/5e3c283ae548155f18940708ed1042bc24e32723/res/drawable-xhdpi/k.jpg
--------------------------------------------------------------------------------
/res/drawable-xhdpi/l.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jingchenUSTC/PullToRefreshAndLoad/5e3c283ae548155f18940708ed1042bc24e32723/res/drawable-xhdpi/l.jpg
--------------------------------------------------------------------------------
/res/drawable-xhdpi/load_failed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jingchenUSTC/PullToRefreshAndLoad/5e3c283ae548155f18940708ed1042bc24e32723/res/drawable-xhdpi/load_failed.png
--------------------------------------------------------------------------------
/res/drawable-xhdpi/load_succeed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jingchenUSTC/PullToRefreshAndLoad/5e3c283ae548155f18940708ed1042bc24e32723/res/drawable-xhdpi/load_succeed.png
--------------------------------------------------------------------------------
/res/drawable-xhdpi/loading.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jingchenUSTC/PullToRefreshAndLoad/5e3c283ae548155f18940708ed1042bc24e32723/res/drawable-xhdpi/loading.png
--------------------------------------------------------------------------------
/res/drawable-xhdpi/m.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jingchenUSTC/PullToRefreshAndLoad/5e3c283ae548155f18940708ed1042bc24e32723/res/drawable-xhdpi/m.jpg
--------------------------------------------------------------------------------
/res/drawable-xhdpi/pull_icon_big.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jingchenUSTC/PullToRefreshAndLoad/5e3c283ae548155f18940708ed1042bc24e32723/res/drawable-xhdpi/pull_icon_big.png
--------------------------------------------------------------------------------
/res/drawable-xhdpi/pullup_icon_big.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jingchenUSTC/PullToRefreshAndLoad/5e3c283ae548155f18940708ed1042bc24e32723/res/drawable-xhdpi/pullup_icon_big.png
--------------------------------------------------------------------------------
/res/drawable-xhdpi/refresh_failed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jingchenUSTC/PullToRefreshAndLoad/5e3c283ae548155f18940708ed1042bc24e32723/res/drawable-xhdpi/refresh_failed.png
--------------------------------------------------------------------------------
/res/drawable-xhdpi/refresh_succeed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jingchenUSTC/PullToRefreshAndLoad/5e3c283ae548155f18940708ed1042bc24e32723/res/drawable-xhdpi/refresh_succeed.png
--------------------------------------------------------------------------------
/res/drawable-xhdpi/refreshing.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jingchenUSTC/PullToRefreshAndLoad/5e3c283ae548155f18940708ed1042bc24e32723/res/drawable-xhdpi/refreshing.png
--------------------------------------------------------------------------------
/res/drawable-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jingchenUSTC/PullToRefreshAndLoad/5e3c283ae548155f18940708ed1042bc24e32723/res/drawable-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/layout/activity_expandablelistview.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/res/layout/activity_gridview.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/res/layout/activity_imageview.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/res/layout/activity_listview.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
15 |
16 |
22 |
23 |
32 |
33 |
42 |
43 |
52 |
53 |
62 |
63 |
64 |
70 |
71 |
72 |
73 |
74 |
81 |
82 |
83 |
84 |
85 |
--------------------------------------------------------------------------------
/res/layout/activity_scrollview.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
12 |
13 |
16 |
17 |
23 |
24 |
28 |
29 |
33 |
34 |
38 |
42 |
46 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/res/layout/activity_textview.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/res/layout/activity_webview.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/res/layout/list_item_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
15 |
16 |
--------------------------------------------------------------------------------
/res/layout/load_more.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
14 |
15 |
19 |
20 |
27 |
28 |
36 |
37 |
45 |
46 |
54 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/res/layout/refresh_head.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
14 |
15 |
19 |
20 |
27 |
28 |
36 |
37 |
45 |
46 |
54 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/res/values-sw600dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/res/values-sw720dp-land/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 | 128dp
8 |
9 |
10 |
--------------------------------------------------------------------------------
/res/values/color.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FFFFFF
4 | #000000
5 | #aaaaaa
6 | #6593cb
7 |
8 |
--------------------------------------------------------------------------------
/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 16dp
5 | 16dp
6 |
7 |
8 |
--------------------------------------------------------------------------------
/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 通用版下拉刷新上拉加载控件
5 | 这里是HeadView
6 | 下拉刷新
7 | 释放立即刷新
8 | 正在刷新...
9 | 刷新成功
10 | 刷新失败
11 | 上拉加载更多
12 | 释放立即加载
13 | 正在加载...
14 | 加载成功
15 | 加载失败
16 |
17 |
--------------------------------------------------------------------------------
/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/screenshots/ExpandableListView.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jingchenUSTC/PullToRefreshAndLoad/5e3c283ae548155f18940708ed1042bc24e32723/screenshots/ExpandableListView.gif
--------------------------------------------------------------------------------
/screenshots/GridView.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jingchenUSTC/PullToRefreshAndLoad/5e3c283ae548155f18940708ed1042bc24e32723/screenshots/GridView.gif
--------------------------------------------------------------------------------
/screenshots/ImageView.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jingchenUSTC/PullToRefreshAndLoad/5e3c283ae548155f18940708ed1042bc24e32723/screenshots/ImageView.gif
--------------------------------------------------------------------------------
/screenshots/ListView.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jingchenUSTC/PullToRefreshAndLoad/5e3c283ae548155f18940708ed1042bc24e32723/screenshots/ListView.gif
--------------------------------------------------------------------------------
/screenshots/ScrollView.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jingchenUSTC/PullToRefreshAndLoad/5e3c283ae548155f18940708ed1042bc24e32723/screenshots/ScrollView.gif
--------------------------------------------------------------------------------
/screenshots/TextView.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jingchenUSTC/PullToRefreshAndLoad/5e3c283ae548155f18940708ed1042bc24e32723/screenshots/TextView.gif
--------------------------------------------------------------------------------
/screenshots/WebView.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jingchenUSTC/PullToRefreshAndLoad/5e3c283ae548155f18940708ed1042bc24e32723/screenshots/WebView.gif
--------------------------------------------------------------------------------
/screenshots/main.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jingchenUSTC/PullToRefreshAndLoad/5e3c283ae548155f18940708ed1042bc24e32723/screenshots/main.gif
--------------------------------------------------------------------------------
/src/com/jingchen/pulltorefresh/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.jingchen.pulltorefresh;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | import android.app.Activity;
7 | import android.content.Intent;
8 | import android.os.Bundle;
9 | import android.view.View;
10 | import android.widget.AdapterView;
11 | import android.widget.AdapterView.OnItemClickListener;
12 | import android.widget.AdapterView.OnItemLongClickListener;
13 | import android.widget.ListView;
14 | import android.widget.Toast;
15 |
16 | import com.jingchen.pulltorefresh.activity.PullableExpandableListViewActivity;
17 | import com.jingchen.pulltorefresh.activity.PullableGridViewActivity;
18 | import com.jingchen.pulltorefresh.activity.PullableImageViewActivity;
19 | import com.jingchen.pulltorefresh.activity.PullableListViewActivity;
20 | import com.jingchen.pulltorefresh.activity.PullableScrollViewActivity;
21 | import com.jingchen.pulltorefresh.activity.PullableTextViewActivity;
22 | import com.jingchen.pulltorefresh.activity.PullableWebViewActivity;
23 |
24 | /**
25 | * 更多详解见博客http://blog.csdn.net/zhongkejingwang/article/details/38868463
26 | *
27 | * @author 陈靖
28 | *
29 | */
30 | public class MainActivity extends Activity
31 | {
32 | private ListView listView;
33 |
34 | @Override
35 | protected void onCreate(Bundle savedInstanceState)
36 | {
37 | super.onCreate(savedInstanceState);
38 | setContentView(R.layout.activity_main);
39 | ((PullToRefreshLayout) findViewById(R.id.refresh_view))
40 | .setOnRefreshListener(new MyListener());
41 | listView = (ListView) findViewById(R.id.content_view);
42 | initListView();
43 | }
44 |
45 | /**
46 | * ListView初始化方法
47 | */
48 | private void initListView()
49 | {
50 | List items = new ArrayList();
51 | items.add("可下拉刷新上拉加载的ListView");
52 | items.add("可下拉刷新上拉加载的GridView");
53 | items.add("可下拉刷新上拉加载的ExpandableListView");
54 | items.add("可下拉刷新上拉加载的SrcollView");
55 | items.add("可下拉刷新上拉加载的WebView");
56 | items.add("可下拉刷新上拉加载的ImageView");
57 | items.add("可下拉刷新上拉加载的TextView");
58 | MyAdapter adapter = new MyAdapter(this, items);
59 | listView.setAdapter(adapter);
60 | listView.setOnItemLongClickListener(new OnItemLongClickListener()
61 | {
62 |
63 | @Override
64 | public boolean onItemLongClick(AdapterView> parent, View view,
65 | int position, long id)
66 | {
67 | Toast.makeText(
68 | MainActivity.this,
69 | " LongClick on "
70 | + parent.getAdapter().getItemId(position),
71 | Toast.LENGTH_SHORT).show();
72 | return true;
73 | }
74 | });
75 | listView.setOnItemClickListener(new OnItemClickListener()
76 | {
77 |
78 | @Override
79 | public void onItemClick(AdapterView> parent, View view,
80 | int position, long id)
81 | {
82 |
83 | Intent it = new Intent();
84 | switch (position)
85 | {
86 | case 0:
87 | it.setClass(MainActivity.this,
88 | PullableListViewActivity.class);
89 | break;
90 | case 1:
91 | it.setClass(MainActivity.this,
92 | PullableGridViewActivity.class);
93 | break;
94 | case 2:
95 | it.setClass(MainActivity.this,
96 | PullableExpandableListViewActivity.class);
97 | break;
98 | case 3:
99 | it.setClass(MainActivity.this,
100 | PullableScrollViewActivity.class);
101 | break;
102 | case 4:
103 | it.setClass(MainActivity.this,
104 | PullableWebViewActivity.class);
105 | break;
106 | case 5:
107 | it.setClass(MainActivity.this,
108 | PullableImageViewActivity.class);
109 | break;
110 | case 6:
111 | it.setClass(MainActivity.this,
112 | PullableTextViewActivity.class);
113 | break;
114 |
115 | default:
116 | break;
117 | }
118 | startActivity(it);
119 | }
120 | });
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/src/com/jingchen/pulltorefresh/MyAdapter.java:
--------------------------------------------------------------------------------
1 | package com.jingchen.pulltorefresh;
2 |
3 | import java.util.List;
4 |
5 | import android.content.Context;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 | import android.widget.BaseAdapter;
10 | import android.widget.TextView;
11 |
12 | public class MyAdapter extends BaseAdapter {
13 | List items;
14 | Context context;
15 |
16 | public MyAdapter(Context context, List items) {
17 | this.context = context;
18 | this.items = items;
19 | }
20 |
21 | @Override
22 | public int getCount() {
23 | return items.size();
24 | }
25 |
26 | @Override
27 | public Object getItem(int position) {
28 | return items.get(position);
29 | }
30 |
31 | @Override
32 | public long getItemId(int position) {
33 | return position;
34 | }
35 |
36 | @Override
37 | public View getView(int position, View convertView, ViewGroup parent) {
38 | View view = LayoutInflater.from(context).inflate(
39 | R.layout.list_item_layout, null);
40 | TextView tv = (TextView) view.findViewById(R.id.tv);
41 | tv.setText(items.get(position));
42 | return view;
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/src/com/jingchen/pulltorefresh/MyListener.java:
--------------------------------------------------------------------------------
1 | package com.jingchen.pulltorefresh;
2 |
3 | import android.os.Handler;
4 | import android.os.Message;
5 |
6 | import com.jingchen.pulltorefresh.PullToRefreshLayout.OnRefreshListener;
7 |
8 | public class MyListener implements OnRefreshListener
9 | {
10 |
11 | @Override
12 | public void onRefresh(final PullToRefreshLayout pullToRefreshLayout)
13 | {
14 | // 下拉刷新操作
15 | new Handler()
16 | {
17 | @Override
18 | public void handleMessage(Message msg)
19 | {
20 | // 千万别忘了告诉控件刷新完毕了哦!
21 | pullToRefreshLayout.refreshFinish(PullToRefreshLayout.SUCCEED);
22 | }
23 | }.sendEmptyMessageDelayed(0, 5000);
24 | }
25 |
26 | @Override
27 | public void onLoadMore(final PullToRefreshLayout pullToRefreshLayout)
28 | {
29 | // 加载操作
30 | new Handler()
31 | {
32 | @Override
33 | public void handleMessage(Message msg)
34 | {
35 | // 千万别忘了告诉控件加载完毕了哦!
36 | pullToRefreshLayout.loadmoreFinish(PullToRefreshLayout.SUCCEED);
37 | }
38 | }.sendEmptyMessageDelayed(0, 5000);
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/src/com/jingchen/pulltorefresh/PullToRefreshLayout.java:
--------------------------------------------------------------------------------
1 | package com.jingchen.pulltorefresh;
2 |
3 | import java.util.Timer;
4 | import java.util.TimerTask;
5 |
6 | import android.app.Activity;
7 | import android.content.Context;
8 | import android.os.AsyncTask;
9 | import android.os.Handler;
10 | import android.os.Message;
11 | import android.util.AttributeSet;
12 | import android.util.Log;
13 | import android.view.MotionEvent;
14 | import android.view.View;
15 | import android.view.ViewGroup;
16 | import android.view.animation.AnimationUtils;
17 | import android.view.animation.LinearInterpolator;
18 | import android.view.animation.RotateAnimation;
19 | import android.widget.RelativeLayout;
20 | import android.widget.TextView;
21 |
22 | import com.jingchen.pulltorefresh.pullableview.Pullable;
23 |
24 | /**
25 | * 自定义的布局,用来管理三个子控件,其中一个是下拉头,一个是包含内容的pullableView(可以是实现Pullable接口的的任何View),
26 | * 还有一个上拉头,更多详解见博客http://blog.csdn.net/zhongkejingwang/article/details/38868463
27 | *
28 | * @author 陈靖
29 | */
30 | public class PullToRefreshLayout extends RelativeLayout
31 | {
32 | public static final String TAG = "PullToRefreshLayout";
33 | // 初始状态
34 | public static final int INIT = 0;
35 | // 释放刷新
36 | public static final int RELEASE_TO_REFRESH = 1;
37 | // 正在刷新
38 | public static final int REFRESHING = 2;
39 | // 释放加载
40 | public static final int RELEASE_TO_LOAD = 3;
41 | // 正在加载
42 | public static final int LOADING = 4;
43 | // 操作完毕
44 | public static final int DONE = 5;
45 | // 当前状态
46 | private int state = INIT;
47 | // 刷新回调接口
48 | private OnRefreshListener mListener;
49 | // 刷新成功
50 | public static final int SUCCEED = 0;
51 | // 刷新失败
52 | public static final int FAIL = 1;
53 | // 按下Y坐标,上一个事件点Y坐标
54 | private float downY, lastY;
55 |
56 | // 下拉的距离。注意:pullDownY和pullUpY不可能同时不为0
57 | public float pullDownY = 0;
58 | // 上拉的距离
59 | private float pullUpY = 0;
60 |
61 | // 释放刷新的距离
62 | private float refreshDist = 200;
63 | // 释放加载的距离
64 | private float loadmoreDist = 200;
65 |
66 | private MyTimer timer;
67 | // 回滚速度
68 | public float MOVE_SPEED = 8;
69 | // 第一次执行布局
70 | private boolean isLayout = false;
71 | // 在刷新过程中滑动操作
72 | private boolean isTouch = false;
73 | // 手指滑动距离与下拉头的滑动距离比,中间会随正切函数变化
74 | private float radio = 2;
75 |
76 | // 下拉箭头的转180°动画
77 | private RotateAnimation rotateAnimation;
78 | // 均匀旋转动画
79 | private RotateAnimation refreshingAnimation;
80 |
81 | // 下拉头
82 | private View refreshView;
83 | // 下拉的箭头
84 | private View pullView;
85 | // 正在刷新的图标
86 | private View refreshingView;
87 | // 刷新结果图标
88 | private View refreshStateImageView;
89 | // 刷新结果:成功或失败
90 | private TextView refreshStateTextView;
91 |
92 | // 上拉头
93 | private View loadmoreView;
94 | // 上拉的箭头
95 | private View pullUpView;
96 | // 正在加载的图标
97 | private View loadingView;
98 | // 加载结果图标
99 | private View loadStateImageView;
100 | // 加载结果:成功或失败
101 | private TextView loadStateTextView;
102 |
103 | // 实现了Pullable接口的View
104 | private View pullableView;
105 | // 过滤多点触碰
106 | private int mEvents;
107 | // 这两个变量用来控制pull的方向,如果不加控制,当情况满足可上拉又可下拉时没法下拉
108 | private boolean canPullDown = true;
109 | private boolean canPullUp = true;
110 |
111 | private Context mContext;
112 |
113 | /**
114 | * 执行自动回滚的handler
115 | */
116 | Handler updateHandler = new Handler()
117 | {
118 |
119 | @Override
120 | public void handleMessage(Message msg)
121 | {
122 | // 回弹速度随下拉距离moveDeltaY增大而增大
123 | MOVE_SPEED = (float) (8 + 5 * Math.tan(Math.PI / 2
124 | / getMeasuredHeight() * (pullDownY + Math.abs(pullUpY))));
125 | if (!isTouch)
126 | {
127 | // 正在刷新,且没有往上推的话则悬停,显示"正在刷新..."
128 | if (state == REFRESHING && pullDownY <= refreshDist)
129 | {
130 | pullDownY = refreshDist;
131 | timer.cancel();
132 | } else if (state == LOADING && -pullUpY <= loadmoreDist)
133 | {
134 | pullUpY = -loadmoreDist;
135 | timer.cancel();
136 | }
137 |
138 | }
139 | if (pullDownY > 0)
140 | pullDownY -= MOVE_SPEED;
141 | else if (pullUpY < 0)
142 | pullUpY += MOVE_SPEED;
143 | if (pullDownY < 0)
144 | {
145 | // 已完成回弹
146 | pullDownY = 0;
147 | pullView.clearAnimation();
148 | // 隐藏下拉头时有可能还在刷新,只有当前状态不是正在刷新时才改变状态
149 | if (state != REFRESHING && state != LOADING)
150 | changeState(INIT);
151 | timer.cancel();
152 | requestLayout();
153 | }
154 | if (pullUpY > 0)
155 | {
156 | // 已完成回弹
157 | pullUpY = 0;
158 | pullUpView.clearAnimation();
159 | // 隐藏上拉头时有可能还在刷新,只有当前状态不是正在刷新时才改变状态
160 | if (state != REFRESHING && state != LOADING)
161 | changeState(INIT);
162 | timer.cancel();
163 | requestLayout();
164 | }
165 | Log.d("handle", "handle");
166 | // 刷新布局,会自动调用onLayout
167 | requestLayout();
168 | // 没有拖拉或者回弹完成
169 | if (pullDownY + Math.abs(pullUpY) == 0)
170 | timer.cancel();
171 | }
172 |
173 | };
174 |
175 | public void setOnRefreshListener(OnRefreshListener listener)
176 | {
177 | mListener = listener;
178 | }
179 |
180 | public PullToRefreshLayout(Context context)
181 | {
182 | super(context);
183 | initView(context);
184 | }
185 |
186 | public PullToRefreshLayout(Context context, AttributeSet attrs)
187 | {
188 | super(context, attrs);
189 | initView(context);
190 | }
191 |
192 | public PullToRefreshLayout(Context context, AttributeSet attrs, int defStyle)
193 | {
194 | super(context, attrs, defStyle);
195 | initView(context);
196 | }
197 |
198 | private void initView(Context context)
199 | {
200 | mContext = context;
201 | timer = new MyTimer(updateHandler);
202 | rotateAnimation = (RotateAnimation) AnimationUtils.loadAnimation(
203 | context, R.anim.reverse_anim);
204 | refreshingAnimation = (RotateAnimation) AnimationUtils.loadAnimation(
205 | context, R.anim.rotating);
206 | // 添加匀速转动动画
207 | LinearInterpolator lir = new LinearInterpolator();
208 | rotateAnimation.setInterpolator(lir);
209 | refreshingAnimation.setInterpolator(lir);
210 | }
211 |
212 | private void hide()
213 | {
214 | timer.schedule(5);
215 | }
216 |
217 | /**
218 | * 完成刷新操作,显示刷新结果。注意:刷新完成后一定要调用这个方法
219 | */
220 | /**
221 | * @param refreshResult
222 | * PullToRefreshLayout.SUCCEED代表成功,PullToRefreshLayout.FAIL代表失败
223 | */
224 | public void refreshFinish(int refreshResult)
225 | {
226 | refreshingView.clearAnimation();
227 | refreshingView.setVisibility(View.GONE);
228 | switch (refreshResult)
229 | {
230 | case SUCCEED:
231 | // 刷新成功
232 | refreshStateImageView.setVisibility(View.VISIBLE);
233 | refreshStateTextView.setText(R.string.refresh_succeed);
234 | refreshStateImageView
235 | .setBackgroundResource(R.drawable.refresh_succeed);
236 | break;
237 | case FAIL:
238 | default:
239 | // 刷新失败
240 | refreshStateImageView.setVisibility(View.VISIBLE);
241 | refreshStateTextView.setText(R.string.refresh_fail);
242 | refreshStateImageView
243 | .setBackgroundResource(R.drawable.refresh_failed);
244 | break;
245 | }
246 | if (pullDownY > 0)
247 | {
248 | // 刷新结果停留1秒
249 | new Handler()
250 | {
251 | @Override
252 | public void handleMessage(Message msg)
253 | {
254 | changeState(DONE);
255 | hide();
256 | }
257 | }.sendEmptyMessageDelayed(0, 1000);
258 | } else
259 | {
260 | changeState(DONE);
261 | hide();
262 | }
263 | }
264 |
265 | /**
266 | * 加载完毕,显示加载结果。注意:加载完成后一定要调用这个方法
267 | *
268 | * @param refreshResult
269 | * PullToRefreshLayout.SUCCEED代表成功,PullToRefreshLayout.FAIL代表失败
270 | */
271 | public void loadmoreFinish(int refreshResult)
272 | {
273 | loadingView.clearAnimation();
274 | loadingView.setVisibility(View.GONE);
275 | switch (refreshResult)
276 | {
277 | case SUCCEED:
278 | // 加载成功
279 | loadStateImageView.setVisibility(View.VISIBLE);
280 | loadStateTextView.setText(R.string.load_succeed);
281 | loadStateImageView.setBackgroundResource(R.drawable.load_succeed);
282 | break;
283 | case FAIL:
284 | default:
285 | // 加载失败
286 | loadStateImageView.setVisibility(View.VISIBLE);
287 | loadStateTextView.setText(R.string.load_fail);
288 | loadStateImageView.setBackgroundResource(R.drawable.load_failed);
289 | break;
290 | }
291 | if (pullUpY < 0)
292 | {
293 | // 刷新结果停留1秒
294 | new Handler()
295 | {
296 | @Override
297 | public void handleMessage(Message msg)
298 | {
299 | changeState(DONE);
300 | hide();
301 | }
302 | }.sendEmptyMessageDelayed(0, 1000);
303 | } else
304 | {
305 | changeState(DONE);
306 | hide();
307 | }
308 | }
309 |
310 | private void changeState(int to)
311 | {
312 | state = to;
313 | switch (state)
314 | {
315 | case INIT:
316 | // 下拉布局初始状态
317 | refreshStateImageView.setVisibility(View.GONE);
318 | refreshStateTextView.setText(R.string.pull_to_refresh);
319 | pullView.clearAnimation();
320 | pullView.setVisibility(View.VISIBLE);
321 | // 上拉布局初始状态
322 | loadStateImageView.setVisibility(View.GONE);
323 | loadStateTextView.setText(R.string.pullup_to_load);
324 | pullUpView.clearAnimation();
325 | pullUpView.setVisibility(View.VISIBLE);
326 | break;
327 | case RELEASE_TO_REFRESH:
328 | // 释放刷新状态
329 | refreshStateTextView.setText(R.string.release_to_refresh);
330 | pullView.startAnimation(rotateAnimation);
331 | break;
332 | case REFRESHING:
333 | // 正在刷新状态
334 | pullView.clearAnimation();
335 | refreshingView.setVisibility(View.VISIBLE);
336 | pullView.setVisibility(View.INVISIBLE);
337 | refreshingView.startAnimation(refreshingAnimation);
338 | refreshStateTextView.setText(R.string.refreshing);
339 | break;
340 | case RELEASE_TO_LOAD:
341 | // 释放加载状态
342 | loadStateTextView.setText(R.string.release_to_load);
343 | pullUpView.startAnimation(rotateAnimation);
344 | break;
345 | case LOADING:
346 | // 正在加载状态
347 | pullUpView.clearAnimation();
348 | loadingView.setVisibility(View.VISIBLE);
349 | pullUpView.setVisibility(View.INVISIBLE);
350 | loadingView.startAnimation(refreshingAnimation);
351 | loadStateTextView.setText(R.string.loading);
352 | break;
353 | case DONE:
354 | // 刷新或加载完毕,啥都不做
355 | break;
356 | }
357 | }
358 |
359 | /**
360 | * 不限制上拉或下拉
361 | */
362 | private void releasePull()
363 | {
364 | canPullDown = true;
365 | canPullUp = true;
366 | }
367 |
368 | /*
369 | * (非 Javadoc)由父控件决定是否分发事件,防止事件冲突
370 | *
371 | * @see android.view.ViewGroup#dispatchTouchEvent(android.view.MotionEvent)
372 | */
373 | @Override
374 | public boolean dispatchTouchEvent(MotionEvent ev)
375 | {
376 | switch (ev.getActionMasked())
377 | {
378 | case MotionEvent.ACTION_DOWN:
379 | downY = ev.getY();
380 | lastY = downY;
381 | timer.cancel();
382 | mEvents = 0;
383 | releasePull();
384 | break;
385 | case MotionEvent.ACTION_POINTER_DOWN:
386 | case MotionEvent.ACTION_POINTER_UP:
387 | // 过滤多点触碰
388 | mEvents = -1;
389 | break;
390 | case MotionEvent.ACTION_MOVE:
391 | if (mEvents == 0)
392 | {
393 | if (pullDownY > 0
394 | || (((Pullable) pullableView).canPullDown()
395 | && canPullDown && state != LOADING))
396 | {
397 | // 可以下拉,正在加载时不能下拉
398 | // 对实际滑动距离做缩小,造成用力拉的感觉
399 | pullDownY = pullDownY + (ev.getY() - lastY) / radio;
400 | if (pullDownY < 0)
401 | {
402 | pullDownY = 0;
403 | canPullDown = false;
404 | canPullUp = true;
405 | }
406 | if (pullDownY > getMeasuredHeight())
407 | pullDownY = getMeasuredHeight();
408 | if (state == REFRESHING)
409 | {
410 | // 正在刷新的时候触摸移动
411 | isTouch = true;
412 | }
413 | } else if (pullUpY < 0
414 | || (((Pullable) pullableView).canPullUp() && canPullUp && state != REFRESHING))
415 | {
416 | // 可以上拉,正在刷新时不能上拉
417 | pullUpY = pullUpY + (ev.getY() - lastY) / radio;
418 | if (pullUpY > 0)
419 | {
420 | pullUpY = 0;
421 | canPullDown = true;
422 | canPullUp = false;
423 | }
424 | if (pullUpY < -getMeasuredHeight())
425 | pullUpY = -getMeasuredHeight();
426 | if (state == LOADING)
427 | {
428 | // 正在加载的时候触摸移动
429 | isTouch = true;
430 | }
431 | } else
432 | releasePull();
433 | } else
434 | mEvents = 0;
435 | lastY = ev.getY();
436 | // 根据下拉距离改变比例
437 | radio = (float) (2 + 2 * Math.tan(Math.PI / 2 / getMeasuredHeight()
438 | * (pullDownY + Math.abs(pullUpY))));
439 | if (pullDownY > 0 || pullUpY < 0)
440 | requestLayout();
441 | if (pullDownY > 0)
442 | {
443 | if (pullDownY <= refreshDist
444 | && (state == RELEASE_TO_REFRESH || state == DONE))
445 | {
446 | // 如果下拉距离没达到刷新的距离且当前状态是释放刷新,改变状态为下拉刷新
447 | changeState(INIT);
448 | }
449 | if (pullDownY >= refreshDist && state == INIT)
450 | {
451 | // 如果下拉距离达到刷新的距离且当前状态是初始状态刷新,改变状态为释放刷新
452 | changeState(RELEASE_TO_REFRESH);
453 | }
454 | } else if (pullUpY < 0)
455 | {
456 | // 下面是判断上拉加载的,同上,注意pullUpY是负值
457 | if (-pullUpY <= loadmoreDist
458 | && (state == RELEASE_TO_LOAD || state == DONE))
459 | {
460 | changeState(INIT);
461 | }
462 | // 上拉操作
463 | if (-pullUpY >= loadmoreDist && state == INIT)
464 | {
465 | changeState(RELEASE_TO_LOAD);
466 | }
467 |
468 | }
469 | // 因为刷新和加载操作不能同时进行,所以pullDownY和pullUpY不会同时不为0,因此这里用(pullDownY +
470 | // Math.abs(pullUpY))就可以不对当前状态作区分了
471 | if ((pullDownY + Math.abs(pullUpY)) > 8)
472 | {
473 | // 防止下拉过程中误触发长按事件和点击事件
474 | ev.setAction(MotionEvent.ACTION_CANCEL);
475 | }
476 | break;
477 | case MotionEvent.ACTION_UP:
478 | if (pullDownY > refreshDist || -pullUpY > loadmoreDist)
479 | // 正在刷新时往下拉(正在加载时往上拉),释放后下拉头(上拉头)不隐藏
480 | {
481 | isTouch = false;
482 | }
483 | if (state == RELEASE_TO_REFRESH)
484 | {
485 | changeState(REFRESHING);
486 | // 刷新操作
487 | if (mListener != null)
488 | mListener.onRefresh(this);
489 | } else if (state == RELEASE_TO_LOAD)
490 | {
491 | changeState(LOADING);
492 | // 加载操作
493 | if (mListener != null)
494 | mListener.onLoadMore(this);
495 | }
496 | hide();
497 | default:
498 | break;
499 | }
500 | // 事件分发交给父类
501 | super.dispatchTouchEvent(ev);
502 | return true;
503 | }
504 |
505 | /**
506 | * @author chenjing 自动模拟手指滑动的task
507 | *
508 | */
509 | private class AutoRefreshAndLoadTask extends
510 | AsyncTask
511 | {
512 |
513 | @Override
514 | protected String doInBackground(Integer... params)
515 | {
516 | while (pullDownY < 4 / 3 * refreshDist)
517 | {
518 | pullDownY += MOVE_SPEED;
519 | publishProgress(pullDownY);
520 | try
521 | {
522 | Thread.sleep(params[0]);
523 | } catch (InterruptedException e)
524 | {
525 | e.printStackTrace();
526 | }
527 | }
528 | return null;
529 | }
530 |
531 | @Override
532 | protected void onPostExecute(String result)
533 | {
534 | changeState(REFRESHING);
535 | // 刷新操作
536 | if (mListener != null)
537 | mListener.onRefresh(PullToRefreshLayout.this);
538 | hide();
539 | }
540 |
541 | @Override
542 | protected void onProgressUpdate(Float... values)
543 | {
544 | if (pullDownY > refreshDist)
545 | changeState(RELEASE_TO_REFRESH);
546 | requestLayout();
547 | }
548 |
549 | }
550 |
551 | /**
552 | * 自动刷新
553 | */
554 | public void autoRefresh()
555 | {
556 | AutoRefreshAndLoadTask task = new AutoRefreshAndLoadTask();
557 | task.execute(20);
558 | }
559 |
560 | /**
561 | * 自动加载
562 | */
563 | public void autoLoad()
564 | {
565 | pullUpY = -loadmoreDist;
566 | requestLayout();
567 | changeState(LOADING);
568 | // 加载操作
569 | if (mListener != null)
570 | mListener.onLoadMore(this);
571 | }
572 |
573 | private void initView()
574 | {
575 | // 初始化下拉布局
576 | pullView = refreshView.findViewById(R.id.pull_icon);
577 | refreshStateTextView = (TextView) refreshView
578 | .findViewById(R.id.state_tv);
579 | refreshingView = refreshView.findViewById(R.id.refreshing_icon);
580 | refreshStateImageView = refreshView.findViewById(R.id.state_iv);
581 | // 初始化上拉布局
582 | pullUpView = loadmoreView.findViewById(R.id.pullup_icon);
583 | loadStateTextView = (TextView) loadmoreView
584 | .findViewById(R.id.loadstate_tv);
585 | loadingView = loadmoreView.findViewById(R.id.loading_icon);
586 | loadStateImageView = loadmoreView.findViewById(R.id.loadstate_iv);
587 | }
588 |
589 | @Override
590 | protected void onLayout(boolean changed, int l, int t, int r, int b)
591 | {
592 | Log.d("Test", "Test");
593 | if (!isLayout)
594 | {
595 | // 这里是第一次进来的时候做一些初始化
596 | refreshView = getChildAt(0);
597 | pullableView = getChildAt(1);
598 | loadmoreView = getChildAt(2);
599 | isLayout = true;
600 | initView();
601 | refreshDist = ((ViewGroup) refreshView).getChildAt(0)
602 | .getMeasuredHeight();
603 | loadmoreDist = ((ViewGroup) loadmoreView).getChildAt(0)
604 | .getMeasuredHeight();
605 | }
606 | // 改变子控件的布局,这里直接用(pullDownY + pullUpY)作为偏移量,这样就可以不对当前状态作区分
607 | refreshView.layout(0,
608 | (int) (pullDownY + pullUpY) - refreshView.getMeasuredHeight(),
609 | refreshView.getMeasuredWidth(), (int) (pullDownY + pullUpY));
610 | pullableView.layout(0, (int) (pullDownY + pullUpY),
611 | pullableView.getMeasuredWidth(), (int) (pullDownY + pullUpY)
612 | + pullableView.getMeasuredHeight());
613 | loadmoreView.layout(0,
614 | (int) (pullDownY + pullUpY) + pullableView.getMeasuredHeight(),
615 | loadmoreView.getMeasuredWidth(),
616 | (int) (pullDownY + pullUpY) + pullableView.getMeasuredHeight()
617 | + loadmoreView.getMeasuredHeight());
618 | }
619 |
620 | class MyTimer
621 | {
622 | private Handler handler;
623 | private Timer timer;
624 | private MyTask mTask;
625 |
626 | public MyTimer(Handler handler)
627 | {
628 | this.handler = handler;
629 | timer = new Timer();
630 | }
631 |
632 | public void schedule(long period)
633 | {
634 | if (mTask != null)
635 | {
636 | mTask.cancel();
637 | mTask = null;
638 | }
639 | mTask = new MyTask(handler);
640 | timer.schedule(mTask, 0, period);
641 | }
642 |
643 | public void cancel()
644 | {
645 | if (mTask != null)
646 | {
647 | mTask.cancel();
648 | mTask = null;
649 | }
650 | }
651 |
652 | class MyTask extends TimerTask
653 | {
654 | private Handler handler;
655 |
656 | public MyTask(Handler handler)
657 | {
658 | this.handler = handler;
659 | }
660 |
661 | @Override
662 | public void run()
663 | {
664 | handler.obtainMessage().sendToTarget();
665 | }
666 |
667 | }
668 | }
669 |
670 | /**
671 | * 刷新加载回调接口
672 | *
673 | * @author chenjing
674 | *
675 | */
676 | public interface OnRefreshListener
677 | {
678 | /**
679 | * 刷新操作
680 | */
681 | void onRefresh(PullToRefreshLayout pullToRefreshLayout);
682 |
683 | /**
684 | * 加载操作
685 | */
686 | void onLoadMore(PullToRefreshLayout pullToRefreshLayout);
687 | }
688 |
689 | }
690 |
--------------------------------------------------------------------------------
/src/com/jingchen/pulltorefresh/activity/PullableExpandableListViewActivity.java:
--------------------------------------------------------------------------------
1 | package com.jingchen.pulltorefresh.activity;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.os.Bundle;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 | import android.widget.AdapterView;
10 | import android.widget.AdapterView.OnItemLongClickListener;
11 | import android.widget.BaseExpandableListAdapter;
12 | import android.widget.ExpandableListView;
13 | import android.widget.ExpandableListView.OnChildClickListener;
14 | import android.widget.ExpandableListView.OnGroupClickListener;
15 | import android.widget.TextView;
16 | import android.widget.Toast;
17 |
18 | import com.jingchen.pulltorefresh.MyListener;
19 | import com.jingchen.pulltorefresh.PullToRefreshLayout;
20 | import com.jingchen.pulltorefresh.R;
21 |
22 | public class PullableExpandableListViewActivity extends Activity
23 | {
24 | ExpandableListView expandableListView;
25 |
26 | @Override
27 | protected void onCreate(Bundle savedInstanceState)
28 | {
29 | super.onCreate(savedInstanceState);
30 | setContentView(R.layout.activity_expandablelistview);
31 | ((PullToRefreshLayout) findViewById(R.id.refresh_view))
32 | .setOnRefreshListener(new MyListener());
33 | expandableListView = (ExpandableListView) findViewById(R.id.content_view);
34 | initExpandableListView();
35 | }
36 |
37 | /**
38 | * ExpandableListView初始化方法
39 | */
40 | private void initExpandableListView()
41 | {
42 | expandableListView.setAdapter(new ExpandableListAdapter(this));
43 | expandableListView.setOnChildClickListener(new OnChildClickListener()
44 | {
45 |
46 | @Override
47 | public boolean onChildClick(ExpandableListView parent, View v,
48 | int groupPosition, int childPosition, long id)
49 | {
50 | Toast.makeText(
51 | PullableExpandableListViewActivity.this,
52 | " Click on group " + groupPosition + " item "
53 | + childPosition, Toast.LENGTH_SHORT).show();
54 | return true;
55 | }
56 | });
57 | expandableListView
58 | .setOnItemLongClickListener(new OnItemLongClickListener()
59 | {
60 |
61 | @Override
62 | public boolean onItemLongClick(AdapterView> parent,
63 | View view, int position, long id)
64 | {
65 | Toast.makeText(
66 | PullableExpandableListViewActivity.this,
67 | "LongClick on "
68 | + parent.getAdapter().getItemId(
69 | position), Toast.LENGTH_SHORT)
70 | .show();
71 | return true;
72 | }
73 | });
74 | expandableListView.setOnGroupClickListener(new OnGroupClickListener()
75 | {
76 |
77 | @Override
78 | public boolean onGroupClick(ExpandableListView parent, View v,
79 | int groupPosition, long id)
80 | {
81 | if (parent.isGroupExpanded(groupPosition))
82 | {
83 | // 如果展开则关闭
84 | parent.collapseGroup(groupPosition);
85 | } else
86 | {
87 | // 如果关闭则打开,注意这里是手动打开不要默认滚动否则会有bug
88 | parent.expandGroup(groupPosition);
89 | }
90 | return true;
91 | }
92 | });
93 | }
94 |
95 | class ExpandableListAdapter extends BaseExpandableListAdapter
96 | {
97 | private String[] groupsStrings;// = new String[] { "这里是group 0",
98 | // "这里是group 1", "这里是group 2" };
99 | private String[][] groupItems;
100 | private Context context;
101 |
102 | public ExpandableListAdapter(Context context)
103 | {
104 | this.context = context;
105 | groupsStrings = new String[8];
106 | for (int i = 0; i < groupsStrings.length; i++)
107 | {
108 | groupsStrings[i] = new String("这里是group " + i);
109 | }
110 | groupItems = new String[8][8];
111 | for (int i = 0; i < groupItems.length; i++)
112 | for (int j = 0; j < groupItems[i].length; j++)
113 | {
114 | groupItems[i][j] = new String("这里是group " + i + "里的item "
115 | + j);
116 | }
117 | }
118 |
119 | @Override
120 | public int getGroupCount()
121 | {
122 | return groupsStrings.length;
123 | }
124 |
125 | @Override
126 | public int getChildrenCount(int groupPosition)
127 | {
128 | return groupItems[groupPosition].length;
129 | }
130 |
131 | @Override
132 | public Object getGroup(int groupPosition)
133 | {
134 | return groupsStrings[groupPosition];
135 | }
136 |
137 | @Override
138 | public Object getChild(int groupPosition, int childPosition)
139 | {
140 | return groupItems[groupPosition][childPosition];
141 | }
142 |
143 | @Override
144 | public long getGroupId(int groupPosition)
145 | {
146 | return groupPosition;
147 | }
148 |
149 | @Override
150 | public long getChildId(int groupPosition, int childPosition)
151 | {
152 | return childPosition;
153 | }
154 |
155 | @Override
156 | public boolean hasStableIds()
157 | {
158 | return true;
159 | }
160 |
161 | @Override
162 | public View getGroupView(int groupPosition, boolean isExpanded,
163 | View convertView, ViewGroup parent)
164 | {
165 | View view = LayoutInflater.from(context).inflate(
166 | R.layout.list_item_layout, null);
167 | TextView tv = (TextView) view.findViewById(R.id.tv);
168 | tv.setText(groupsStrings[groupPosition]);
169 | return view;
170 | }
171 |
172 | @Override
173 | public View getChildView(int groupPosition, int childPosition,
174 | boolean isLastChild, View convertView, ViewGroup parent)
175 | {
176 | View view = LayoutInflater.from(context).inflate(
177 | R.layout.list_item_layout, null);
178 | TextView tv = (TextView) view.findViewById(R.id.tv);
179 | tv.setText(groupItems[groupPosition][childPosition]);
180 | return view;
181 | }
182 |
183 | @Override
184 | public boolean isChildSelectable(int groupPosition, int childPosition)
185 | {
186 | return true;
187 | }
188 |
189 | }
190 |
191 | }
192 |
--------------------------------------------------------------------------------
/src/com/jingchen/pulltorefresh/activity/PullableGridViewActivity.java:
--------------------------------------------------------------------------------
1 | package com.jingchen.pulltorefresh.activity;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | import android.app.Activity;
7 | import android.os.Bundle;
8 | import android.view.View;
9 | import android.widget.AdapterView;
10 | import android.widget.AdapterView.OnItemClickListener;
11 | import android.widget.AdapterView.OnItemLongClickListener;
12 | import android.widget.GridView;
13 | import android.widget.Toast;
14 |
15 | import com.jingchen.pulltorefresh.MyAdapter;
16 | import com.jingchen.pulltorefresh.MyListener;
17 | import com.jingchen.pulltorefresh.PullToRefreshLayout;
18 | import com.jingchen.pulltorefresh.R;
19 |
20 | public class PullableGridViewActivity extends Activity
21 | {
22 | GridView gridView;
23 |
24 | @Override
25 | protected void onCreate(Bundle savedInstanceState)
26 | {
27 | super.onCreate(savedInstanceState);
28 | setContentView(R.layout.activity_gridview);
29 | ((PullToRefreshLayout) findViewById(R.id.refresh_view))
30 | .setOnRefreshListener(new MyListener());
31 | gridView = (GridView) findViewById(R.id.content_view);
32 | initGridView();
33 | }
34 |
35 | /**
36 | * GridView初始化方法
37 | */
38 | private void initGridView()
39 | {
40 | List items = new ArrayList();
41 | for (int i = 0; i < 30; i++)
42 | {
43 | items.add("这里是item " + i);
44 | }
45 | MyAdapter adapter = new MyAdapter(this, items);
46 | gridView.setAdapter(adapter);
47 | gridView.setOnItemLongClickListener(new OnItemLongClickListener()
48 | {
49 |
50 | @Override
51 | public boolean onItemLongClick(AdapterView> parent, View view,
52 | int position, long id)
53 | {
54 | Toast.makeText(
55 | PullableGridViewActivity.this,
56 | "LongClick on "
57 | + parent.getAdapter().getItemId(position),
58 | Toast.LENGTH_SHORT).show();
59 | return true;
60 | }
61 | });
62 | gridView.setOnItemClickListener(new OnItemClickListener()
63 | {
64 |
65 | @Override
66 | public void onItemClick(AdapterView> parent, View view,
67 | int position, long id)
68 | {
69 | Toast.makeText(PullableGridViewActivity.this,
70 | " Click on " + parent.getAdapter().getItemId(position),
71 | Toast.LENGTH_SHORT).show();
72 | }
73 | });
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/com/jingchen/pulltorefresh/activity/PullableImageViewActivity.java:
--------------------------------------------------------------------------------
1 | package com.jingchen.pulltorefresh.activity;
2 |
3 | import com.jingchen.pulltorefresh.MyListener;
4 | import com.jingchen.pulltorefresh.PullToRefreshLayout;
5 | import com.jingchen.pulltorefresh.R;
6 |
7 | import android.app.Activity;
8 | import android.os.Bundle;
9 |
10 | public class PullableImageViewActivity extends Activity
11 | {
12 | @Override
13 | protected void onCreate(Bundle savedInstanceState)
14 | {
15 | super.onCreate(savedInstanceState);
16 | setContentView(R.layout.activity_imageview);
17 | ((PullToRefreshLayout) findViewById(R.id.refresh_view))
18 | .setOnRefreshListener(new MyListener());
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/com/jingchen/pulltorefresh/activity/PullableListViewActivity.java:
--------------------------------------------------------------------------------
1 | package com.jingchen.pulltorefresh.activity;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | import android.app.Activity;
7 | import android.os.Bundle;
8 | import android.view.View;
9 | import android.widget.AdapterView;
10 | import android.widget.AdapterView.OnItemClickListener;
11 | import android.widget.AdapterView.OnItemLongClickListener;
12 | import android.widget.ListView;
13 | import android.widget.Toast;
14 |
15 | import com.jingchen.pulltorefresh.MyAdapter;
16 | import com.jingchen.pulltorefresh.MyListener;
17 | import com.jingchen.pulltorefresh.PullToRefreshLayout;
18 | import com.jingchen.pulltorefresh.R;
19 |
20 | public class PullableListViewActivity extends Activity
21 | {
22 | private ListView listView;
23 | private PullToRefreshLayout ptrl;
24 | private boolean isFirstIn = true;
25 |
26 | @Override
27 | protected void onCreate(Bundle savedInstanceState)
28 | {
29 | super.onCreate(savedInstanceState);
30 | setContentView(R.layout.activity_listview);
31 | ptrl = ((PullToRefreshLayout) findViewById(R.id.refresh_view));
32 | ptrl.setOnRefreshListener(new MyListener());
33 | listView = (ListView) findViewById(R.id.content_view);
34 | initListView();
35 | }
36 |
37 | @Override
38 | public void onWindowFocusChanged(boolean hasFocus)
39 | {
40 | super.onWindowFocusChanged(hasFocus);
41 | // 第一次进入自动刷新
42 | if (isFirstIn)
43 | {
44 | ptrl.autoRefresh();
45 | isFirstIn = false;
46 | }
47 | }
48 |
49 | /**
50 | * ListView初始化方法
51 | */
52 | private void initListView()
53 | {
54 | List items = new ArrayList();
55 | for (int i = 0; i < 30; i++)
56 | {
57 | items.add("这里是item " + i);
58 | }
59 | MyAdapter adapter = new MyAdapter(this, items);
60 | listView.setAdapter(adapter);
61 | listView.setOnItemLongClickListener(new OnItemLongClickListener()
62 | {
63 |
64 | @Override
65 | public boolean onItemLongClick(AdapterView> parent, View view,
66 | int position, long id)
67 | {
68 | Toast.makeText(
69 | PullableListViewActivity.this,
70 | "LongClick on "
71 | + parent.getAdapter().getItemId(position),
72 | Toast.LENGTH_SHORT).show();
73 | return true;
74 | }
75 | });
76 | listView.setOnItemClickListener(new OnItemClickListener()
77 | {
78 |
79 | @Override
80 | public void onItemClick(AdapterView> parent, View view,
81 | int position, long id)
82 | {
83 | Toast.makeText(PullableListViewActivity.this,
84 | " Click on " + parent.getAdapter().getItemId(position),
85 | Toast.LENGTH_SHORT).show();
86 | }
87 | });
88 | }
89 |
90 | }
91 |
--------------------------------------------------------------------------------
/src/com/jingchen/pulltorefresh/activity/PullableScrollViewActivity.java:
--------------------------------------------------------------------------------
1 | package com.jingchen.pulltorefresh.activity;
2 |
3 | import com.jingchen.pulltorefresh.MyListener;
4 | import com.jingchen.pulltorefresh.PullToRefreshLayout;
5 | import com.jingchen.pulltorefresh.R;
6 |
7 | import android.app.Activity;
8 | import android.os.Bundle;
9 |
10 | public class PullableScrollViewActivity extends Activity
11 | {
12 | @Override
13 | protected void onCreate(Bundle savedInstanceState)
14 | {
15 | super.onCreate(savedInstanceState);
16 | setContentView(R.layout.activity_scrollview);
17 | ((PullToRefreshLayout) findViewById(R.id.refresh_view))
18 | .setOnRefreshListener(new MyListener());
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/com/jingchen/pulltorefresh/activity/PullableTextViewActivity.java:
--------------------------------------------------------------------------------
1 | package com.jingchen.pulltorefresh.activity;
2 |
3 | import com.jingchen.pulltorefresh.MyListener;
4 | import com.jingchen.pulltorefresh.PullToRefreshLayout;
5 | import com.jingchen.pulltorefresh.R;
6 |
7 | import android.app.Activity;
8 | import android.os.Bundle;
9 |
10 | public class PullableTextViewActivity extends Activity
11 | {
12 | @Override
13 | protected void onCreate(Bundle savedInstanceState)
14 | {
15 | super.onCreate(savedInstanceState);
16 | setContentView(R.layout.activity_textview);
17 | ((PullToRefreshLayout) findViewById(R.id.refresh_view))
18 | .setOnRefreshListener(new MyListener());
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/com/jingchen/pulltorefresh/activity/PullableWebViewActivity.java:
--------------------------------------------------------------------------------
1 | package com.jingchen.pulltorefresh.activity;
2 |
3 | import android.app.Activity;
4 | import android.os.Bundle;
5 | import android.webkit.WebView;
6 |
7 | import com.jingchen.pulltorefresh.MyListener;
8 | import com.jingchen.pulltorefresh.PullToRefreshLayout;
9 | import com.jingchen.pulltorefresh.R;
10 |
11 | public class PullableWebViewActivity extends Activity
12 | {
13 | WebView webView;
14 |
15 | @Override
16 | protected void onCreate(Bundle savedInstanceState)
17 | {
18 | super.onCreate(savedInstanceState);
19 | setContentView(R.layout.activity_webview);
20 | ((PullToRefreshLayout) findViewById(R.id.refresh_view))
21 | .setOnRefreshListener(new MyListener());
22 | webView = (WebView) findViewById(R.id.content_view);
23 | webView.loadUrl("http://blog.csdn.net/zhongkejingwang");
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/com/jingchen/pulltorefresh/pullableview/Pullable.java:
--------------------------------------------------------------------------------
1 | package com.jingchen.pulltorefresh.pullableview;
2 |
3 | public interface Pullable
4 | {
5 | /**
6 | * 判断是否可以下拉,如果不需要下拉功能可以直接return false
7 | *
8 | * @return true如果可以下拉否则返回false
9 | */
10 | boolean canPullDown();
11 |
12 | /**
13 | * 判断是否可以上拉,如果不需要上拉功能可以直接return false
14 | *
15 | * @return true如果可以上拉否则返回false
16 | */
17 | boolean canPullUp();
18 | }
19 |
--------------------------------------------------------------------------------
/src/com/jingchen/pulltorefresh/pullableview/PullableExpandableListView.java:
--------------------------------------------------------------------------------
1 | package com.jingchen.pulltorefresh.pullableview;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.widget.ExpandableListView;
6 |
7 | public class PullableExpandableListView extends ExpandableListView implements
8 | Pullable
9 | {
10 |
11 | public PullableExpandableListView(Context context)
12 | {
13 | super(context);
14 | }
15 |
16 | public PullableExpandableListView(Context context, AttributeSet attrs)
17 | {
18 | super(context, attrs);
19 | }
20 |
21 | public PullableExpandableListView(Context context, AttributeSet attrs,
22 | int defStyle)
23 | {
24 | super(context, attrs, defStyle);
25 | }
26 |
27 | @Override
28 | public boolean canPullDown()
29 | {
30 | if (getCount() == 0)
31 | {
32 | // 没有item的时候也可以下拉刷新
33 | return true;
34 | } else if (getFirstVisiblePosition() == 0
35 | && getChildAt(0).getTop() >= 0)
36 | {
37 | // 滑到顶部了
38 | return true;
39 | } else
40 | return false;
41 | }
42 |
43 | @Override
44 | public boolean canPullUp()
45 | {
46 | if (getCount() == 0)
47 | {
48 | // 没有item的时候也可以上拉加载
49 | return true;
50 | } else if (getLastVisiblePosition() == (getCount() - 1))
51 | {
52 | // 滑到底部了
53 | if (getChildAt(getLastVisiblePosition() - getFirstVisiblePosition()) != null
54 | && getChildAt(
55 | getLastVisiblePosition()
56 | - getFirstVisiblePosition()).getBottom() <= getMeasuredHeight())
57 | return true;
58 | }
59 | return false;
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/src/com/jingchen/pulltorefresh/pullableview/PullableGridView.java:
--------------------------------------------------------------------------------
1 | package com.jingchen.pulltorefresh.pullableview;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.widget.GridView;
6 |
7 | public class PullableGridView extends GridView implements Pullable
8 | {
9 |
10 | public PullableGridView(Context context)
11 | {
12 | super(context);
13 | }
14 |
15 | public PullableGridView(Context context, AttributeSet attrs)
16 | {
17 | super(context, attrs);
18 | }
19 |
20 | public PullableGridView(Context context, AttributeSet attrs, int defStyle)
21 | {
22 | super(context, attrs, defStyle);
23 | }
24 |
25 | @Override
26 | public boolean canPullDown()
27 | {
28 | if (getCount() == 0)
29 | {
30 | // 没有item的时候也可以下拉刷新
31 | return true;
32 | } else if (getFirstVisiblePosition() == 0
33 | && getChildAt(0).getTop() >= 0)
34 | {
35 | // 滑到顶部了
36 | return true;
37 | } else
38 | return false;
39 | }
40 |
41 | @Override
42 | public boolean canPullUp()
43 | {
44 | if (getCount() == 0)
45 | {
46 | // 没有item的时候也可以上拉加载
47 | return true;
48 | } else if (getLastVisiblePosition() == (getCount() - 1))
49 | {
50 | // 滑到底部了
51 | if (getChildAt(getLastVisiblePosition() - getFirstVisiblePosition()) != null
52 | && getChildAt(
53 | getLastVisiblePosition()
54 | - getFirstVisiblePosition()).getBottom() <= getMeasuredHeight())
55 | return true;
56 | }
57 | return false;
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/src/com/jingchen/pulltorefresh/pullableview/PullableImageView.java:
--------------------------------------------------------------------------------
1 | package com.jingchen.pulltorefresh.pullableview;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.widget.ImageView;
6 |
7 |
8 | public class PullableImageView extends ImageView implements Pullable
9 | {
10 |
11 | public PullableImageView(Context context)
12 | {
13 | super(context);
14 | }
15 |
16 | public PullableImageView(Context context, AttributeSet attrs)
17 | {
18 | super(context, attrs);
19 | }
20 |
21 | public PullableImageView(Context context, AttributeSet attrs, int defStyle)
22 | {
23 | super(context, attrs, defStyle);
24 | }
25 |
26 | @Override
27 | public boolean canPullDown()
28 | {
29 | return true;
30 | }
31 |
32 | @Override
33 | public boolean canPullUp()
34 | {
35 | return true;
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/src/com/jingchen/pulltorefresh/pullableview/PullableListView.java:
--------------------------------------------------------------------------------
1 | package com.jingchen.pulltorefresh.pullableview;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.util.Log;
6 | import android.widget.ListView;
7 |
8 | public class PullableListView extends ListView implements Pullable
9 | {
10 |
11 | public PullableListView(Context context)
12 | {
13 | super(context);
14 | }
15 |
16 | public PullableListView(Context context, AttributeSet attrs)
17 | {
18 | super(context, attrs);
19 | }
20 |
21 | public PullableListView(Context context, AttributeSet attrs, int defStyle)
22 | {
23 | super(context, attrs, defStyle);
24 | }
25 |
26 | @Override
27 | public boolean canPullDown()
28 | {
29 | if (getCount() == 0)
30 | {
31 | // 没有item的时候也可以下拉刷新
32 | return true;
33 | } else if (getFirstVisiblePosition() == 0
34 | && getChildAt(0).getTop() >= 0)
35 | {
36 | // 滑到ListView的顶部了
37 | return true;
38 | } else
39 | return false;
40 | }
41 |
42 | @Override
43 | public boolean canPullUp()
44 | {
45 | if (getCount() == 0)
46 | {
47 | // 没有item的时候也可以上拉加载
48 | return true;
49 | } else if (getLastVisiblePosition() == (getCount() - 1))
50 | {
51 | // 滑到底部了
52 | if (getChildAt(getLastVisiblePosition() - getFirstVisiblePosition()) != null
53 | && getChildAt(
54 | getLastVisiblePosition()
55 | - getFirstVisiblePosition()).getBottom() <= getMeasuredHeight())
56 | return true;
57 | }
58 | return false;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/com/jingchen/pulltorefresh/pullableview/PullableScrollView.java:
--------------------------------------------------------------------------------
1 | package com.jingchen.pulltorefresh.pullableview;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.widget.ScrollView;
6 |
7 | public class PullableScrollView extends ScrollView implements Pullable
8 | {
9 |
10 | public PullableScrollView(Context context)
11 | {
12 | super(context);
13 | }
14 |
15 | public PullableScrollView(Context context, AttributeSet attrs)
16 | {
17 | super(context, attrs);
18 | }
19 |
20 | public PullableScrollView(Context context, AttributeSet attrs, int defStyle)
21 | {
22 | super(context, attrs, defStyle);
23 | }
24 |
25 | @Override
26 | public boolean canPullDown()
27 | {
28 | if (getScrollY() == 0)
29 | return true;
30 | else
31 | return false;
32 | }
33 |
34 | @Override
35 | public boolean canPullUp()
36 | {
37 | if (getScrollY() >= (getChildAt(0).getHeight() - getMeasuredHeight()))
38 | return true;
39 | else
40 | return false;
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/src/com/jingchen/pulltorefresh/pullableview/PullableTextView.java:
--------------------------------------------------------------------------------
1 | package com.jingchen.pulltorefresh.pullableview;
2 |
3 |
4 | import android.content.Context;
5 | import android.util.AttributeSet;
6 | import android.widget.TextView;
7 |
8 | public class PullableTextView extends TextView implements Pullable
9 | {
10 |
11 | public PullableTextView(Context context)
12 | {
13 | super(context);
14 | }
15 |
16 | public PullableTextView(Context context, AttributeSet attrs)
17 | {
18 | super(context, attrs);
19 | }
20 |
21 | public PullableTextView(Context context, AttributeSet attrs, int defStyle)
22 | {
23 | super(context, attrs, defStyle);
24 | }
25 |
26 | @Override
27 | public boolean canPullDown()
28 | {
29 | return true;
30 | }
31 |
32 | @Override
33 | public boolean canPullUp()
34 | {
35 | return true;
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/src/com/jingchen/pulltorefresh/pullableview/PullableWebView.java:
--------------------------------------------------------------------------------
1 | package com.jingchen.pulltorefresh.pullableview;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.webkit.WebView;
6 |
7 | public class PullableWebView extends WebView implements Pullable
8 | {
9 |
10 | public PullableWebView(Context context)
11 | {
12 | super(context);
13 | }
14 |
15 | public PullableWebView(Context context, AttributeSet attrs)
16 | {
17 | super(context, attrs);
18 | }
19 |
20 | public PullableWebView(Context context, AttributeSet attrs, int defStyle)
21 | {
22 | super(context, attrs, defStyle);
23 | }
24 |
25 | @Override
26 | public boolean canPullDown()
27 | {
28 | if (getScrollY() == 0)
29 | return true;
30 | else
31 | return false;
32 | }
33 |
34 | @Override
35 | public boolean canPullUp()
36 | {
37 | if (getScrollY() >= getContentHeight() * getScale()
38 | - getMeasuredHeight())
39 | return true;
40 | else
41 | return false;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------