相信會碰到不少相似的需求,一個列表控件,而後控件上方的一個頭部須要自定義,這樣就很差有時候也不能加在列表控件的頭部了,那必須得嵌套一層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 }
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 }
這個很簡單,主要的邏輯也就一個方法裏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 }
侵入式的下拉刷新的確麻煩不少,可是好在本身也都解決了,而有了這兩種方案不敢說每一個第三方庫都能通用,可是大部分均可以通用,只要懂得了其中的原理,本身稍加修改也行,畢竟第三方庫太多了,每一個庫都有它本身的自定義,因此仍是要根據獨特的狀況去修改
網上有些第三方的,可是也都是人家自定義從新作的,並不能完美的和第三方庫結合,因此不少時候與其苦苦找尋不如本身慢慢摸索,這樣不管是用別人的仍是本身定義都更加的瞭解原理,並且這種效果是很頻繁出如今項目中的,因此本身必須得搞懂才行,否則你下次種會遇到它的
前面命名有點亂,在這裏重新把代碼都貼一下,以避免搞混
侵入式和非侵入式
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); } } }
<?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); } } }
<?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