参考原文连接:http://blog.csdn.net/nono_love_lilith/article/details/7100845
先上图:
这里要用到的关键技术就是onTouch的拦截与分发,如果没有这个基础,先花一两分钟搞定消化我另外一篇文章:最快速掌握,及快速理解 onTouch 事件的拦截与分发 链接:http://blog.csdn.net/qishaohe/article/details/10221307
关键代码:RefreshableView.java
package com.qige.test;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.ScrollView;
import android.widget.Scroller;
import android.widget.TextView;
/**
* 刷新控制view
*
* @author Nono
*
*/
public class RefreshableView extends LinearLayout {
private static final String TAG = "RefreshableView";
private Scroller scroller;
private View refreshView;
private ImageView refreshIndicatorView;
private int refreshHeight = 80;
private ProgressBar bar;
private TextView downTextView;
private TextView timeTextView;
private RefreshListener refreshListener;
private String downTextString;
private String releaseTextString;
private Long refreshTime = null;
private int lastX;
private int lastY;
// 在刷新中标记
private boolean isRefreshing = false;
private Context mContext;
public RefreshableView(Context context) {
super(context);
mContext = context;
}
public RefreshableView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
init();
}
private void init() {
// TODO Auto-generated method stub
//滑动对象,
scroller = new Scroller(mContext);
//刷新视图顶端的的view
refreshView = LayoutInflater.from(mContext).inflate(R.layout.refresh_top_item, null);
//指示器view
refreshIndicatorView = (ImageView) refreshView.findViewById(R.id.indicator);
//刷新bar
bar = (ProgressBar) refreshView.findViewById(R.id.progress);
//下拉显示text
downTextView = (TextView) refreshView.findViewById(R.id.refresh_hint);
//下来显示时间
timeTextView = (TextView) refreshView.findViewById(R.id.refresh_time);
LayoutParams lp = new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, 0);
// 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);
}
/**
* 刷新
* @param time
*/
private void setRefreshText(String time) {
// TODO Auto-generated method stub
//timeTextView.setText(time);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int y= (int) event.getRawY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_MOVE:
Log.i(TAG, "ACTION_MOVE");
//y移动坐标
int m = y - lastY;
// if(((m < 6) && (m > -1)) || (!enterScrollState )){
doMovement(m);
// }
//记录下此刻y坐标
this.lastY = y;
break;
case MotionEvent.ACTION_UP:
Log.i(TAG, "ACTION_UP");
fling();
break;
}
return true;
}
/**
* up事件处理
*/
private void fling() {
// TODO Auto-generated method stub
LinearLayout.LayoutParams lp = (LayoutParams) refreshView.getLayoutParams();
Log.i(TAG, "fling()" + lp.height);
if(lp.height > refreshHeight){//拉到了触发可刷新事件
refresh();
}else{
returnInitState();
}
}
private void returnInitState() {
// TODO Auto-generated method stub
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)this.refreshView.getLayoutParams();
int i = lp.height;
scroller.startScroll(0, i, 0, -i);
invalidate();
}
private void refresh() {
// TODO Auto-generated method stub
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)this.refreshView.getLayoutParams();
int i = lp.height;
refreshIndicatorView.setVisibility(View.GONE);
bar.setVisibility(View.VISIBLE);
timeTextView.setVisibility(View.GONE);
downTextView.setText("正在刷新......");
scroller.startScroll(0, i, 0, refreshHeight-i);
invalidate();
if(refreshListener !=null){
refreshListener.onRefresh(this);
isRefreshing = true;
}
}
/**
*
*/
@Override
public void computeScroll() {
// TODO Auto-generated method stub
if(scroller.computeScrollOffset()){
int i = this.scroller.getCurrY();
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)this.refreshView.getLayoutParams();
int k = Math.max(i, 0);
lp.height = k;
Log.d(TAG, "执行computeScroll"+lp.height);
this.refreshView.setLayoutParams(lp);
this.refreshView.invalidate();
invalidate();
}
}
/**
* 下拉move事件处理
* @param moveY
*/
private void doMovement(int moveY) {
// TODO Auto-generated method stub
Log.d("RefreshableView", "执行doMovement");
LinearLayout.LayoutParams lp = (LayoutParams) refreshView.getLayoutParams();
if(lp.height>=0){
//获取view的高度
float f1 =lp.height;
float f2 = moveY * 0.3F;
int i = (int)(f1+f2);
//修改高度
if(i>0){
lp.height = i;
}else{
lp.height = 0;
}
Log.d("RefreshableView", lp.height+"");
//修改后刷新
refreshView.setLayoutParams(lp);
refreshView.invalidate();
invalidate();
}
// timeTextView.setVisibility(View.VISIBLE);
if(refreshTime!= null){
setRefreshTime(refreshTime);
}
if(lp.height>0){
refreshIndicatorView.setVisibility(View.VISIBLE);
downTextView.setVisibility(View.VISIBLE);
bar.setVisibility(View.GONE);
if(lp.height >= refreshHeight){
downTextView.setText(R.string.refresh_release_text);
refreshIndicatorView.setImageResource(R.drawable.refresh_arrow_up);
}else if(lp.height < refreshHeight ){
downTextView.setText(R.string.refresh_down_text);
refreshIndicatorView.setImageResource(R.drawable.refresh_arrow_down);
}
}else{
timeTextView.setVisibility(View.GONE);
refreshIndicatorView.setVisibility(View.GONE);
downTextView.setVisibility(View.GONE);
}
}
public void setRefreshListener(RefreshListener listener) {
this.refreshListener = listener;
}
/**
* 刷新时间
* @param refreshTime2
*/
private void setRefreshTime(Long time) {
// TODO Auto-generated method stub
}
/**
* 结束刷新事件
*/
public void finishRefresh(){
Log.i(TAG, "执行了=====finishRefresh");
LinearLayout.LayoutParams lp= (LinearLayout.LayoutParams)this.refreshView.getLayoutParams();
int i = lp.height;
refreshIndicatorView.setVisibility(View.GONE);
bar.setVisibility(View.GONE);
downTextView.setVisibility(View.GONE);
// timeTextView.setVisibility(View.VISIBLE);
scroller.startScroll(0, i, 0, -i);
invalidate();
isRefreshing = false;
}
/*该方法一般和ontouchEvent 一起用
* (non-Javadoc)
* @see android.view.ViewGroup#onInterceptTouchEvent(android.view.MotionEvent)
*/
@Override
public boolean onInterceptTouchEvent(MotionEvent e) {
// TODO Auto-generated method stub
int action = e.getAction();
int y= (int) e.getRawY();
switch (action) {
case MotionEvent.ACTION_DOWN:
lastY = y;
Log.d("onInterceptTouchEvent", "lastY:"+lastY);
break;
case MotionEvent.ACTION_MOVE:
//y移动坐标
int m = y - lastY;
Log.d("onInterceptTouchEvent", "ACTION_MOVE:"+m);
//记录下此刻y坐标
// this.lastY = y;
if(m > 6 && canScroll()){
return true;
}
break;
case MotionEvent.ACTION_UP:
break;
case MotionEvent.ACTION_CANCEL:
break;
}
return false;
}
private boolean canScroll() {
// TODO Auto-generated method stub
View childView;
if(getChildCount()>1){
childView = this.getChildAt(1);
if(childView instanceof ListView){
int top =((ListView)childView).getChildAt(0).getTop();
int pad =((ListView)childView).getListPaddingTop();
if((Math.abs(top-pad)) < 3&&
((ListView) childView).getFirstVisiblePosition() == 0){
return true;
}else{
return false;
}
}else if(childView instanceof GridView){
int top =((GridView)childView).getChildAt(0).getTop();
int pad =((GridView)childView).getListPaddingTop();
if((Math.abs(top-pad)) < 3&&
((GridView) childView).getFirstVisiblePosition() == 0){
return true;
}else{
return false;
}
}else if(childView instanceof ScrollView){
if(((ScrollView)childView).getScrollY() == 0){
return true;
}else{
return false;
}
}
}
return false;
}
/**
* 刷新监听接口
* @author Nono
*
*/
public interface RefreshListener{
public void onRefresh(RefreshableView 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="wrap_content"
android:gravity="center"
android:layout_gravity="center"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<ProgressBar
android:id="@+id/progress"
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"
/>
<TextView
android:id="@+id/refresh_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
测试代码:testActivity.java
package com.qige.test;
import javax.security.auth.PrivateCredentialPermission;
import com.qige.test.RefreshableView.RefreshListener;
import com.qige.test.SharedPreferencesHelper;
import android.app.Activity;
import android.app.Dialog;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.GestureDetector.OnGestureListener;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.AbsListView;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.GridView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ViewFlipper;
public class TestActivity extends Activity{
/** Called when the activity is first created. */
public static final String szSPName="com.kingsense.emenu.ui_preferences"; //sp名称
public static SharedPreferencesHelper sp=null;
Dialog initDataDialog;
private ListView dataList;
//private GridView dataGrid;
private BaseAdapter dataAdapter;
private String[] goods = {"商品一","商品二","商品三","商品四","商品午","商品六","商品七","商品一","商品二","商品三","商品四","商品午","商品六","商品七"};
private RefreshableView refreshableView;
//private String TAG = "slipMenu";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
dataList = (ListView)findViewById(R.id.data_list);
// dataGrid = (GridView) findViewById(R.id.data_grid);
refreshableView = (RefreshableView) findViewById(R.id.refresh_widget);
refreshableView.setRefreshListener(new RefreshListener() {
@Override
public void onRefresh(RefreshableView view) {
// TODO Auto-generated method stub
new AsyncTask<Object, Object, Object>(){
@Override
protected Object doInBackground(Object... params) {
// TODO Auto-generated method stub
try {
Thread.sleep(5*1000);
} catch (Exception e) {
// TODO: handle exception
}
return true;
}
@Override
protected void onPostExecute(Object result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
refreshableView.finishRefresh();
}
@Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
}
}.execute();
}
});
dataAdapter = new BaseAdapter() {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
TextView goodsView = new TextView(TestActivity.this);
goodsView.setText(goods[position]);
goodsView.setLayoutParams(new AbsListView.LayoutParams(AbsListView.LayoutParams.FILL_PARENT,80));
goodsView.setTextColor(getResources().getColor(R.color.text_color_white));
goodsView.setBackgroundColor(getResources().getColor(R.color.text_color_price));
return goodsView;
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return goods.length;
}
};
dataList.setAdapter(dataAdapter);
// dataGrid.setAdapter(dataAdapter);
dataAdapter.notifyDataSetChanged();
}
}
main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#fff">
<TextView android:layout_width="fill_parent"
android:layout_height="48dp"
android:text="菜品数据刷新"
android:gravity="center_horizontal"/>
<com.qige.test.RefreshableView
android:id="@+id/refresh_widget"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#ccc"
android:orientation="vertical"
>
<ListView
android:id="@+id/data_list"
android:layout_width="fill_parent"
android:scrollbars="none"
android:fadingEdge="none"
android:layout_height="wrap_content"
android:scrollingCache="false"
android:background="#ccc">
</ListView>
<!-- <GridView
android:id="@+id/data_grid"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:numColumns="3">
</GridView>
-->
</com.qige.test.RefreshableView>
</LinearLayout>
string.xml:
<string name="refresh_down_text">下拉刷新</string>
<string name="refresh_release_text">送开可刷新</string>