当前位置:网站首页>Swiperefreshlayout+recyclerview failed to pull down troubleshooting
Swiperefreshlayout+recyclerview failed to pull down troubleshooting
2022-06-25 08:39:00 【Shen Ye】
background
stay Android In development ,SwipeRefreshLayout
+RecyclerView
Of UI The pattern helps developers easily provide the ability of pull-down refresh , But in previous development , I met a SwipeRefreshLayout Problems that cannot be pulled down .
The specific problem is , I need to go through RecyclerView
Show a series of content , The displayed content is distributed according to the server , For example, you need to show Banner
, Recommendation list, etc . Later, during the second phase of development , This interface needs to add a small feature, The server may not issue Banner Related properties , But because of the previous Adapter
There is some logic in , As a result, if it is not issued Banner
Data words ,RecyclerView
Will still show Banner
Corresponding ViewHolder
, And this ViewHolder
Empty to display . To solve this problem , I am here Adapter
A new... Has been added to the ViewType
And corresponding ViewHolder
:EmptyViewHolder
. This ViewHolder
Corresponding Layout That's true :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="0dp">
</RelativeLayout>
But this will lead to the problems mentioned in this article ,SwipeRefreshLayout
Unable to pull down refresh , Simply speaking , Is that when RecyclerView
Of the 0 Height View
The height of 0 when ,SwipeRefreshLayout
Unable to pull down refresh .
analysis
Observe SwipeRefreshLayout
Unable to pull down ,RecyclerView
When you pull down, something appears RippleEffect
, It is obvious that it was originally required by SwipeRefreshLayout
Handle the pull-down gesture , By RecyclerView
The consumption . As for this gesture RecyclerView
Reasons for consumption , according to Android Of View
The principle of event distribution , A reasonable guess is SwipeRefreshLayout
There is a problem with the distribution or interception of this event .
dispatchTouchEvent
SwipeRefreshLayout
Inherited from ViewGroup
, And does not rewrite itself dispatchTouchEvent
, So the problem is probably not here .
onInterceptTouchEvent
onInterceptTouchEvent
This method is responsible for intercepting events . The basic implementation of this method is :
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
// Omitted code
if (!isEnabled() || mReturningToStart || canChildScrollUp()
|| mRefreshing || mNestedScrollInProgress) {
// Fail fast if we're not in a state where a swipe is possible
return false;
}
// Omitted code
return true;
}
according to bug What happened and the code , This if The judgment is very suspicious , The probability is that there is a lot of judgment true, Lead to the whole method return false, The incident was not stopped . therefore canChildScrollUp()
This judgment is very suspicious . according to SwipeRefreshLayout
The law of operation , You can guess when RecyclerView When it can slide ,canChildScrollUp()
by true,SwipeRefreshLayout
Do not block gestures ,RecyclerView
Can slide up and down normally ; When RecyclerView In slide to 0 individual item, And continue to pull down ,canChildScrollUp()
return false, The incident was SwipeRefreshLayout
Intercept .
canChildScrollUp()
The source code of the method is as follows :
/**
* @return Whether it is possible for the child view of this layout to
* scroll up. Override this if the child view is a custom view.
*/
public boolean canChildScrollUp() {
if (mChildScrollUpCallback != null) {
return mChildScrollUpCallback.canChildScrollUp(this, mTarget);
}
if (mTarget instanceof ListView) {
return ListViewCompat.canScrollList((ListView) mTarget, -1);
}
return mTarget.canScrollVertically(-1);
}
This note is very interesting , Remind us if SwipeRefreshLayout
The son of View It's a custom View, This method has to be rewritten , tell SwipeRefreshLayout
Son View Can I slide . ( I didn't know this before , So the level of the source code will be improved )
Code logic , There are three branches here , Just look at the code , I don't know which branch to take , Forget it , direct debug Well .
Debug
adopt debug It can be seen that the final branch is taken , there mTarget It's the son View, namely RecyclerView
, But think about it later Debug RecyclerView#canScrollVertically()
when ` You will find that the number of lines of code does not correspond to . This is because the domestic manufacturers will be Android Customize the system source code , Recommended here Android Studio Self contained Simulator , Use the original operating system Debug.
Start simulator , restart Debug.
/**
* Check if this view can be scrolled vertically in a certain direction.
*
* @param direction Negative to check scrolling up, positive to check scrolling down.
* @return true if this view can be scrolled in the specified direction, false otherwise.
*/
public boolean canScrollVertically(int direction) {
final int offset = computeVerticalScrollOffset();
final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
if (range == 0) return false;
if (direction < 0) {
return offset > 0;
} else {
return offset < range - 1;
}
}
The point is that final int offset = computeVerticalScrollOffset();
, here offset Returned a greater than 0 Value , This causes the entire method to return true.
Let's see it again computeVerticalScrollOffset()
What happened? .
/**
* <p>Compute the vertical offset of the vertical scrollbar's thumb within the vertical range.
* This value is used to compute the length of the thumb within the scrollbar's track. </p>
*
* <p>The range is expressed in arbitrary units that must be the same as the units used by
* {@link #computeVerticalScrollRange()} and {@link #computeVerticalScrollExtent()}.</p>
*
* <p>Default implementation returns 0.</p>
*
* <p>If you want to support scroll bars, override
* {@link RecyclerView.LayoutManager#computeVerticalScrollOffset(RecyclerView.State)} in your
* LayoutManager.</p>
*
* @return The vertical offset of the scrollbar's thumb
* @see RecyclerView.LayoutManager#computeVerticalScrollOffset
* (RecyclerView.State)
*/
@Override
public int computeVerticalScrollOffset() {
if (mLayout == null) {
return 0;
}
return mLayout.canScrollVertically() ? mLayout.computeVerticalScrollOffset(mState) : 0;
}
Here we give the calculation of the vertical offset to layoutManager To do , We're going to use LinearLayoutManager, Continue to look at the source code . After a few jumps , Arrived ScrollbarHelper#computeScrollOffset()
, The core code is as follows :
/**
* @param startChild View closest to start of the list. (top or left)
* @param endChild View closest to end of the list (bottom or right)
*/
static int computeScrollOffset(RecyclerView.State state, OrientationHelper orientation,
View startChild, View endChild, RecyclerView.LayoutManager lm,
boolean smoothScrollbarEnabled, boolean reverseLayout) {
// Omitted code ...
final int minPosition = //.... Visible page 0 individual item
final int maxPosition = //... The last visible item
final int itemsBefore = //... Visible page 0 individual item In front of item The number of
//
final int laidOutArea = Math.abs(orientation.getDecoratedEnd(endChild)
- orientation.getDecoratedStart(startChild));// Last visible item The bottom split line of the to 0 A visible item Top style line
final int itemRange = Math.abs(lm.getPosition(startChild)
- lm.getPosition(endChild)) + 1;
// so item The number of
final float avgSizePerRow = (float) laidOutArea / itemRange;
// Every item The average height of
return Math.round(itemsBefore * avgSizePerRow + (orientation.getStartAfterPadding()
- orientation.getDecoratedStart(startChild)));// Calculate how far you can slide
}
The general logic here is as follows , First, find the first and last... Visible on the screen item Of position, Already these two item Distance between , Then calculate each item The average height of , forecast recyclerview The sliding distance . for instance , Currently visible 3 individual item,position And height respectively 0->100px,1->200px,2->300p, So here itemRange Namely 2-0+1=3, The average height is 600/3=200px,itemBefore by 0, So the final result is that you can slide 0*200px = 0px. Change the scene , The current courseware is 3 individual item,position And height respectively 1->100px,2->200px,3->300p, here itemBefore for 1, Therefore, the calculation result is 200px.
So in this scenario , The first 0 individual item The height is 0 invisible , The first 0 A visible item Of position by 1, therefore itemBefore by 1, The result must be greater than 0.
So go back to the top canScrollVertically()
Method , The return value is true, It can lead to swipeRefreshLayout
Do not block gestures , Therefore, the pull-down refresh cannot be triggered .
terms of settlement
Set up EmptyViewHolder The height of 1px That's all right. . In this way, No 0 individual item It can be seen ,itemBefore = 0, The return value is 0,SwipeRefreshLayout
You can intercept the event .
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="1px">
</RelativeLayout>
边栏推荐
- How to calculate critical weight indicators?
- Paper:Generating Hierarchical Explanations on Text Classification via Feature Interaction Detection
- 35岁腾讯员工被裁员感叹:北京一套房,存款700多万,失业好焦虑
- Iframe is simple to use, iframe is obtained, iframe element value is obtained, and iframe information of parent page is obtained
- Bluecmsv1.6- code audit
- Exchange: manage calendar permissions
- Fault: 0x800ccc1a error when outlook sends and receives mail
- Index analysis of DEMATEL model
- 想开个户,网上股票开户安不安全?
- How to calculate the independence weight index?
猜你喜欢
Data-centric vs. Model-centric. The Answer is Clear!
leetcode.13 --- 罗马数字转整数
Prepare these before the interview. The offer is soft. The general will not fight unprepared battles
Use pytorch to build mobilenetv2 and learn and train based on migration
Scanpy (VII) spatial data analysis based on scanorama integrated scrna seq
Stack awareness - stack overflow instance (ret2libc)
About i/o -- the relationship between memory and CPU and disk
How to design test cases
Internet of things (intelligent irrigation system - Android end)
How to calculate the information entropy and utility value of entropy method?
随机推荐
Rqt command
rosbag
Go语言学习教程(十三)
Hyper-v:hyper-v generation 1 or generation 2 virtual machines
leetcode.13 --- 罗马数字转整数
EasyPlayer流媒体播放器播放HLS视频,起播速度慢的技术优化
Paper:Generating Hierarchical Explanations on Text Classification via Feature Interaction Detection
Daily question brushing record (III)
About i/o -- the relationship between memory and CPU and disk
How to calculate the independence weight index?
How to design test cases
在哪个平台买股票开户安全?求分享
如何实现一个系统调用
钱堂教育商学院给的证券账户安全吗?能开户吗?
是否可以给数据库表授予删除列对象的权限?为什么?
Almost taken away by this wave of handler interview cannons~
What are the indicators of VIKOR compromise?
Getting to know the generation confrontation network (11) -- using pytoch to build wgan to generate handwritten digits
现在网上开通股票账号安全吗?
Unity addressable batch management