27

我在我的应用程序中实现了 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  

}
4

4 回答 4

40

v4 支持库的版本 21 提供了一个 API 来设置距离。

public void setDistanceToTriggerSync (int distance)

在此处查看文档。

还有一件事,转速。21 更改了进度条的行为,现在是圆形图像。不知道如何回到旧的方式。

于 2014-10-27T02:07:24.607 回答
30

如果您使用的是支持库的 API 21,请参考并请在此处支持 Han He 的答案。存在一种设置触发距离的方法,称为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) 是类中的私有常量,您无法修改。

您可以使用上述计算触发距离,并使用您自己的常数作为滑动距离因子。

全局布局监听器

可以在全局布局侦听器中进行设置,mDistanceToTriggerSync以便可以正确检索布局的高度以计算触发距离。调用getHeight视图onCreate将始终返回 0,因为它尚未绘制。我从这里得到了代码。根据您的要求,您可能需要也可能不需要这样做。

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可以在这里找到。

于 2014-04-05T18:55:18.227 回答
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.../>确保更改您的导入。

于 2014-04-04T08:56:24.057 回答
-1

这个只是做了一个技巧,没有更多额外的代码只需将你的回收器视图包装到 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>
于 2020-08-20T03:39:25.560 回答