选择ViewGroup而不是单个View的理由就是通用性
下拉过程分为3个状态
1.下拉,未满足释放刷新的高度,显示“下拉刷新”

2.下拉,满足释放刷新的高度,显示“释放刷新”

3.释放,显示“刷新”

接着我们Touch事件 有
1. 按下
2.按下移动
3.松开
接着必须要知道的方法onInterceptTouchEvent,用于在OnTouchEvent之前截取一次事件
public boolean onInterceptTouchEvent(MotionEvent event)
return false;//表示未消费此事件,将事件传递下一层View
return true;//表示消费了此事件,将不再下传
用于主要的逻辑处理
public boolean onTouchEvent(MotionEvent event)
通过判断HeaderView的TopMargin来判断是否满足释放刷新条件
Code:
public class RefreshView extends LinearLayout{
private Scroller scroller;
private LinearLayout refreshView;
private ImageView refreshIndicatorView;
private int refreshTargetTop = -60;
private ProgressBar bar;
private TextView downTextView;
private TextView timeTextView;
private LinearLayout refereshLinearLayout;
private RefreshListener refreshListener;
private String downTextString;
private String releaseTextString;
private Long refreshTime = null;
private int lastX;
private int lastY;
private boolean isDragging = false;// 拉动标记
private boolean isRefreshEnabled = true;// 是否可刷新标记
private boolean isRefreshing = false;// 在刷新中标记
private Context mContext;
public RefreshView(Context context) {
// TODO Auto-generated constructor stub
this(context, null);
}
public RefreshView(Context context,AttributeSet attrs) {
super(context,attrs);
// TODO Auto-generated constructor stub
mContext = context;
init();
}
private void init(){
scroller = new Scroller(mContext);
refreshView =(LinearLayout)View.inflate(mContext, R.layout.refresh_top_item, null);
// 拉动时候的视图
refreshIndicatorView = (ImageView)refreshView.findViewById(R.id.indicator);
downTextView = (TextView)refreshView.findViewById(R.id.refresh_hint);
// 刷新时候的视图
refereshLinearLayout = (LinearLayout)refreshView
.findViewById(R.id.referesh_linearlayout);
bar = (ProgressBar)refreshView.findViewById(R.id.progress);
timeTextView =(TextView)refreshView.findViewById(R.id.refresh_time);
LayoutParams lp = new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT
, -refreshTargetTop);
lp.topMargin = refreshTargetTop;
lp.gravity = Gravity.CENTER;
addView(refreshView,lp);
downTextString = mContext.getResources()
.getString(R.string.refresh_down_text);
releaseTextString = mContext.getResources()
.getString(R.string.refresh_release_text);
}
// 首次截取 事件
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
int y = (int) event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
lastY = y;
break;
case MotionEvent.ACTION_MOVE:
int m = y - lastY;
lastY = y;
if(canScroll(m)){
return true;
}
break;
}
return false;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
if(isRefreshing) return false;
int y = (int) event.getY();
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
lastY = y;
break;
case MotionEvent.ACTION_MOVE:
int m = y - lastY;
doMovement(m);
lastY = y;
break;
case MotionEvent.ACTION_UP:
fling();
break;
}
return true;
}
private void fling(){
if(isRefreshing) return;
LinearLayout.LayoutParams lp = (LayoutParams)refreshView
.getLayoutParams();
if(lp.topMargin > 0){
refresh();
}else{
returnInitState();
}
}
private void returnInitState() {
// TODO Auto-generated method stub
LinearLayout.LayoutParams lp = (LayoutParams)refreshView
.getLayoutParams();
int i = lp.topMargin;
scroller.startScroll(0, i, 0, refreshTargetTop - i);// 回滚到初始状态
invalidate();
}
private void refresh() {
// TODO Auto-generated method stub
LinearLayout.LayoutParams lp = (LayoutParams)refreshView
.getLayoutParams();
int i = lp.topMargin;
refreshIndicatorView.setVisibility(View.GONE);
downTextView.setVisibility(View.GONE);
refereshLinearLayout.setVisibility(View.VISIBLE);
// 回滚到第一格位置
scroller.startScroll(0, i, 0, -i);
invalidate();
if(refreshListener != null){
refreshListener.onRefresh(this);
isRefreshing = true;
}
}
public void finishRefresh() {
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) this.refreshView
.getLayoutParams();
int i = lp.topMargin;
scroller.startScroll(0, i, 0, refreshTargetTop);
invalidate();
// refreshIndicatorView.setVisibility(View.VISIBLE);
// timeTextView.setVisibility(View.VISIBLE);
isRefreshing = false;
setRefreshDate(Calendar.getInstance().getTime());
}
@Override
public void computeScroll() {
// TODO Auto-generated method stub
//super.computeScroll();
if(scroller.computeScrollOffset()){
int i = this.scroller.getCurrY();
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) this.refreshView
.getLayoutParams();
lp.topMargin = i;
refreshView.setLayoutParams(lp);
refreshView.invalidate();
invalidate();
}
}
private void doMovement(int moveY){
LinearLayout.LayoutParams lp = (LayoutParams)refreshView.getLayoutParams();
lp.topMargin = (int)(lp.topMargin + moveY * 0.3);// 修改上边距
refreshView.setLayoutParams(lp);
refreshView.invalidate();
invalidate();
if(refreshTime != null) setRefreshTime(refreshTime);
downTextView.setVisibility(View.VISIBLE);
refreshIndicatorView.setVisibility(View.VISIBLE);
if(lp.topMargin > 0){
downTextView.setText(mContext.getResources().getString(R.string.refresh_release_text));
refreshIndicatorView.setImageResource(R.drawable.refresh_arrow_up);
}else{
downTextView.setText(mContext.getResources().getString(R.string.refresh_down_text));
refreshIndicatorView.setImageResource(R.drawable.refresh_arrow_down);
}
}
private void setRefreshTime(Long time){
refreshTime = time;
}
public void setRefreshEnabled(boolean b) {
this.isRefreshEnabled = b;
}
public void setRefreshListener(RefreshListener listener) {
this.refreshListener = listener;
}
private void setRefreshDate(Date date) {
SimpleDateFormat format = new SimpleDateFormat("MM-dd hh:mm");
timeTextView.setText("更新与:" + format.format(date));
}
private boolean canScroll(int moveY){
View childView;
if(moveY < 0){
return false;
}
if(getChildCount() > 1){
childView = this.getChildAt(1);
if(childView instanceof ListView){
if(((ListView) childView).getFirstVisiblePosition() == 0)
return true;
else
return false;
}else if (childView instanceof ScrollView){
if(((ScrollView)childView).getScrollY() == 0)
return true;
else
return false;
}else if(childView instanceof GridView){
if(((GridView) childView).getFirstVisiblePosition() == 0)
return true;
else
return false;
}
}
return true;
}
public interface RefreshListener {
public void onRefresh(RefreshView view);
}
}
refresh_top_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#EEEEEEEE"
android:orientation="vertical" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal" >
<ImageView
android:id="@+id/indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/refresh_hint"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:id="@+id/referesh_linearlayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1" />
<ProgressBar
android:id="@+id/progress"
style="?android:attr/progressBarStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="正在获取数据..." />
<TextView
android:id="@+id/refresh_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="更新与:" />
</LinearLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1" />
</LinearLayout>
</LinearLayout>
Adapter
import java.util.List;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
public class MyListAdapter extends BaseAdapter {
List<String> 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(list.size()-position-1);
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return list.size()-position-1;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView textview = new TextView(parent.getContext());
textview.setText(list.get(list.size()-position-1));
return textview;
}
public List<String> getList() {
return list;
}
public void setList(List<String> list) {
this.list = list;
}
}
Activity
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.widget.ListView;
import com.ishow.chenjq.RefreshView;
import com.ishow.chenjq.RefreshView.RefreshListener;;
public class MainActivity extends Activity {
private RefreshView refreshableLinearLayout;
private ListView listView;
private MyListAdapter adapter;
private List<String> list;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
preinitUI();
initUI();
}
private void preinitUI() {
adapter = new MyListAdapter();
list = new ArrayList<String>();
addLists(10);
adapter.setList(list);
}
private void initUI() {
setContentView(R.layout.referesh_view);
refreshableLinearLayout = (RefreshView) findViewById(R.id.refresh_root);
refreshableLinearLayout.setRefreshListener(listener);
listView = (ListView) findViewById(R.id.listview);
listView.setAdapter(adapter);
}
RefreshListener listener = new RefreshListener() {
@Override
public void onRefresh(RefreshView view) {
referesh();
}
};
protected void referesh() {
new AsyncTask<Void, Void, Void>() {
protected Void doInBackground(Void... params) {
try {
Thread.sleep(2000);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Void result) {
addLists(1);
refreshableLinearLayout.finishRefresh();
}
}.execute();
}
private void addLists(int n){
n += list.size();
for(int i=list.size();i<n;i++){
list.add("选项"+i);
}
}
}
Activity布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<com.ishow.chenjq.RefreshView
android:id="@+id/refresh_root"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ListView
android:id="@+id/listview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:paddingTop="100px"
android:paddingBottom="80px"
android:paddingRight="90px"
android:paddingLeft="10px"
android:cacheColorHint="@android:color/transparent"
android:descendantFocusability="blocksDescendants"
android:divider="#FFCC00"
android:dividerHeight="0dip" />
</com.ishow.chenjq.RefreshView>
</LinearLayout>
本文详细解析了如何使用通用的ViewGroup组件替代单个View来实现下拉刷新功能,包括下拉过程的三个状态、触摸事件处理、关键方法onInterceptTouchEvent和onTouchEvent的使用,以及具体的代码实现细节。
2万+

被折叠的 条评论
为什么被折叠?



