使用ScrollView实现下拉刷新(一)

来源:互联网 发布:弱矩阵 编辑:程序博客网 时间:2024/06/05 22:31

转载自:http://blog.csdn.net/a6920502/article/details/8759244


使用ListView来做下拉刷新有很多例子,而且封装的很好。

ListView有 header 但是如果不使用ListView的下拉刷新网上的例子相对来说比较少,于是自己动手写了个,原理差不多,主要都是在OnTouchListener

首先是Header的布局文件:

[html] view plaincopy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <!-- ListView的头部 -->  
  3. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  4.     android:id="@+id/head_rootLayout"  
  5.     android:layout_width="fill_parent"  
  6.     android:layout_height="wrap_content" >  
  7.   
  8.     <!-- 内容 -->  
  9.   
  10.     <RelativeLayout  
  11.         android:id="@+id/head_contentLayout"  
  12.         android:layout_width="fill_parent"  
  13.         android:layout_height="wrap_content"  
  14.         android:paddingLeft="30dp" >  
  15.   
  16.         <!-- 箭头图像、进度条 -->  
  17.   
  18.         <FrameLayout  
  19.             android:layout_width="wrap_content"  
  20.             android:layout_height="wrap_content"  
  21.             android:layout_alignParentLeft="true"  
  22.             android:layout_centerVertical="true" >  
  23.   
  24.             <!-- 箭头 -->  
  25.   
  26.             <ImageView  
  27.                 android:id="@+id/head_arrowImageView"  
  28.                 android:layout_width="wrap_content"  
  29.                 android:layout_height="wrap_content"  
  30.                 android:layout_gravity="center"  
  31.                 android:contentDescription="@string/app_name"  
  32.                 android:src="@drawable/head_arrow" />  
  33.             <!-- 进度条 -->  
  34.   
  35.             <ProgressBar  
  36.                 android:id="@+id/head_progressBar"  
  37.                 style="?android:attr/progressBarStyleSmall"  
  38.                 android:layout_width="wrap_content"  
  39.                 android:layout_height="wrap_content"  
  40.                 android:layout_gravity="center"  
  41.                 android:visibility="gone" />  
  42.         </FrameLayout>  
  43.         <!-- 提示、最近更新 -->  
  44.   
  45.         <LinearLayout  
  46.             android:layout_width="wrap_content"  
  47.             android:layout_height="wrap_content"  
  48.             android:layout_centerHorizontal="true"  
  49.             android:gravity="center_horizontal"  
  50.             android:orientation="vertical" >  
  51.   
  52.             <!-- 提示 -->  
  53.   
  54.             <TextView  
  55.                 android:id="@+id/head_tipsTextView"  
  56.                 android:layout_width="wrap_content"  
  57.                 android:layout_height="wrap_content"  
  58.                 android:text="@string/pulltorefresh"  
  59.                 android:textSize="20sp" />  
  60.             <!-- 最近更新 -->  
  61.   
  62.             <TextView  
  63.                 android:id="@+id/head_lastUpdatedTextView"  
  64.                 android:layout_width="wrap_content"  
  65.                 android:layout_height="wrap_content"  
  66.                 android:text="@string/lastupdate"  
  67.                 android:textColor="#cc6600"  
  68.                 android:textSize="12sp" />  
  69.         </LinearLayout>  
  70.     </RelativeLayout>  
  71.   
  72. </LinearLayout>  


Activity布局:

[html] view plaincopy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout  xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="fill_parent"  
  4.     android:layout_height="fill_parent"  
  5.     android:orientation="vertical"  
  6.     android:id="@+id/globleLayout">  
  7.   
  8.     <ScrollView  
  9.         android:id="@+id/scrollView"  
  10.         android:layout_width="fill_parent"  
  11.         android:layout_height="fill_parent" >  
  12. <span style="white-space:pre">  </span><!-- 这里放你想要放的布局 --!>  
  13.         <LinearLayout  
  14.             android:id="@+id/linearLayout"  
  15.             android:layout_width="fill_parent"  
  16.             android:layout_height="wrap_content"  
  17.             android:orientation="vertical" >  
  18.             <ImageView  
  19.                 android:layout_width="80dp"  
  20.                 android:layout_height="120dp"  
  21.                 android:src="@drawable/a" />  
  22.   
  23.             <ImageView  
  24.                 android:layout_width="80dp"  
  25.                 android:layout_height="120dp"  
  26.                 android:src="@drawable/b" />  
  27.   
  28.             <ImageView  
  29.                 android:layout_width="80dp"  
  30.                 android:layout_height="120dp"  
  31.                 android:src="@drawable/c" />  
  32.   
  33.             <ImageView  
  34.                 android:layout_width="80dp"  
  35.                 android:layout_height="120dp"  
  36.                 android:src="@drawable/d" />  
  37.   
  38.             <ImageView  
  39.                 android:layout_width="80dp"  
  40.                 android:layout_height="120dp"  
  41.                 android:src="@drawable/e" />  
  42.   
  43.             <ImageView  
  44.                 android:layout_width="80dp"  
  45.                 android:layout_height="120dp"  
  46.                 android:src="@drawable/f" />  
  47.              
  48.         </LinearLayout>  
  49.     </ScrollView>  
  50.   
  51. </LinearLayout>  

现在是Activity 的代码:

[java] view plaincopy
  1. package com.example.scrollviewtest;  
  2.   
  3. import java.util.Date;  
  4.   
  5. import android.app.Activity;  
  6. import android.content.Context;  
  7. import android.os.AsyncTask;  
  8. import android.os.Bundle;  
  9. import android.view.LayoutInflater;  
  10. import android.view.MotionEvent;  
  11. import android.view.View;  
  12. import android.view.View.MeasureSpec;  
  13. import android.view.View.OnTouchListener;  
  14. import android.view.ViewGroup;  
  15. import android.view.ViewGroup.LayoutParams;  
  16. import android.view.animation.LinearInterpolator;  
  17. import android.view.animation.RotateAnimation;  
  18. import android.widget.ImageView;  
  19. import android.widget.LinearLayout;  
  20. import android.widget.ProgressBar;  
  21. import android.widget.ScrollView;  
  22. import android.widget.TextView;  
  23.   
  24. public class MainActivity extends Activity {  
  25.     private ScrollView sc;  
  26.     private LinearLayout header;  
  27.     private ImageView arrowImg;  
  28.     private ProgressBar headProgress;  
  29.     private TextView lastUpdateTxt;  
  30.     private TextView tipsTxt;  
  31.     private RotateAnimation tipsAnimation;  
  32.     private RotateAnimation reverseAnimation;  
  33.     private LayoutInflater inflater;  
  34.     private LinearLayout globleLayout;  
  35.     private int headerHeight;   //头高度  
  36.     private int lastHeaderPadding; //最后一次调用Move Header的Padding  
  37.     private boolean isBack; //从Release 转到 pull  
  38.     private int headerState = DONE;  
  39.     static final private int RELEASE_To_REFRESH = 0;  
  40.     static final private int PULL_To_REFRESH = 1;  
  41.     static final private int REFRESHING = 2;  
  42.     static final private int DONE = 3;  
  43.     @Override  
  44.     protected void onCreate(Bundle savedInstanceState) {  
  45.         super.onCreate(savedInstanceState);  
  46.         setContentView(R.layout.activity_main);  
  47.         init(this);  
  48.     }  
  49.       
  50.     private void init(Context context) {  
  51.         globleLayout = (LinearLayout) findViewById(R.id.globleLayout);  
  52.         sc = (ScrollView) globleLayout.findViewById(R.id.scrollView);  
  53.         inflater = (LayoutInflater) this  
  54.                 .getSystemService(Context.LAYOUT_INFLATER_SERVICE);  
  55.           
  56.         header = (LinearLayout) inflater.inflate(R.layout.drag_drop_header, null);  
  57.         measureView(header);  
  58.         headerHeight = header.getMeasuredHeight();  
  59.         lastHeaderPadding = (-1*headerHeight); //最后一次调用Move Header的Padding  
  60.         header.setPadding(0, lastHeaderPadding, 00);  
  61.         header.invalidate();  
  62.         globleLayout.addView(header,0);  
  63.           
  64.         headProgress = (ProgressBar) findViewById(R.id.head_progressBar);  
  65.         arrowImg = (ImageView) findViewById(R.id.head_arrowImageView);  
  66.         arrowImg.setMinimumHeight(50);  
  67.         arrowImg.setMinimumWidth(50);  
  68.         tipsTxt = (TextView) findViewById(R.id.head_tipsTextView);  
  69.         lastUpdateTxt = (TextView) findViewById(R.id.head_lastUpdatedTextView);  
  70.         //箭头转动动画  
  71.         tipsAnimation = new RotateAnimation(0, -180,  
  72.                 RotateAnimation.RELATIVE_TO_SELF, 0.5f,  
  73.                 RotateAnimation.RELATIVE_TO_SELF, 0.5f);  
  74.         tipsAnimation.setInterpolator(new LinearInterpolator());  
  75.         tipsAnimation.setDuration(200);     //动画持续时间  
  76.         tipsAnimation.setFillAfter(true);   //动画结束后保持动画  
  77.         //箭头反转动画  
  78.         reverseAnimation = new RotateAnimation(-1800,  
  79.                 RotateAnimation.RELATIVE_TO_SELF, 0.5f,  
  80.                 RotateAnimation.RELATIVE_TO_SELF, 0.5f);  
  81.         reverseAnimation.setInterpolator(new LinearInterpolator());  
  82.         reverseAnimation.setDuration(200);  
  83.         reverseAnimation.setFillAfter(true);  
  84.         //为scrollview绑定事件  
  85.         sc.setOnTouchListener(new OnTouchListener() {  
  86.             private int beginY;  
  87.               
  88.             @Override  
  89.             public boolean onTouch(View v, MotionEvent event) {  
  90.   
  91.                 switch (event.getAction()) {  
  92.                 case MotionEvent.ACTION_MOVE:  
  93.                     //sc.getScrollY == 0  scrollview 滑动到头了   
  94.                     //lastHeaderPadding > (-1*headerHeight) 表示header还没完全隐藏起来时  
  95.                     //headerState != REFRESHING 当正在刷新时  
  96.                     if((sc.getScrollY() == 0 || lastHeaderPadding > (-1*headerHeight)) && headerState != REFRESHING) {  
  97.                         //拿到滑动的Y轴距离  
  98.                         int interval = (int) (event.getY() - beginY);  
  99.                         //是向下滑动而不是向上滑动  
  100.                         if (interval > 0) {  
  101.                             interval = interval/2;//下滑阻力  
  102.                             lastHeaderPadding = interval + (-1*headerHeight);  
  103.                             header.setPadding(0, lastHeaderPadding, 00);  
  104.                             if(lastHeaderPadding > 0) {  
  105.                                 //txView.setText("我要刷新咯");  
  106.                                 headerState = RELEASE_To_REFRESH;  
  107.                                 //是否已经更新了UI  
  108.                                 if(! isBack) {  
  109.                                     isBack = true;  //到了Release状态,如果往回滑动到了pull则启动动画  
  110.                                     changeHeaderViewByState();  
  111.                                 }  
  112.                             } else {  
  113.                                 headerState = PULL_To_REFRESH;  
  114.                                 changeHeaderViewByState();  
  115.                                 //txView.setText("看到我了哦");  
  116.                                 //sc.scrollTo(0, headerPadding);  
  117.                             }  
  118.                         }  
  119.                     }  
  120.                     break;  
  121.                 case MotionEvent.ACTION_DOWN:  
  122.                     //加上下滑阻力与实际滑动距离的差(大概值)  
  123.                     beginY = (int) ((int) event.getY() + sc.getScrollY()*1.5);  
  124.                     break;  
  125.                 case MotionEvent.ACTION_UP:  
  126.                     if (headerState != REFRESHING) {  
  127.                         switch (headerState) {  
  128.                         case DONE:  
  129.                             //什么也不干  
  130.                             break;  
  131.                         case PULL_To_REFRESH:  
  132.                             headerState = DONE;  
  133.                             lastHeaderPadding = -1*headerHeight;  
  134.                             header.setPadding(0, lastHeaderPadding, 00);  
  135.                             changeHeaderViewByState();  
  136.                             break;  
  137.                         case RELEASE_To_REFRESH:  
  138.                             isBack = false//准备开始刷新,此时将不会往回滑动  
  139.                             headerState = REFRESHING;  
  140.                             changeHeaderViewByState();  
  141.                             onRefresh();  
  142.                             break;  
  143.                         default:  
  144.                             break;  
  145.                         }  
  146.                     }  
  147.                     break;  
  148.                 }  
  149.                 //如果Header是完全被隐藏的则让ScrollView正常滑动,让事件继续否则的话就阻断事件  
  150.                 if(lastHeaderPadding > (-1*headerHeight) && headerState != REFRESHING) {  
  151.                     return true;  
  152.                 } else {  
  153.                     return false;  
  154.                 }  
  155.             }  
  156.         });  
  157.     }  
  158.   
  159.     private void changeHeaderViewByState() {  
  160.         switch (headerState) {  
  161.         case PULL_To_REFRESH:  
  162.             // 是由RELEASE_To_REFRESH状态转变来的  
  163.             if (isBack) {  
  164.                 isBack = false;  
  165.                 arrowImg.startAnimation(reverseAnimation);  
  166.                 tipsTxt.setText("下拉刷新");  
  167.             }  
  168.             tipsTxt.setText("下拉刷新");  
  169.             break;  
  170.         case RELEASE_To_REFRESH:  
  171.             arrowImg.setVisibility(View.VISIBLE);  
  172.             headProgress.setVisibility(View.GONE);  
  173.             tipsTxt.setVisibility(View.VISIBLE);  
  174.             lastUpdateTxt.setVisibility(View.VISIBLE);  
  175.             arrowImg.clearAnimation();  
  176.             arrowImg.startAnimation(tipsAnimation);  
  177.             tipsTxt.setText("松开刷新");  
  178.             break;  
  179.         case REFRESHING:  
  180.             lastHeaderPadding = 0;  
  181.             header.setPadding(0, lastHeaderPadding, 00);  
  182.             header.invalidate();  
  183.             headProgress.setVisibility(View.VISIBLE);  
  184.             arrowImg.clearAnimation();  
  185.             arrowImg.setVisibility(View.INVISIBLE);  
  186.             tipsTxt.setText("正在刷新...");  
  187.             lastUpdateTxt.setVisibility(View.VISIBLE);  
  188.             break;  
  189.         case DONE:  
  190.             lastHeaderPadding = -1 * headerHeight;  
  191.             header.setPadding(0, lastHeaderPadding, 00);  
  192.             header.invalidate();  
  193.             headProgress.setVisibility(View.GONE);  
  194.             arrowImg.clearAnimation();  
  195.             arrowImg.setVisibility(View.VISIBLE);  
  196.             tipsTxt.setText("下拉刷新");  
  197.             lastUpdateTxt.setVisibility(View.VISIBLE);  
  198.             break;  
  199.         default:  
  200.             break;  
  201.         }  
  202.     }  
  203.     private void onRefresh() {  
  204.         new AsyncTask<Void, Void, Void>() {  
  205.             protected Void doInBackground(Void... params) {  
  206.                 try {  
  207.                     Thread.sleep(2000);  
  208.                 } catch (Exception e) {  
  209.                     e.printStackTrace();  
  210.                 }  
  211.                 return null;  
  212.             }  
  213.   
  214.             @Override  
  215.             protected void onPostExecute(Void result) {  
  216.                 onRefreshComplete();  
  217.             }  
  218.   
  219.         }.execute(null);  
  220.     }  
  221.     public void onRefreshComplete() {  
  222.         headerState = DONE;  
  223.         lastUpdateTxt.setText("最近更新:" + new Date().toLocaleString());  
  224.         changeHeaderViewByState();  
  225.     }  
  226.     //由于OnCreate里面拿不到header的高度所以需要手动计算  
  227.     private void measureView(View childView) {  
  228.         LayoutParams p = childView.getLayoutParams();  
  229.         if (p == null) {  
  230.             p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,  
  231.                     ViewGroup.LayoutParams.WRAP_CONTENT);  
  232.         }  
  233.         int childWidthSpec = ViewGroup.getChildMeasureSpec(00 + 0, p.width);  
  234.         int height = p.height;  
  235.         int childHeightSpec;  
  236.         if (height > 0) {  
  237.             childHeightSpec = MeasureSpec.makeMeasureSpec(height,  
  238.                     MeasureSpec.EXACTLY);  
  239.         } else {  
  240.             childHeightSpec = MeasureSpec.makeMeasureSpec(0,  
  241.                     MeasureSpec.UNSPECIFIED);  
  242.         }  
  243.         childView.measure(childWidthSpec, childHeightSpec);  
  244.     }  
  245. }<span style="color: rgb(255, 0, 0);">  
  246. </span>  
0 0
原创粉丝点击