If you're using API 21 of the support library, refer to and please upvote Han He's answer here. A method exists to set the trigger distance called setDistanceToTriggerSync
.
Prior to API 21, as adneal mentioned, there are no public or internal methods to modify the trigger distance.
However, if you don't want to keep a copy of the classes to modify the constants, you can use reflection to manually set a trigger distance.
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();
}
If you're using the height of the layout to determine the distance, you may want to use something like a GlobalLayoutListener
.
mDistanceToTriggerSync
In SwipeRefreshLayout
, there is an internal variable called mDistanceToTriggerSync
.
This is used to determine at what distance to trigger the refresh.
In the source code, it is set by the code below in SwipeRefreshLayout
:
final DisplayMetrics metrics = getResources().getDisplayMetrics();
mDistanceToTriggerSync = (int) Math.min(
((View) getParent()) .getHeight() * MAX_SWIPE_DISTANCE_FACTOR,
REFRESH_TRIGGER_DISTANCE * metrics.density);
The above uses the parent view height and some constants to calculate the trigger distance. MAX_SWIPE_DISTANCE_FACTOR
(0.6) and REFRESH_TRIGGER_DISTANCE
(120) are private constants in the class that you cannot modify.
You can use the above to calculate your trigger distance and use your own constants for the swipe distance factors.
GlobalLayoutListener
Setting of the mDistanceToTriggerSync
can be done inside a global layout listener so that the height of the layout can be retrieved properly for calculating the trigger distance. Calling getHeight
on a view in onCreate
will always return 0 because it has not been drawn yet. I got the code from here. You may or may not need to do this depending on your requirements.
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);
}
}
});
The setting of the variable only needs to be done once if I understand the underlying code properly as it only sets mDistanceToTriggerSync
if it is equal to -1
. Therefore, it should be safe to do it in the global layout listener once.
SwipeRefreshLayout
If you're interested in the source code of SwipeRefreshLayout
you can find it here.
http://blog.xamarin.com/android-the-swipe-down-to-refresh-pattern/
it may be helpful to you – Cub