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

 

相信會碰到不少相似的需求,一個列表控件,而後控件上方的一個頭部須要自定義,這樣就很差有時候也不能加在列表控件的頭部了,那必須得嵌套一層scrollview了,沒毛病,那麼通常的列表控件都是有上拉下拉的操做,並且通常也是在 github 上找尋一個收藏量高的android

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

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

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

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

先看失敗的效果圖post

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

若是直接把上下拉控件包住頭部其實沒有問題,可是這樣你下拉的時候在頂端顯示效果,這樣頭部和直接加入到列表控件裏有什麼區別,因此從新建立了個類,從頭再來,好好在理理思路,先從簡單的開始,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

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

而後在github上又找了個下拉庫,收藏畢竟多spa

 

 結果不行了,上滑一小段距離,而後在下拉,結果拉不動了,直接就顯示了上拉效果,這顯然不正常,問題一個一個來解決,確定是有其它問題的,不過先把眼前的解決了才能下一步,要解決這個問題就得禁止 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

相關文章
相關標籤/搜索