当前位置:网站首页>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>
边栏推荐
- Quickly build a real-time face mask detection system in five minutes (opencv+paddlehub with source code)
- 是否可以给数据库表授予删除列对象的权限?为什么?
- What is the difference between TP5 and tp6?
- Can I grant database tables permission to delete column objects? Why?
- Bluecmsv1.6- code audit
- Retrieval model rough hnsw
- linux中的mysql有10061错误怎么解决
- Hyper-v:hyper-v generation 1 or generation 2 virtual machines
- What about the exponential smoothing index?
- How to calculate the fuzzy comprehensive evaluation index? How to calculate the four fuzzy operators?
猜你喜欢

《树莓派项目实战》第五节 使用Nokia 5110液晶屏显示Hello World

How to interpret the information weight index?

第五天 脚本与UI系统

Find the nearest common ancestor (Sword finger offer) of two nodes in the binary tree (search tree)

How to calculate critical weight indicators?

What about the exponential smoothing index?

微信小程序_7,项目练习,本地生活

2021 "Ai China" selection

How to do factor analysis? Why should data be standardized?

How to calculate the independence weight index?
随机推荐
检测点是否在多边形内
Biweekly investment and financial report: capital ambush Web3 infrastructure
C language "recursive series": recursive implementation of 1+2+3++ n
What problems do you worry about when you want to switch to software testing?
4 reasons for adopting "safe left shift"
To achieve good software testing results, it is a prerequisite to build a good testing environment
SwipeRefreshLayout+RecyclerView无法下拉问题排查
EasyPlayer流媒体播放器播放HLS视频,起播速度慢的技术优化
4个不可不知的采用“安全左移”的理由
What are the indicators of DEA?
Find the nearest common ancestor (Sword finger offer) of two nodes in the binary tree (search tree)
在二叉树(搜索树)中找到两个节点的最近公共祖先(剑指offer)
Stimulsoft Ultimate呈现报告和仪表板
开户券商怎么选择?在线开户是安全么?
Use pytorch to build mobilenetv2 and learn and train based on migration
Can I grant database tables permission to delete column objects? Why?
GPU calculation
How to calculate the fuzzy comprehensive evaluation index? How to calculate the four fuzzy operators?
Trendmicro:apex one server tools folder
打新债安不安全 有风险吗