Android SwipeRefreshLayout教程 [更好的解决ListView SwipeRefreshLayout 冲

Android SwipeRefreshLayout教程

在这篇文章中,我们将介绍AndroidSwipeRefreshLayout组件。当用户可以使用滑动手势刷新UI时,应使用此组件。在之前的一篇文章中,我们讨论了另一种刷新UI的方法,我们称之为摇动刷新,用户在其中摇动智能手机,并使用加速度计传感器,该应用程序刷新UI。我们在这篇文章中讨论了这种刷新模式的自定义实现,我们实现了一些类似的操作。

摇动刷新
https://www.survivingwithandroid.com/2014/04/android-shake-to-refresh-tutorial.html

所述的Android SwipeRefreshLayout组分是由SDK提供的标准实现,它已经在由Android(即Gmail的)提供了一些应用中使用。

开始使用Android SwipeRefreshLayout

Android SwipeRefreshLayout组件只接受一个孩子:我们要刷新的组件。它使用侦听器机制来通知持有此组件的侦听器发生刷新事件,因此,换句话说,我们的Activity(例如)必须实现要通知的接口。活动负责处理刷新事件并刷新相应的视图。如果收听者收到该事件,确定刷新过程应该发生并想要显示“刷新动画”,则必须调用setRefrshing(true),否则可以取消调用setRefreshing(false)的动画。

如何使用SwipeRefreshLayout

现在我们知道这个组件如何工作,我们将创建一个简单的例子来显示如何使用它。让我们假设我们想要在用户使用垂直滑动手势时生成一个随机数:

Android SwipeRefreshLayout教程 [更好的解决ListView SwipeRefreshLayout 冲 - 阿里云
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/rndNum"
android:layout_toRightOf="@id/lbl"/>
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/lbl"
android:layout_centerHorizontal="true"
android:layout_marginTop="20dp"
android:text="Swipe to Refresh"
/>

从上面的布局可以看出,SwipeRefreshLayout只有一个孩子。现在我们可以编写我们的Activity:


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final SwipeRefreshLayout swipeView = (SwipeRefreshLayout) findViewById(R.id.swipe);
final TextView rndNum = (TextView) findViewById(R.id.rndNum);
swipeView.setColorScheme(android.R.color.holo_blue_dark,
android.R.color.holo_blue_light,
android.R.color.holo_green_light,
android.R.color.holo_green_light);
swipeView.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
swipeView.setRefreshing(true);
Log.d("Swipe", "Refreshing Number");
( new Handler()).postDelayed(new Runnable() {
@Override
public void run() {
swipeView.setRefreshing(false);
double f = Math.random();
rndNum.setText(String.valueOf(f));
}
}, 3000);
}
});
}
….

正如你可以看到我们的例子中的一切都在onCreate方法中。在第6行,我们得到SwipeRefreshLayout的引用,以便我们设置侦听器(第10,11,12行)。在侦听器中,我们只需要设置Refreshing(true)来启用刷新动画,然后生成我们的随机数。最后(我们模拟一个相当长的过程),我们停止动画。

使用ListView SwipeRefreshLayout

另一个有趣的例子是如何在ListView中使用SwipeRefreshLayout。这是一个有趣的例子,因为在真实的应用程序中,我们经常遇到这样一种情况:我们只有一个ListView包含一些项目,我们要刷新它们。
如果ListView是SwipeRefreshLayout的唯一一个孩子,我们就不会有任何问题,因为一切顺利。在某些情况下,我们不仅有ListView,而且还有其他元素,让我们假设我们有这样的一个UI:

Android SwipeRefreshLayout教程 [更好的解决ListView SwipeRefreshLayout 冲 - 阿里云

这种情况更复杂一点,因为如果我们向上滚动ListView的项目,所有内容都按预期工作,但是如果向下滚动刷新过程,并且列表项不按我们想要的滚动。在这种情况下,我们可以使用一个技巧,我们可以使用setEnabled(false)来禁用刷新通知,只要ListView的第一个项目可见,就可以重新启动它:

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final SwipeRefreshLayout swipeView = (SwipeRefreshLayout) findViewById(R.id.swipe);
swipeView.setEnabled(false);
ListView lView = (ListView) findViewById(R.id.list);
ArrayAdapter adp = new ArrayAdapter (this, android.R.layout.simple_list_item_1, createItems(40,0 ));
lView.setAdapter(adp);
swipeView.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
swipeView.setRefreshing(true);
( new Handler()).postDelayed(new Runnable() {
@Override
public void run() {
swipeView.setRefreshing(false);
}
}, 3000);
}
});
lView.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView absListView, int i) {
}
@Override
public void onScroll(AbsListView absListView, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if (firstVisibleItem == 0)
swipeView.setEnabled(true);
else
swipeView.setEnabled(false);
}
});
}

如第33行所示,我们覆盖ListView的onScrollListener来处理启用/禁用机制。

事实上,这种方案不是很好,
(只是ListVIew第一项视图可见即可使用下拉刷新功能,也就导致,第一项视图显示不全,也可刷新)
更好的解决方案,请往下看

来源:https://www.survivingwithandroid.com/2014/05/android-swiperefreshlayout-tutorial-2.html
作者: Francesco Azzola

Can’t scroll in a ListView in a swipeRefreshLayout

来源:https://stackoverflow.com/questions/27041416/cant-scroll-in-a-listview-in-a-swiperefreshlayout

判断listview第一项视图的顶部坐标(顶部Y坐标)是否大于等于0
如果是,则开启swiperefreshlayout功能

listView.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
@Override
public void onScroll(AbsListView listView, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
int topRowVerticalPosition = (listView == null || listView.getChildCount() == 0) ?
0 : expandableListview.getChildAt(0).getTop();
refresh.setEnabled((topRowVerticalPosition >= 0));
}
});

end