避免SwipeRefresh而在Android的fastScrolling [英] Avoid SwipeRefresh while fastScrolling in android
问题描述
我有一个 的ListView
为 fastScroll
始终处于启用状态 SwipeRefresh
的实施。当我刷卡列表中向下,它刷新列表。我的问题是 fastScroll
。如果列表的第一个项目可见或者说在其最初的顶部,那么如果滚动的 fastScrollThumb
向下,但它确实在 刷卡
的效果不是向下滚动。反正是有/解决方案,如果我preSS的 fastScrollThumb
,那么它不应该做的刷卡
刷新的效果,而它应该向下滚动,因为它自然的行为。
EDITED
我的 XML布局
情况如下:
< XML版本=1.0编码=UTF-8&GT?;
< android.support.v4.widget.SwipeRefreshLayout
的xmlns:机器人=http://schemas.android.com/apk/res/android
机器人:ID =@ + ID / swipe_container
机器人:layout_width =match_parent
机器人:layout_height =match_parent
机器人:背景=@色/白>
< RelativeLayout的
机器人:layout_width =match_parent
机器人:layout_height =match_parent>
< RelativeLayout的
机器人:ID =@ + ID / buttons_layout
机器人:layout_width =WRAP_CONTENT
机器人:layout_height =WRAP_CONTENT
机器人:layout_centerHorizontal =真
机器人:layout_marginTop =10dp>
< ImageView的
机器人:ID =@ + ID /提交按钮
机器人:layout_width =WRAP_CONTENT
机器人:layout_height =WRAP_CONTENT
机器人:背景=@可绘制/ neoo_tab_selector/>
< / RelativeLayout的>
<的ListView
机器人:ID =@ ID / Android的:清单
风格=@风格/ NeeoContactListView
机器人:layout_width =match_parent
机器人:layout_height =match_parent
机器人:layout_below =@ + ID / buttons_layout
机器人:layout_marginTop =10dp/>
< / RelativeLayout的>
< /android.support.v4.widget.SwipeRefreshLayout>
我的 逻辑为onScroll
启用/禁用 SwipeRefresh
是:
getListView()。setOnScrollListener(新OnScrollListener(){
@覆盖
公共无效onScrollStateChanged(AbsListView观点,诠释scrollState){
}
@覆盖
公共无效onScroll(AbsListView观点,诠释firstVisibleItem,诠释visibleItemCount,诠释totalItemCount){
布尔有效=虚假的;
如果(getListView()= NULL和放大器;!&安培; getListView()getChildCount()> 0){
//检查列表的第一个项目是可见
布尔firstItemVisible = getListView()getFirstVisiblePosition()== 0。
//检查是否所述第一项的顶部是可见
布尔topOfFirstItemVisible = getListView()getChildAt(0).getTop()== 0。
//启用或停用刷新布局
启用= firstItemVisible和放大器;&安培; topOfFirstItemVisible;
}
如果(启用){
enableSwipe();
}其他{
disableSwipe();
}
}
});
我只是看着的 的文档 的 SwipeRefreshLayout
,我想他们提到你在找什么:
...如果侦听确定不应该有一个刷新,就必须 叫
setRefreshing(假)
取消的任何视觉指示 刷新。如果活动希望只显示进度动画,它 应该叫setRefreshing(真)
。要禁用手势和进步 动漫,呼叫的setEnabled(假)
的看法。
所以,你有几个选项,我先试试玩弄的setEnabled()
或 setRefreshing()
,但正确使用这些我们首先需要能够检测是否的ListView
是快速滚动的方法。有没有监听器或任何要快速滚动,但你可以通过反射得到国家!基于 这个优秀的,严重被低估的答案 我已经写了 FastScrollListener
可用于就像一个 OnScrollListener
:
this.listView.setFastScrollEnabled(真正的);
this.listView.setOnScrollListener(新FastScrollListener(this.listView){
@覆盖
保护无效onFastScrollStateChanged(AbsListView观点,FastScrollState州){
//这行禁用SwipeRefreshLayout
//每当用户快速滚动
swipeRefreshLayout.setEnabled(州= FastScrollState.DRAGGING!);
}
@覆盖
保护无效onFastScroll(AbsListView观点,诠释firstVisibleItem,诠释visibleItemCount,诠释totalItemCount){
}
});
您也可以尝试调用 setRefreshing()
而不是的setEnabled()
如果的setEnabled ()
不起作用。
这里是的code中的 FastScrollListener
:
公共抽象类FastScrollListener实现AbsListView.OnScrollListener {
私人最终诠释STATE_DRAGGING;
私人最终诠释STATE_VISIBLE;
私人最终诠释STATE_NONE;
公共枚举FastScrollState {
拖动
可见,
NONE,
未知
}
私人FastScrollState fastScrollState = FastScrollState.UNKNOWN;
私人领域stateField;
私有对象mFastScroller;
公共FastScrollListener(AbsListView的ListView){
尝试 {
最后一个字段fastScrollerField = AbsListView.class.getDeclaredField(mFastScroller);
fastScrollerField.setAccessible(真正的);
mFastScroller = fastScrollerField.get(ListView控件);
最后一个字段stateDraggingField = mFastScroller.getClass()getDeclaredField(STATE_DRAGGING)。
stateDraggingField.setAccessible(真正的);
STATE_DRAGGING = stateDraggingField.getInt(mFastScroller);
最后一个字段stateVisibleField = mFastScroller.getClass()getDeclaredField(STATE_VISIBLE)。
stateVisibleField.setAccessible(真正的);
STATE_VISIBLE = stateVisibleField.getInt(mFastScroller);
最后一个字段stateNoneField = mFastScroller.getClass()getDeclaredField(STATE_NONE)。
stateNoneField.setAccessible(真正的);
STATE_NONE = stateNoneField.getInt(mFastScroller);
stateField = mFastScroller.getClass()getDeclaredField(mState);
stateField.setAccessible(真正的);
fastScrollState = getFastScrollState();
}赶上(NoSuchFieldException E){
抛出新IllegalStateException异常(无法找到快速滚动检测所需的领域!,E);
}赶上(IllegalAccessException E){
抛出新IllegalStateException异常(无法找到快速滚动检测所需的领域!,E);
}
}
@覆盖
公共无效onScrollStateChanged(AbsListView观点,诠释scrollState){
updateFastScrollState(视图);
}
@覆盖
公共无效onScroll(AbsListView观点,诠释firstVisibleItem,诠释visibleItemCount,诠释totalItemCount){
updateFastScrollState(视图);
updateFastScroll(查看,firstVisibleItem,visibleItemCount,totalItemCount);
}
私人无效updateFastScrollState(AbsListView视图){
如果(stateField!= NULL){
最后FastScrollState状态= getFastScrollState();
如果(fastScrollState!=状态){
fastScrollState =状态;
onFastScrollStateChanged(视图,状态);
}
}
}
私人无效updateFastScroll(AbsListView观点,诠释firstVisibleItem,诠释visibleItemCount,诠释totalItemCount){
如果(fastScrollState == FastScrollState.DRAGGING){
onFastScroll(查看,firstVisibleItem,visibleItemCount,totalItemCount);
}
}
私人FastScrollState getFastScrollState(){
尝试 {
最终诠释状态= stateField.getInt(mFastScroller);
如果(国家== STATE_DRAGGING){
返回FastScrollState.DRAGGING;
}
如果(国家== STATE_VISIBLE){
返回FastScrollState.VISIBLE;
}
如果(国家== STATE_NONE){
返回FastScrollState.NONE;
}
返回FastScrollState.UNKNOWN;
}赶上(IllegalAccessException E){
抛出新IllegalStateException异常(无法读取快速滚动的状态!,E);
}
}
保护抽象无效onFastScrollStateChanged(AbsListView观点,FastScrollState状态);
保护抽象无效onFastScroll(AbsListView观点,诠释firstVisibleItem,诠释visibleItemCount,INT totalItemCount);
}
我希望我可以帮你,如果你有任何问题,请随时问!
编辑:试试这个,但我怀疑它会工作:
@覆盖
保护无效onFastScrollStateChanged(AbsListView观点,FastScrollState州){
布尔有效=虚假的;
如果(getListView()getChildCount()> 0){
布尔firstItemVisible = getListView()getFirstVisiblePosition()== 0。
布尔topOfFirstItemVisible = getListView()getChildAt(0).getTop()== 0。
启用= firstItemVisible和放大器;&安培; topOfFirstItemVisible;
}
refreshLayout.setEnabled(启用);
}
I have a ListView
having fastScroll
always enabled and SwipeRefresh
implementation. When i swipe the list downward, it refreshes the list. My problem is fastScroll
. If the list has its first item visible or say at its initial top, then if scroll the fastScrollThumb
downward, it does the Swipe
effect not the scroll down. Is there anyway/solution that if i press the fastScrollThumb
, then it should not do Swipe
refresh effect rather it should scroll down as it natural behavior.
EDITED
My XML Layout
is as follow:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/swipe_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<RelativeLayout
android:id="@+id/buttons_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="10dp">
<ImageView
android:id="@+id/SubmitButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/neoo_tab_selector" />
</RelativeLayout>
<ListView
android:id="@id/android:list"
style="@style/NeeoContactListView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/buttons_layout"
android:layout_marginTop="10dp" />
</RelativeLayout>
</android.support.v4.widget.SwipeRefreshLayout>
My Logic for onScroll
for enabling/disabling the SwipeRefresh
is :
getListView().setOnScrollListener(new OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
boolean enable = false;
if(getListView() != null && getListView().getChildCount() > 0){
// check if the first item of the list is visible
boolean firstItemVisible = getListView().getFirstVisiblePosition() == 0;
// check if the top of the first item is visible
boolean topOfFirstItemVisible = getListView().getChildAt(0).getTop() == 0;
// enabling or disabling the refresh layout
enable = firstItemVisible && topOfFirstItemVisible;
}
if(enable){
enableSwipe();
}else{
disableSwipe();
}
}
});
I just looked into the documentation of the SwipeRefreshLayout
and I think they mention what you are looking for:
... If the listener determines there should not be a refresh, it must call
setRefreshing(false)
to cancel any visual indication of a refresh. If an activity wishes to show just the progress animation, it should callsetRefreshing(true)
. To disable the gesture and progress animation, callsetEnabled(false)
on the view.
So you have a few options, I would first try playing around with setEnabled()
or setRefreshing()
, but to properly use those methods we first need to be able to detect if the ListView
is fast scrolling. There is no listener or anything for fast scrolling but you can get the state through reflection! Based on this excellent and seriously underrated answer I have written a FastScrollListener
which can be used just like a OnScrollListener
:
this.listView.setFastScrollEnabled(true);
this.listView.setOnScrollListener(new FastScrollListener(this.listView) {
@Override
protected void onFastScrollStateChanged(AbsListView view, FastScrollState state) {
// This line disabled the SwipeRefreshLayout
// whenever the user is fast scrolling
swipeRefreshLayout.setEnabled(state != FastScrollState.DRAGGING);
}
@Override
protected void onFastScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
}
});
You could also try calling setRefreshing()
instead of setEnabled()
if setEnabled()
doesn't work.
And here is the code of the FastScrollListener
:
public abstract class FastScrollListener implements AbsListView.OnScrollListener {
private final int STATE_DRAGGING;
private final int STATE_VISIBLE;
private final int STATE_NONE;
public enum FastScrollState {
DRAGGING,
VISIBLE,
NONE,
UNKNOWN
}
private FastScrollState fastScrollState = FastScrollState.UNKNOWN;
private Field stateField;
private Object mFastScroller;
public FastScrollListener(AbsListView listView) {
try {
final Field fastScrollerField = AbsListView.class.getDeclaredField("mFastScroller");
fastScrollerField.setAccessible(true);
mFastScroller = fastScrollerField.get(listView);
final Field stateDraggingField = mFastScroller.getClass().getDeclaredField("STATE_DRAGGING");
stateDraggingField.setAccessible(true);
STATE_DRAGGING = stateDraggingField.getInt(mFastScroller);
final Field stateVisibleField = mFastScroller.getClass().getDeclaredField("STATE_VISIBLE");
stateVisibleField.setAccessible(true);
STATE_VISIBLE = stateVisibleField.getInt(mFastScroller);
final Field stateNoneField = mFastScroller.getClass().getDeclaredField("STATE_NONE");
stateNoneField.setAccessible(true);
STATE_NONE = stateNoneField.getInt(mFastScroller);
stateField = mFastScroller.getClass().getDeclaredField("mState");
stateField.setAccessible(true);
fastScrollState = getFastScrollState();
} catch (NoSuchFieldException e) {
throw new IllegalStateException("Could not find required fields for fast scroll detection!", e);
} catch (IllegalAccessException e) {
throw new IllegalStateException("Could not find required fields for fast scroll detection!", e);
}
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
updateFastScrollState(view);
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
updateFastScrollState(view);
updateFastScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
}
private void updateFastScrollState(AbsListView view) {
if (stateField != null) {
final FastScrollState state = getFastScrollState();
if (fastScrollState != state) {
fastScrollState = state;
onFastScrollStateChanged(view, state);
}
}
}
private void updateFastScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if(fastScrollState == FastScrollState.DRAGGING) {
onFastScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
}
}
private FastScrollState getFastScrollState() {
try {
final int state = stateField.getInt(mFastScroller);
if (state == STATE_DRAGGING) {
return FastScrollState.DRAGGING;
}
if (state == STATE_VISIBLE) {
return FastScrollState.VISIBLE;
}
if (state == STATE_NONE) {
return FastScrollState.NONE;
}
return FastScrollState.UNKNOWN;
} catch (IllegalAccessException e) {
throw new IllegalStateException("Could not read fast scroll state!", e);
}
}
protected abstract void onFastScrollStateChanged(AbsListView view, FastScrollState state);
protected abstract void onFastScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount);
}
I hope I could help you and if you have any further questions please feel free to ask!
EDIT: Try this, but I doubt it will work:
@Override
protected void onFastScrollStateChanged(AbsListView view, FastScrollState state) {
boolean enable = false;
if (getListView().getChildCount() > 0) {
boolean firstItemVisible = getListView().getFirstVisiblePosition() == 0;
boolean topOfFirstItemVisible = getListView().getChildAt(0).getTop() == 0;
enable = firstItemVisible && topOfFirstItemVisible;
}
refreshLayout.setEnabled(enable);
}
这篇关于避免SwipeRefresh而在Android的fastScrolling的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!