Android--GirdView下拉刷新功能

網上很少有關於GridView的下拉刷新數據,搜了一些解決方案,很多方法看起來很複雜,自己也沒有看懂(本人屬於頭腦笨的那種),不過這段文字給了我點啓發“具有下拉刷新功能的ListView/gridview其實也沒什麼複雜的,就是加一個head,然後判斷當前gridview時候拖動到了頂端,然後根據像下拖曳的距離與head的高度做對比以設置head的狀態(下拉刷新、鬆開刷新、還是隱藏掉等)”。其實GridView實現下拉刷新類似ListView是比較困難的最主要的原因是gridView沒有addHeaderView方法,這也是爲什麼網上很少有關於GirdView的相關代碼,自己無意中按照上面那段話的啓示,把上一篇PullToRefreshListView類以及Activity裏面的佈局略加修改,在手機一運行居然實現了,把我樂的要命,給大家展示一下,代碼和ListView實現類似,代碼紅色部分爲不同處,大家看一下就知道比較簡單了(想想,很多事情都是相通的)。
 

Android--GirdView下拉刷新功能

Android--GirdView下拉刷新功能

Android--GirdView下拉刷新功能

Android--GirdView下拉刷新功能

Android--GirdView下拉刷新功能
 

//PullToRefreshGridView類複寫GridView,與ListView的PullToRefreshListView沒有多少區別,最主要的原因是gridView沒有addHeaderView方法,所以只能在GridView之前加head佈局,其他與ListView都是一樣的

packagesrc.com.lyg.refreshlist;

importjava.text.SimpleDateFormat;

importjava.util.Date;

 

importsrc.com.lyg.R;

importandroid.content.Context;

importandroid.util.AttributeSet;

importandroid.util.Log;

importandroid.view.LayoutInflater;

importandroid.view.MotionEvent;

importandroid.view.View;

importandroid.view.ViewGroup;

importandroid.view.animation.LinearInterpolator;

importandroid.view.animation.RotateAnimation;

importandroid.widget.AbsListView;

importandroid.widget.AbsListView.OnScrollListener;

importandroid.widget.BaseAdapter;

importandroid.widget.GridView;

importandroid.widget.ImageView;

importandroid.widget.LinearLayout;

importandroid.widget.ProgressBar;

importandroid.widget.TextView;

 

 

 

public classPullToRefreshGridView extends GridView implementsOnScrollListener {

 

   private static final String TAG ="listview";

   private final static intRELEASE_To_REFRESH = 0; // 釋放

   private final static intPULL_To_REFRESH = 1;// 下拉刷新

   private final static intREFRESHING = 2; // 正在刷新

   private final static int DONE =3; // 按下

   private final static int LOADING= 4;

   // 實際的padding的距離與界面上偏移距離的比例

   private final static int RATIO =3;

   private LayoutInflater inflater;

   private LinearLayout headView;

   private TextView tipsTextview;

   private TextView lastUpdatedTextView;

   private ImageView arrowImageView;

   private ProgressBar progressBar;

   private RotateAnimation animation;

   private RotateAnimation reverseAnimation;

   // 用於保證startY的值在一個完整的touch事件中只被記錄一次

   private boolean isRecored;

   private int headContentWidth;

   private int headContentHeight;

   private int startY;

   private int firstItemIndex;

   private int state;

   private boolean isBack;

   private OnRefreshListener refreshListener;

   private boolean isRefreshable;

   public PullToRefreshGridViewActivity context;

 

 

 publicPullToRefreshGridView(Context context){ 

    super(context);

    this.context=(PullToRefreshGridViewActivity)context;

    init(context); 

      } 

 

   public PullToRefreshGridView(Context context, AttributeSetattrs) { 

      super(context, attrs);

      this.context=(PullToRefreshGridViewActivity)context;

       init(context); 

   }

   

   public View getView(){

   return headView;

   }

   

      private void init(Context context){ 

 

      //setCacheColorHint(context.getResources().getColor(R.color.transparent));

 

      inflater = LayoutInflater.from(context);

      // head 佈局文件

      headView = (LinearLayout) inflater.inflate(R.layout.head,null);

      // 下拉箭頭

      arrowImageView = (ImageView) headView.findViewById(R.id.head_arrowImageView);

      arrowImageView.setMinimumWidth(70);

      arrowImageView.setMinimumHeight(50);

      // 進度條

      progressBar = (ProgressBar) headView.findViewById(R.id.head_progressBar);

      // 下拉提示 刷新

      tipsTextview = (TextView)headView.findViewById(R.id.head_tipsTextView);

      //最新一次刷新時間

      lastUpdatedTextView = (TextView)headView.findViewById(R.id.head_lastUpdatedTextView);

       //計算head的高寬

      measureView(headView);

      headContentHeight = headView.getMeasuredHeight();

      headContentWidth = headView.getMeasuredWidth();

      //初始狀態是 隱藏掉head 佈局

      headView.setPadding(0, -1 * headContentHeight, 0, 0);

      headView.invalidate();

        Log.v("size", "width:" + headContentWidth + " height:" +headContentHeight);  

        setOnScrollListener(this);

        //下拉以及恢復動畫

        animation = new RotateAnimation(0, -180,RotateAnimation.RELATIVE_TO_SELF,0.5f,RotateAnimation.RELATIVE_TO_SELF,0.5f); 

            animation.setInterpolator(newLinearInterpolator()); 

            animation.setDuration(250); 

            animation.setFillAfter(true); 

           reverseAnimation = new RotateAnimation(-180,0, 

                    RotateAnimation.RELATIVE_TO_SELF,0.5f, 

                    RotateAnimation.RELATIVE_TO_SELF,0.5f); 

          reverseAnimation.setInterpolator(newLinearInterpolator()); 

          reverseAnimation.setDuration(200); 

          reverseAnimation.setFillAfter(true); 

          state = DONE

          isRefreshable = false

    } 

      public void onScroll(AbsListView arg0, intfirstVisiableItem, int arg2, int arg3){ 

         firstItemIndex = firstVisiableItem; 

        } 

      public void onScrollStateChanged(AbsListView arg0,int arg1) { 

      } 

 

   public boolean onTouchEvent(MotionEvent event){

 

      if (isRefreshable) {

          switch (event.getAction()) {

          // 在down時候記錄當前Y的位置

          case MotionEvent.ACTION_DOWN:

             if (firstItemIndex == 0 &&!isRecored) {

                 isRecored = true;

                 startY = (int) event.getY();

                 Log.v(TAG, "在down時候記錄當前位置‘");

             }

             break;

          case MotionEvent.ACTION_UP:

             if (state != REFRESHING&& state != LOADING){

                 if (state == DONE) {

                    // 什麼都不做

                 }

                 //由下拉刷新狀態,到done狀態

                 if (state == PULL_To_REFRESH) {

                    state = DONE;

                    changeHeaderViewByState();

                    Log.v(TAG, "由下拉刷新狀態,到done狀態");

                 }

 

                 if (state == RELEASE_To_REFRESH) {

                    state = REFRESHING;

                    changeHeaderViewByState();

                    onRefresh();

                    Log.v(TAG, "由鬆開刷新狀態,到done狀態");

                 }

             }

             isRecored = false;

             isBack = false;

             break;

 

          case MotionEvent.ACTION_MOVE:

             int tempY = (int) event.getY();

             if (!isRecored &&firstItemIndex == 0) {

                 Log.v(TAG, "在move時候記錄下位置");

                 isRecored = true;

                 startY = tempY;

             }

             if (state != REFRESHING&& isRecored&& state != LOADING){

                 //保證在設置padding的過程中,當前的位置一直是在head,否則如果當列表超出屏幕的話,當在上推的時候,列表會同時進行滾動

                // 可以鬆手去刷新了

                 if (state == RELEASE_To_REFRESH) {

                    setSelection(0);

                    // 往上推了,推到了屏幕足夠掩蓋head的程度,但是還沒有推到全部掩蓋的地步

                    if (((tempY - startY) / RATIO <headContentHeight)

                    && (tempY - startY)> 0) {

                        state = PULL_To_REFRESH;

                        changeHeaderViewByState();

                        Log.v(TAG, "由鬆開刷新狀態轉變到下拉刷新狀態");

                    }

                    // 一下子推到頂了

                    else if (tempY - startY <= 0){

                        state = DONE;

                        changeHeaderViewByState();

                        Log.v(TAG, "由鬆開刷新狀態轉變到done狀態");

                    }

                    // 往下拉了,或者還沒有上推到屏幕頂部掩蓋head的地步

                    else {

                        // 不用進行特別的操作,只用更新paddingTop的值就行了

                    }

                 }

                 // 還沒有到達顯示鬆開刷新的時候,DONE或者是PULL_To_REFRESH狀態

                 if (state == PULL_To_REFRESH) {

                    setSelection(0);

                    // 下拉到可以進入RELEASE_TO_REFRESH的狀態

                    if ((tempY - startY) / RATIO >=headContentHeight) {

                        state = RELEASE_To_REFRESH;

                        isBack = true;

                        changeHeaderViewByState();

                        Log.v(TAG, "由done或者下拉刷新狀態轉變到鬆開刷新");

                    }

                    // 上推到頂了

                    else if (tempY - startY <= 0){

                        state = DONE;

                        changeHeaderViewByState();

                        Log.v(TAG, "由DOne或者下拉刷新狀態轉變到done狀態");

                    }

                 }

                 // done狀態下

                 if (state == DONE) {

                    if (tempY - startY > 0) {

                        state = PULL_To_REFRESH;

                        changeHeaderViewByState();

                    }

                 }

                 // 更新headView的size

 

                 if (state == PULL_To_REFRESH) {

                    headView.setPadding(0, -1 * headContentHeight

                    + (tempY - startY) / RATIO, 0, 0);

                 }

                 // 更新headView的paddingTop

                 if (state == RELEASE_To_REFRESH) {

                    headView.setPadding(0, (tempY - startY) / RATIO

                           - headContentHeight, 0, 0);

                 }

             }

             break;

          }

      }

      return super.onTouchEvent(event);

   }

   

       private void changeHeaderViewByState(){ 

            switch (state) {

            //鬆開刷新狀態

             case RELEASE_To_REFRESH

                arrowImageView.setVisibility(View.VISIBLE); 

               progressBar.setVisibility(View.GONE); 

               tipsTextview.setVisibility(View.VISIBLE); 

               lastUpdatedTextView.setVisibility(View.VISIBLE);     

               arrowImageView.clearAnimation(); 

               arrowImageView.startAnimation(animation);     

                tipsTextview.setText("鬆開刷新");     

                Log.v(TAG, "當前狀態,鬆開刷新"); 

                break

                //下拉刷新

            case PULL_To_REFRESH

                progressBar.setVisibility(View.GONE); 

                tipsTextview.setVisibility(View.VISIBLE); 

                lastUpdatedTextView.setVisibility(View.VISIBLE); 

                arrowImageView.clearAnimation(); 

                 arrowImageView.setVisibility(View.VISIBLE); 

               // 是由RELEASE_To_REFRESH狀態轉變來的

                 //箭頭反轉向上

              if (isBack) { 

                   isBack= false

                   arrowImageView.clearAnimation(); 

                    arrowImageView.startAnimation(reverseAnimation); 

                    tipsTextview.setText("下拉刷新"); 

               } else

                    tipsTextview.setText("下拉刷新"); 

                } 

              Log.v(TAG, "當前狀態,下拉刷新"); 

              break

              //刷新中 狀態

          case REFRESHING:     

                headView.setPadding(0, 0, 0, 0);      

               progressBar.setVisibility(View.VISIBLE); 

              arrowImageView.clearAnimation(); 

              arrowImageView.setVisibility(View.GONE); 

              tipsTextview.setText("正在刷新..."); 

               lastUpdatedTextView.setVisibility(View.VISIBLE);    

               Log.v(TAG,"當前狀態,正在刷新..."); 

               break;

               //刷新完畢

           case DONE

              headView.setPadding(0, -1 * headContentHeight, 0,0); 

              progressBar.setVisibility(View.GONE); 

               arrowImageView.clearAnimation();  

            arrowImageView.setImageResource(R.drawable.goicon); 

                tipsTextview.setText("下拉刷新"); 

               lastUpdatedTextView.setVisibility(View.VISIBLE);     

                Log.v(TAG, "當前狀態,done"); 

               break

           } 

       } 

       public void setonRefreshListener(OnRefreshListenerrefreshListener) { 

 

            this.refreshListener =refreshListener; 

 

            isRefreshable = true

 

       }      

        public interface OnRefreshListener{ 

            public void onRefresh(); 

        }    

      public void onRefreshComplete(){ 

           state = DONE

            SimpleDateFormat format=newSimpleDateFormat("yyyy年MM月dd日 HH:mm"); 

            String date=format.format(newDate()); 

           lastUpdatedTextView.setText("最近更新:"+ date); 

           changeHeaderViewByState(); 

        } 

        private void onRefresh(){ 

          if (refreshListener != null){ 

               refreshListener.onRefresh(); 

          } 

        }  

       //此方法直接照搬自網絡上的一個下拉刷新的demo,此處是“估計”headView的width以及height 

        private void measureView(View child){ 

           ViewGroup.LayoutParams p =child.getLayoutParams(); 

              if (p == null) { 

                   p = new ViewGroup.LayoutParams( 

                          ViewGroup.LayoutParams.FILL_PARENT

                           ViewGroup.LayoutParams.WRAP_CONTENT); 

               } 

            int childWidthSpec = ViewGroup.getChildMeasureSpec(0,0 + 0, p.width); 

              int lpHeight = p.height; 

               int childHeightSpec; 

               if (lpHeight > 0){ 

                   childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight,MeasureSpec.EXACTLY); 

            } else

              childHeightSpec = MeasureSpec.makeMeasureSpec(0,MeasureSpec.UNSPECIFIED); 

               } 

                child.measure(childWidthSpec,childHeightSpec); 

      } 

       public void setAdapter(BaseAdapter adapter){ 

           SimpleDateFormat format=newSimpleDateFormat("yyyy年MM月dd日 HH:mm"); 

          String date=format.format(newDate()); 

           lastUpdatedTextView.setText("最近更新:" +date); 

          super.setAdapter(adapter); 

        } 

}

 

//activity裏面的實現,紅色是與ListView的不同方式,其他的都是類似

 

//packagesrc.com.lyg.refreshlist;

 

importjava.util.ArrayList;

importjava.util.HashMap;

importjava.util.List;

 

importsrc.com.lyg.R;

importsrc.com.lyg.refreshlist.PullToRefreshGridView.OnRefreshListener;

importandroid.app.Activity;

importandroid.os.AsyncTask;

importandroid.os.Bundle;

importandroid.view.Gravity;

importandroid.widget.FrameLayout.LayoutParams;

importandroid.widget.LinearLayout;

importandroid.widget.SimpleAdapter;

 

public classPullToRefreshGridViewActivity extends Activity {

   private SimpleAdapter citySimpleAdapter;

   public static LinearLayout head;

   String[] areaName = new String[] { "南京", "蘇州", "無錫", "南通","徐州", "常州",

          "揚州", "泰州", "鹽城", "鎮江", "淮安", "連雲港", "宿遷" };

   // 存放13個城市

   private List<HashMap<String,String>> cityList = newArrayList<HashMap<String,String>>();

 

   public void onCreate(Bundle savedInstanceState){

      super.onCreate(savedInstanceState);

      setContentView(R.layout.grid_main);

      //數據模擬  城市初始化

      for (int i = 0; i < areaName.length *6; i++) {

          HashMap<String, String> hashMap =new HashMap<String,String>();

          hashMap.put("id", String.valueOf(i));

          hashMap.put("name", areaName[i % 13].toString());

          cityList.add(hashMap);

      }

      final PullToRefreshGridView gridView =(PullToRefreshGridView)findViewById(R.id.order_form_grid);

      head = (LinearLayout)findViewById(R.id.head);

      LayoutParams p = newLayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT,Gravity.CENTER);

      //獲取PullToRefreshGridView裏面的head佈局

      head.addView(gridView.getView(), p);

      citySimpleAdapter = new SimpleAdapter(this,cityList,

             R.layout.weather_textview, new String[] { "name"},

             new int[] { R.id.txtRepDlgCity });

      gridView.setAdapter(citySimpleAdapter);

      gridView.setonRefreshListener(new OnRefreshListener(){

          public void onRefresh() {

             new AsyncTask<Void, Void,Void>() {

                 protected Void doInBackground(Void... params) {

                    try {

                        Thread.sleep(1000);

                    } catch (Exception e) {

                        e.printStackTrace();

                    }

                    HashMap<String, String> hashMap =new HashMap<String,String>();

                    hashMap.put("id",String.valueOf(cityList.size()));

                    hashMap.put("name","刷新新增城市");

                    cityList.add(0,hashMap);

                    return null;

                 }

 

                 @Override

                 protected void onPostExecute(Void result){

                    citySimpleAdapter.notifyDataSetChanged();

                    gridView.onRefreshComplete();

                 }

             }.execute();

          }

      });

   }

}

//Activity裏面的XML文件在PullToRefreshGridView之前加了一個LinearLayout,用來添加從PullToRefreshGridView類中獲取到的head佈局

<?xmlversion="1.0"encoding="utf-8"?>

<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"

   android:layout_width="fill_parent"

   android:layout_height="fill_parent"

   android:orientation="vertical" >

 

   <TextView

       android:layout_width="fill_parent"

       android:layout_height="50dp"

       android:gravity="center"

       android:text="GridView下拉刷新測試"/>

 

   <LinearLayout

       android:id="@+id/head"

       android:layout_width="fill_parent"

       android:layout_height="wrap_content">

   </LinearLayout>

 

   <src.com.lyg.refreshlist.PullToRefreshGridView

       android:id="@+id/order_form_grid"

       android:layout_width="fill_parent"

       android:layout_height="wrap_content"

       android:background="@android:color/darker_gray"

       android:cacheColorHint="#00000000"

       android:gravity="center"

       android:horizontalSpacing="5dp"

       android:numColumns="2"

       android:paddingLeft="10dp"

       android:paddingRight="20dp"

       android:stretchMode="columnWidth"

       android:verticalSpacing="5dp" >

   </src.com.lyg.refreshlist.PullToRefreshGridView>

</LinearLayout>

發佈了25 篇原創文章 · 獲贊 5 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章