scrollview嵌套下拉控件嵌套recyclerview(不動第三方原基礎自定義)


 

相信會碰到很多類似的需求,一個列表控件,然后控件上方的一個頭部需要自定義,這樣就不好有時候也不能加在列表控件的頭部了,那必須得嵌套一層scrollview了,沒毛病,那么一般的列表控件都是有上拉下拉的操作,而且一般也是在 github 上找尋一個收藏量高的

來做為一個全局通用的上下拉控件,這里問題就來了,一般的 scrollview 嵌套 recyclerview 或者 listview 都畢竟容易解決,可是在加上一層上下拉控件呢?上下拉控件肯定會有它自己的觸摸處理機制,這樣你改起來也很麻煩,這種滑動觸摸的問題最是難搞,也有的是scrollview,或許網上有一些第三方庫已經有這個效果了,不過看了一些都是自定義的一些控件來解決的,而這里的雖然也是自定義,但是卻是用的一些流行庫在不動它原本的基礎上自定義

嵌套 viewpage 嵌套 recyclerview 的,不過這種效果網上還是有些方案的,搜索material design效果也有一些現成的,不過 scrollview 嵌套 SwipeRefreshLayout 嵌套 recyclerview 或者 scrollview 嵌套 PtrClassicFrameLayout 嵌套 recyclerview 很少,我搜了好久沒有滿足我需求的,而且很多是自定義了 recyclerview 和下拉控件才解決的,這樣的話它不是用的 github 原控件,可以說是自己寫的,可項目里很多都是有固定的一套第三方庫,你不能改,除非你是項目負責人,一開始就這樣規定了,不然就得想辦法去解決

還有一種網上的方案是退而求其次,用 NestedScrollView,不過這也有一些問題,就是下滑的時候對於侵入式的下拉方式有效果,可是對於非侵入刷新就不好使了,而且我個人也更喜歡非侵入刷新,所以花了些空閑的時間搗鼓了一個demo,解決了一個心頭之患,下次遇到就能輕松的對待了,不用在去糾結用這個庫是否會有問題了

一開始做的走了個誤區,沒有思考清楚,大致思路就是首先把下拉的控件禁止 setEnabled(false) ,然后scrollview攔截事件,判斷滑動,超出了頭部的距離就讓子控件滑動,這是一個大致的思路,然后就開干了,可想法是美好的,現實是殘酷的,並沒有取得成功,而且還把自己的思路攪渾了

先看失敗的效果圖

咋一看好像沒啥問題,而且簡單,這還說這么多做什么,其實只是效果沒有顯示出來(顯示不出來),這就尷尬了⊙﹏⊙‖∣

如果直接把上下拉控件包住頭部其實沒有問題,但是這樣你下拉的時候在頂端顯示效果,這樣頭部和直接加入到列表控件里有什么區別,所以重新創建了個類,從頭再來,好好在理理思路,先從簡單的開始,SwipeRefreshLayout 是android自帶的下拉刷新庫,而且是侵入式的下拉刷新,這樣處理起來更簡單,柿子挑軟的捏了,這樣都搞不定那就猝死在電腦邊吧,結果肯定是成功了,先看效果圖

this is scrollView其實就是一個固定的頭部,測試用的,可以換成自己的,而且還能根據滑動添加動畫,基本的需求都滿足了,直接看代碼,代碼粗糙了點
  1 package com.example.demo.test2;
  2 
  3 import android.os.Handler;
  4 import android.support.v4.widget.SwipeRefreshLayout;
  5 import android.support.v7.widget.LinearLayoutManager;
  6 import android.support.v7.widget.RecyclerView;
  7 import android.view.LayoutInflater;
  8 import android.view.View;
  9 import android.view.ViewGroup;
 10 import android.view.ViewTreeObserver;
 11 import android.widget.TextView;
 12 import android.widget.Toast;
 13 
 14 import com.example.demo.BaseActivity;
 15 import com.example.demo.R;
 16 
 17 import butterknife.BindView;
 18 
 19 public class Test3Activity extends BaseActivity {
 20 
 21     @BindView(R.id.scrollView)
 22     MyNestedScroll scrollView;
 23     @BindView(R.id.tv_head)
 24     TextView tv_head;
 25     @BindView(R.id.layout)
 26     SwipeRefreshLayout layout;
 27     @BindView(R.id.recyclerView)
 28     RecyclerView recyclerView;
 29     private boolean hasMeasured;
 30 
 31     @Override
 32     protected int getLayoutId() {
 33         return R.layout.activity_test3;
 34     }
 35 
 36     @Override
 37     protected void initView() {
 38         recyclerView.setLayoutManager(new LinearLayoutManager(Test3Activity.this));
 39         recyclerView.setAdapter(new ContentAdapter());
 40         ViewTreeObserver vto = tv_head.getViewTreeObserver();
 41         vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
 42             public boolean onPreDraw() {
 43                 if (hasMeasured == false) {
 44                     int height = tv_head.getMeasuredHeight();
 45                     scrollView.setHeadHeight(height);
 46                     hasMeasured = true;
 47                 }
 48                 return true;
 49             }
 50         });
 51         scrollView.getViewTreeObserver().addOnScrollChangedListener(new  ViewTreeObserver.OnScrollChangedListener() {
 52             @Override
 53             public void onScrollChanged() {
 54                 boolean b = scrollView.getScrollY()==0;
 55                 layout.setEnabled(b);
 56             }
 57         });
 58         //設置刷新時動畫的顏色,可以設置4個
 59         layout.setColorSchemeResources(android.R.color.holo_blue_light, android.R.color.holo_red_light,
 60                 android.R.color.holo_orange_light, android.R.color.holo_green_light);
 61         layout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
 62 
 63             @Override
 64             public void onRefresh() {
 65                 //正在刷新
 66                 // TODO Auto-generated method stub
 67                 new Handler().postDelayed(new Runnable() {
 68 
 69                     @Override
 70                     public void run() {
 71                         // TODO Auto-generated method stub
 72                         //刷新完成
 73                         layout.setRefreshing(false);
 74                     }
 75                 }, 500);
 76             }
 77         });
 78 
 79     }
 80 
 81     class ContentAdapter extends RecyclerView.Adapter {
 82         @Override
 83         public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
 84             return new ContentViewHolder(LayoutInflater.from(Test3Activity.this).inflate(R.layout.item_test, parent, false));
 85         }
 86 
 87         @Override
 88         public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
 89             final ContentViewHolder viewHolder = (ContentViewHolder) holder;
 90             viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
 91                 @Override
 92                 public void onClick(View view) {
 93                     Toast.makeText(Test3Activity.this, ""+position, Toast.LENGTH_SHORT).show();
 94                 }
 95             });
 96         }
 97 
 98         @Override
 99         public int getItemCount() {
100             return 15;
101         }
102     }
103 
104     class ContentViewHolder extends RecyclerView.ViewHolder {
105 
106         public ContentViewHolder(View itemView) {
107             super(itemView);
108         }
109     }
110 }
MainActivity
 1 package com.example.demo.test2;
 2 
 3 import android.content.Context;
 4 import android.util.AttributeSet;
 5 import android.view.MotionEvent;
 6 import android.widget.ScrollView;
 7 
 8 /**
 9  * Created by LiuZhen on 2017/6/8.
10  */
11 
12 public class MyNestedScroll extends ScrollView {
13 
14     private int headHeight = 300;//默認高度,一般動態設置
15     private int downY;
16 
17     public MyNestedScroll(Context context) {
18         super(context);
19     }
20 
21     public MyNestedScroll(Context context, AttributeSet attrs) {
22         super(context, attrs);
23     }
24 
25     public MyNestedScroll(Context context, AttributeSet attrs, int defStyleAttr) {
26         super(context, attrs, defStyleAttr);
27     }
28 
29     @Override
30     public boolean onInterceptTouchEvent(MotionEvent e) {
31         int action = e.getAction();
32         int dis = getScrollY();
33         switch (action) {
34             case MotionEvent.ACTION_DOWN:
35                 downY = (int) e.getRawY();
36                 break;
37             case MotionEvent.ACTION_MOVE:
38                 int moveY = (int) e.getRawY();
39                 /**判斷是向下滑動**/
40                 if(downY-moveY>0){
41                     if (dis < headHeight && dis >= 0){
42                         return true;//滑動距離小於頭部並且沒有超出頭部攔截事件,讓本身去滑動
43                     }else{
44                         return false;//不攔截事件
45                     }
46                 }else{
47                 }
48         }
49 
50         return super.onInterceptTouchEvent(e);
51     }
52 
53     public void setHeadHeight(int headHeight) {
54         this.headHeight = headHeight;
55     }
56 
57 }
MyNestedScroll

這個很簡單,主要的邏輯也就一個方法里

然后在github上又找了個下拉庫,收藏畢竟多

 

 結果不行了,上滑一小段距離,然后在下拉,結果拉不動了,直接就顯示了上拉效果,這顯然不正常,問題一個一個來解決,肯定是有其它問題的,不過先把眼前的解決了才能下一步,要解決這個問題就得禁止 PtrClassicFrameLayout 的下拉了,問題的根源很有可能是我們用的上下拉控件的滑動刷新效果起沖突了,最好的辦法肯定是直接禁止了,所以就給scrollview來個監聽 onScrollChanged ,獲取scrollview的scrolly,如果scrolly是0,就不禁止,因為在頂部了,不是0就禁止下拉操作,結果好了,可惜新的問題來了,上拉沒反應了,因為被禁止了,所以需要判斷滑動到了底部讓下拉效果出現

 

 於是有了這么兩個判斷,然后肯定還是有問題的,上拉效果沒事了,下拉效果出事了,滑動到頂端的時候下拉效果直接出現了,這樣頭部都顯示不出來了,而此時事件處於子列表控件,所以scrollview不好去監聽了,只得在 recyclerView 上面下手了,需要監聽滑動到頂部,然后禁止上下拉效果,交給scrollview滑動,讓頭部顯示出來

可是這樣一來發現還是那樣,而調試發現的確觸發了事件,可是為什么上下拉還是沒有禁止呢,這樣滑動不出頭部,然后調試發現被下面的 scrollview 的 onScrollChanged 事件里覆蓋了,又設置回去了,所以還得控制一下這里,讓scrollview的監聽不要覆蓋上面的設置,這里只是下拉的時候才會用到,所以就有了dy這個全局參數,這樣一來就ok了

  1 package com.example.demo.test2;
  2 
  3 import android.os.Handler;
  4 import android.support.v4.widget.NestedScrollView;
  5 import android.support.v4.widget.SwipeRefreshLayout;
  6 import android.support.v7.widget.LinearLayoutManager;
  7 import android.support.v7.widget.RecyclerView;
  8 import android.util.Log;
  9 import android.view.LayoutInflater;
 10 import android.view.MotionEvent;
 11 import android.view.View;
 12 import android.view.ViewGroup;
 13 import android.view.ViewTreeObserver;
 14 import android.widget.ScrollView;
 15 import android.widget.TextView;
 16 import android.widget.Toast;
 17 
 18 import com.example.demo.BaseActivity;
 19 import com.example.demo.R;
 20 import com.example.demo.test2.MyRecyclerView;
 21 
 22 import butterknife.BindView;
 23 import in.srain.cube.views.ptr.PtrClassicFrameLayout;
 24 import in.srain.cube.views.ptr.PtrDefaultHandler2;
 25 import in.srain.cube.views.ptr.PtrFrameLayout;
 26 
 27 public class Test2Activity extends BaseActivity {
 28 
 29     @BindView(R.id.scrollView)
 30     MyNestedScroll scrollView;
 31     @BindView(R.id.tv_head)
 32     TextView tv_head;
 33     @BindView(R.id.layout)
 34     PtrClassicFrameLayout layout;
 35     @BindView(R.id.recyclerView)
 36     RecyclerView recyclerView;
 37     private boolean hasMeasured;
 38     int height,dy;
 39 
 40     @Override
 41     protected int getLayoutId() {
 42         return R.layout.activity_test2;
 43     }
 44 
 45     @Override
 46     protected void initView() {
 47         final LinearLayoutManager manager = new LinearLayoutManager(Test2Activity.this);
 48         recyclerView.setLayoutManager(manager);
 49         recyclerView.setAdapter(new ContentAdapter());
 50         ViewTreeObserver vto = tv_head.getViewTreeObserver();
 51         vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
 52             public boolean onPreDraw() {
 53                 if (hasMeasured == false) {
 54                     height = tv_head.getMeasuredHeight();
 55                     scrollView.setHeadHeight(height);//設置頭部的高度
 56                     hasMeasured = true;
 57                 }
 58                 return true;
 59             }
 60         });
 61 
 62         recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
 63             @Override
 64             public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
 65 
 66 //                int visibleItemCount = manager.getChildCount();
 67 //                int totalItemCount = manager.getItemCount();
 68                 int pastVisiblesItems = manager.findFirstVisibleItemPosition();
 69                 Test2Activity.this.dy = dy;
 70                 //小於0表示下拉滑動,下拉到頂端則禁止子控件刷新,讓scrollview滑動,頭部完全顯示后才能下拉,這里只做下滑到頂部時禁止立刻刷新,讓scrollview滑動
 71                 if ( pastVisiblesItems == 0 && dy < 0) {
 72                     Log.e("onScrolled","dy "+dy);
 73                     layout.setEnabled(false);
 74                 }
 75             }
 76         });
 77         scrollView.getViewTreeObserver().addOnScrollChangedListener(new  ViewTreeObserver.OnScrollChangedListener() {
 78             @Override
 79             public void onScrollChanged() {
 80                 //滑動的距離超出頭部,讓列表控件自己滑動,dy大於0是上滑操作,這里只做滑動超出頭部后交給子列表滑動
 81                 boolean b = scrollView.getScrollY()==0;//上拉一段距離后下拉,結果直接下拉效果出現了,滑動失效
 82                 //解決上拉滑動到底部后讓上拉效果有用
 83                 if (scrollView != null && scrollView.getMeasuredHeight() <= scrollView.getScrollY()+height && dy >= 0) {
 84                     b = true;
 85 //                    Log.e("Changed","true ");
 86                 }
 87                 layout.setEnabled(b);
 88                 Log.e("Changed",""+b+" - scrollView.getScrollY "+scrollView.getScrollY());
 89             }
 90         });
 91         layout.setLastUpdateTimeRelateObject(this);
 92         layout.setPtrHandler(new PtrDefaultHandler2() {
 93 
 94             @Override
 95             public void onLoadMoreBegin(PtrFrameLayout frame) {
 96                 updateData();
 97             }
 98 
 99             @Override
100             public void onRefreshBegin(PtrFrameLayout frame) {
101                 updateData();
102             }
103 
104             @Override
105             public boolean checkCanDoLoadMore(PtrFrameLayout frame, View content, View footer) {
106                 return super.checkCanDoLoadMore(frame, recyclerView, footer);
107             }
108 
109             @Override
110             public boolean checkCanDoRefresh(PtrFrameLayout frame, View content, View header) {
111                 return super.checkCanDoRefresh(frame, recyclerView, header);
112             }
113         });
114 
115         layout.postDelayed(new Runnable() {
116             @Override
117             public void run() {
118                 // mPtrFrame.autoRefresh();
119             }
120         }, 100);
121 
122 
123     }
124 
125     protected void updateData() {
126 
127         layout.postDelayed(new Runnable() {
128             @Override
129             public void run() {
130                 layout.refreshComplete();
131             }
132         }, 1000);
133     }
134 
135     class ContentAdapter extends RecyclerView.Adapter {
136         @Override
137         public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
138             return new ContentViewHolder(LayoutInflater.from(Test2Activity.this).inflate(R.layout.item_test, parent, false));
139         }
140 
141         @Override
142         public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
143             final ContentViewHolder viewHolder = (ContentViewHolder) holder;
144             viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
145                 @Override
146                 public void onClick(View view) {
147                     Toast.makeText(Test2Activity.this, ""+position, Toast.LENGTH_SHORT).show();
148                 }
149             });
150         }
151 
152         @Override
153         public int getItemCount() {
154             return 15;
155         }
156     }
157 
158     class ContentViewHolder extends RecyclerView.ViewHolder {
159 
160         public ContentViewHolder(View itemView) {
161             super(itemView);
162         }
163     }
164 }
MainActivity

侵入式的下拉刷新的確麻煩很多,但是好在自己也都解決了,而有了這兩種方案不敢說每個第三方庫都能通用,但是大部分都可以通用,只要懂得了其中的原理,自己稍加修改也行,畢竟第三方庫太多了,每個庫都有它自己的自定義,所以還是要根據獨特的情況去修改

 

網上有些第三方的,但是也都是人家自定義重新做的,並不能完美的和第三方庫結合,所以很多時候與其苦苦找尋不如自己慢慢摸索,這樣無論是用別人的還是自己定義都更加的了解原理,而且這種效果是很頻繁出現在項目中的,所以自己必須得搞懂才行,不然你下次種會遇到它的

 

前面命名有點亂,在這里從新把代碼都貼一下,以免搞混

侵入式和非侵入式

import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.TextView;
import android.widget.Toast;

import com.example.demo.BaseActivity;
import com.example.demo.R;

import butterknife.BindView;
import in.srain.cube.views.ptr.PtrClassicFrameLayout;
import in.srain.cube.views.ptr.PtrDefaultHandler2;
import in.srain.cube.views.ptr.PtrFrameLayout;

public class PtrClassicFrameScrollViewActivity extends BaseActivity {

    @BindView(R.id.scrollView)
    MyNestedScroll scrollView;
    @BindView(R.id.tv_head)
    TextView tv_head;
    @BindView(R.id.layout)
    PtrClassicFrameLayout layout;
    @BindView(R.id.recyclerView)
    RecyclerView recyclerView;
    private boolean hasMeasured;
    int height,dy;

    @Override
    protected int getLayoutId() {
        return R.layout.activity_ptr;
    }

    @Override
    protected void initView() {
        final LinearLayoutManager manager = new LinearLayoutManager(context);
        recyclerView.setLayoutManager(manager);
        recyclerView.setAdapter(new ContentAdapter());
        ViewTreeObserver vto = tv_head.getViewTreeObserver();
        vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
            public boolean onPreDraw() {
                if (hasMeasured == false) {
                    height = tv_head.getMeasuredHeight();
                    scrollView.setHeadHeight(height);//設置頭部的高度
                    hasMeasured = true;
                }
                return true;
            }
        });

        recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {

//                int visibleItemCount = manager.getChildCount();
//                int totalItemCount = manager.getItemCount();
                int pastVisiblesItems = manager.findFirstVisibleItemPosition();
                PtrClassicFrameScrollViewActivity.this.dy = dy;
                //小於0表示下拉滑動,下拉到頂端則禁止子控件刷新,讓scrollview滑動,頭部完全顯示后才能下拉,這里只做下滑到頂部時禁止立刻刷新,讓scrollview滑動
                if ( pastVisiblesItems == 0 && dy < 0) {
                    Log.e("onScrolled","dy "+dy);
                    layout.setEnabled(false);
                }
            }
        });
        scrollView.getViewTreeObserver().addOnScrollChangedListener(new  ViewTreeObserver.OnScrollChangedListener() {
            @Override
            public void onScrollChanged() {
                //滑動的距離超出頭部,讓列表控件自己滑動,dy大於0是上滑操作,這里只做滑動超出頭部后交給子列表滑動
                boolean b = scrollView.getScrollY()==0;//上拉一段距離后下拉,結果直接下拉效果出現了,滑動失效
                //解決上拉滑動到底部后讓上拉效果有用
                if (scrollView != null && scrollView.getMeasuredHeight() <= scrollView.getScrollY()+height && dy >= 0) {
                    b = true;
//                    Log.e("Changed","true ");
                }
                layout.setEnabled(b);
//                Log.e("Changed",""+b+" - scrollView.getScrollY "+scrollView.getScrollY());
            }
        });
        layout.setLastUpdateTimeRelateObject(this);
        layout.setPtrHandler(new PtrDefaultHandler2() {

            @Override
            public void onLoadMoreBegin(PtrFrameLayout frame) {
                updateData();
            }

            @Override
            public void onRefreshBegin(PtrFrameLayout frame) {
                updateData();
            }

            @Override
            public boolean checkCanDoLoadMore(PtrFrameLayout frame, View content, View footer) {
                return super.checkCanDoLoadMore(frame, recyclerView, footer);
            }

            @Override
            public boolean checkCanDoRefresh(PtrFrameLayout frame, View content, View header) {
                return super.checkCanDoRefresh(frame, recyclerView, header);
            }
        });

        layout.postDelayed(new Runnable() {
            @Override
            public void run() {
                // mPtrFrame.autoRefresh();
            }
        }, 100);


    }

    protected void updateData() {

        layout.postDelayed(new Runnable() {
            @Override
            public void run() {
                layout.refreshComplete();
            }
        }, 1000);
    }

    class ContentAdapter extends RecyclerView.Adapter {
        @Override
        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            return new ContentViewHolder(LayoutInflater.from(PtrClassicFrameScrollViewActivity.this).inflate(R.layout.item_test, parent, false));
        }

        @Override
        public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
            final ContentViewHolder viewHolder = (ContentViewHolder) holder;
            viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Toast.makeText(context, ""+position, Toast.LENGTH_SHORT).show();
                }
            });
        }

        @Override
        public int getItemCount() {
            return 15;
        }
    }

    class ContentViewHolder extends RecyclerView.ViewHolder {

        public ContentViewHolder(View itemView) {
            super(itemView);
        }
    }
}
PtrClassicFrameScrollViewActivity
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <com.example.demo.MyNestedScroll
        android:id="@+id/scrollView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <TextView
                android:id="@+id/tv_head"
                android:layout_width="match_parent"
                android:layout_height="300dp"
                android:background="#ffffff"
                android:focusable="true"
                android:focusableInTouchMode="true"
                android:gravity="center"
                android:text="this is scrollView" />

            <in.srain.cube.views.ptr.PtrClassicFrameLayout
                xmlns:cube_ptr="http://schemas.android.com/apk/res-auto"
                android:id="@+id/layout"
                android:layout_width="match_parent"
                android:layout_height="600dp"
                android:background="#ffffff"
                cube_ptr:ptr_duration_to_close_either="1000"
                cube_ptr:ptr_keep_header_when_refresh="true"
                cube_ptr:ptr_pull_to_fresh="false"
                cube_ptr:ptr_ratio_of_header_height_to_refresh="1.2"
                cube_ptr:ptr_resistance="1.7">

                <android.support.v7.widget.RecyclerView
                    android:id="@+id/recyclerView"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent" />

            </in.srain.cube.views.ptr.PtrClassicFrameLayout>
        </LinearLayout>
    </com.example.demo.MyNestedScroll>

</FrameLayout>
import android.os.Handler;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.TextView;
import android.widget.Toast;

import com.example.demo.BaseActivity;
import com.example.demo.R;

import butterknife.BindView;

public class SwipeRefreshScrollViewActivity extends BaseActivity {

    @BindView(R.id.scrollView)
    MyNestedScroll scrollView;
    @BindView(R.id.tv_head)
    TextView tv_head;
    @BindView(R.id.layout)
    SwipeRefreshLayout layout;
    @BindView(R.id.recyclerView)
    RecyclerView recyclerView;
    private boolean hasMeasured;

    @Override
    protected int getLayoutId() {
        return R.layout.activity_swipe;
    }

    @Override
    protected void initView() {
        recyclerView.setLayoutManager(new LinearLayoutManager(SwipeRefreshScrollViewActivity.this));
        recyclerView.setAdapter(new ContentAdapter());
        ViewTreeObserver vto = tv_head.getViewTreeObserver();
        vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
            public boolean onPreDraw() {
                if (hasMeasured == false) {
                    int height = tv_head.getMeasuredHeight();
                    scrollView.setHeadHeight(height);
                    hasMeasured = true;
                }
                return true;
            }
        });
        scrollView.getViewTreeObserver().addOnScrollChangedListener(new  ViewTreeObserver.OnScrollChangedListener() {
            @Override
            public void onScrollChanged() {
                boolean b = scrollView.getScrollY()==0;
                layout.setEnabled(b);
            }
        });
        //設置刷新時動畫的顏色,可以設置4個
        layout.setColorSchemeResources(android.R.color.holo_blue_light, android.R.color.holo_red_light,
                android.R.color.holo_orange_light, android.R.color.holo_green_light);
        layout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {

            @Override
            public void onRefresh() {
                //正在刷新
                // TODO Auto-generated method stub
                new Handler().postDelayed(new Runnable() {

                    @Override
                    public void run() {
                        // TODO Auto-generated method stub
                        //刷新完成
                        layout.setRefreshing(false);
                    }
                }, 500);
            }
        });

    }

    class ContentAdapter extends RecyclerView.Adapter {
        @Override
        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            return new ContentViewHolder(LayoutInflater.from(SwipeRefreshScrollViewActivity.this).inflate(R.layout.item_test, parent, false));
        }

        @Override
        public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
            final ContentViewHolder viewHolder = (ContentViewHolder) holder;
            viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Toast.makeText(SwipeRefreshScrollViewActivity.this, ""+position, Toast.LENGTH_SHORT).show();
                }
            });
        }

        @Override
        public int getItemCount() {
            return 15;
        }
    }

    class ContentViewHolder extends RecyclerView.ViewHolder {

        public ContentViewHolder(View itemView) {
            super(itemView);
        }
    }
}
SwipeRefreshScrollViewActivity
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <com.example.demo.MyNestedScroll
        android:id="@+id/scrollView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <TextView
                android:id="@+id/tv_head"
                android:layout_width="match_parent"
                android:layout_height="300dp"
                android:background="#ffffff"
                android:focusable="true"
                android:focusableInTouchMode="true"
                android:gravity="center"
                android:text="this is scrollView" />

            <android.support.v4.widget.SwipeRefreshLayout
                android:id="@+id/layout"
                android:layout_width="match_parent"
                android:layout_height="800dp"
                android:background="#ffffff">

                <android.support.v7.widget.RecyclerView
                    android:id="@+id/recyclerView"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent" />

            </android.support.v4.widget.SwipeRefreshLayout>
        </LinearLayout>
    </com.example.demo.MyNestedScroll>

</android.support.constraint.ConstraintLayout>

 github下載地址:https://github.com/1024477951/ScrollPullView


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM