我在我的应用中实现了SwipeRefreshLayout。我需要更改必须向下滚动的高度来调用onRefresh()方法。我应该使用哪种方法来添加自定义高度?
SwipeRefreshLayout的实现
private SwipeRefreshLayout swipeLayout;
在oncreate中
swipeLayout = (SwipeRefreshLayout)view.findViewById(R.id.swipe_container);
swipeLayout.setOnRefreshListener(this);
swipeLayout.setColorScheme(android.R.color.holo_blue_dark,
android.R.color.holo_green_dark,
android.R.color.holo_purple,
android.R.color.holo_orange_dark);
swipeLayout.setSoundEffectsEnabled(true);
在onrefresh方法中实现AsyncTask
@Override
public void onRefresh()
{
// Asynctask to perform some task
}
答案 0 :(得分:29)
v4支持库的reversion 21提供了一个API来设置距离。
public void setDistanceToTriggerSync (int distance)
检查文档here。
还有一件事,转。 21改变了进度条的行为,它现在是一个圆形图像。不知道如何回归旧路。
答案 1 :(得分:26)
如果您正在使用支持库的API 21,请参阅并请upvote韩赫的回答here。存在一种方法来设置称为setDistanceToTriggerSync
的触发距离。
在API 21之前,正如adneal所提到的,没有公共或内部方法来修改触发距离。
但是,如果您不想保留类的副本以修改常量,则可以使用反射手动设置触发距离。
swipeLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_container);
// define a distance
Float mDistanceToTriggerSync = yourCalculation();
try {
// Set the internal trigger distance using reflection.
Field field = SwipeRefreshLayout.class.getDeclaredField("mDistanceToTriggerSync");
field.setAccessible(true);
field.setFloat(swipeLayout, mDistanceToTriggerSync);
} catch (Exception e) {
e.printStackTrace();
}
如果您使用布局的高度来确定距离,则可能需要使用类似GlobalLayoutListener
的内容。
<强> mDistanceToTriggerSync 强>
在SwipeRefreshLayout
中,有一个名为mDistanceToTriggerSync
的内部变量。
这用于确定触发刷新的距离。
在源代码中,它由SwipeRefreshLayout
中的代码设置:
final DisplayMetrics metrics = getResources().getDisplayMetrics();
mDistanceToTriggerSync = (int) Math.min(
((View) getParent()) .getHeight() * MAX_SWIPE_DISTANCE_FACTOR,
REFRESH_TRIGGER_DISTANCE * metrics.density);
以上使用父视图高度和一些常量来计算触发距离。 MAX_SWIPE_DISTANCE_FACTOR
(0.6)和REFRESH_TRIGGER_DISTANCE
(120)是类中无法修改的私有常量。
您可以使用上述方法计算触发距离,并使用自己的常数作为滑动距离系数。
<强> GlobalLayoutListener 强>
mDistanceToTriggerSync
的设置可以在全局布局侦听器中完成,以便可以正确检索布局的高度以计算触发距离。在getHeight
中的视图上调用onCreate
将始终返回0,因为尚未绘制它。我从here获得了代码。根据您的要求,您可能需要也可能不需要这样做。
ViewTreeObserver vto = swipeLayout.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
// Calculate the trigger distance.
final DisplayMetrics metrics = getResources().getDisplayMetrics();
Float mDistanceToTriggerSync = Math.min(
((View) swipeLayout.getParent()).getHeight() * 0.6f,
120 * metrics.density);
try {
// Set the internal trigger distance using reflection.
Field field = SwipeRefreshLayout.class.getDeclaredField("mDistanceToTriggerSync");
field.setAccessible(true);
field.setFloat(swipeLayout, mDistanceToTriggerSync);
} catch (Exception e) {
e.printStackTrace();
}
// Only needs to be done once so remove listener.
ViewTreeObserver obs = swipeLayout.getViewTreeObserver();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
obs.removeOnGlobalLayoutListener(this);
} else {
obs.removeGlobalOnLayoutListener(this);
}
}
});
如果我正确理解了底层代码,则只需要进行一次变量设置,因为如果它等于mDistanceToTriggerSync
,它只会设置-1
。因此,在全局布局侦听器中执行一次应该是安全的。
<强> SwipeRefreshLayout 强>
如果您对SwipeRefreshLayout
的源代码感兴趣,可以找到它here。
答案 2 :(得分:3)
目前,还没有可用于调整触发距离的公共方法,甚至是内部方法。但是您可以将支持库中的三个类复制到项目中,然后根据自己的喜好修改SwipeRefreshLayout
。
以下是您需要复制的课程:
使用常数计算跳远距离:
private static final float MAX_SWIPE_DISTANCE_FACTOR = .6f;
private static final int REFRESH_TRIGGER_DISTANCE = 120;
在布局中将<android.support.v4.widget.SwipeRefreshLayout.../>
更改为<your_path_to_SwipeRefreshLayout.../>
,并确保在需要时更改导入。
答案 3 :(得分:0)
这只是一个技巧,不再需要其他代码 只需将您的recyclerview包装到NestedScrollView中,然后将此NestedScrollView包装在SwipeRefreshLayout中
检查下面的代码
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/swipe_refresh_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.core.widget.NestedScrollView>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>