2011-09-30 131 views
37

我有一个列表视图,并根据我想临时禁用滚动的一些逻辑。 view.setOnScrollListener(null);不帮助我我想我需要写一些代码,有人可以给我一个hist或一些片段?在列表视图中禁用滚动

感谢

+0

仍然可点击? –

+0

是的,我需要的只是停止滚动2-3秒 – Lukap

+2

**唯一的解决方案** ... http://danosipov.com/?p=604 – Fattie

回答

39

在你CustomListView:

@Override 
public boolean dispatchTouchEvent(MotionEvent ev){ 
    if(ev.getAction()==MotionEvent.ACTION_MOVE) 
     return true; 
    return super.dispatchTouchEvent(ev); 
} 

然后将的ListView反应点击,但不会改变滚动位置。

+0

很久以前,当我遇到这个问题时,但我认为这是正确的解决方案(我解决了管理可见性问题) – Lukap

+5

看起来这个解决方案只是部分解决方案,并且在任何带外部键盘或BT/USB的设备上都会失败键盘连接。 – sandrstar

+4

不幸的是,这也只是不起作用。如果您滑过按钮或其他任何东西,仍然可以获得滚动效果。 – Fattie

7

让你CustomListView

@Override 
public boolean onInterceptTouchEvent(MotionEvent ev) { 
    if(needToStop){ 
    return false;} 
    return super.onInterceptTouchEvent(ev); 
} 

false孩子的将处理触摸事件,确保你把你的if condition来检查需要滚动与否。

+0

嗯,这是非常好的提示不起作用为了我。这是我在onTouch时需要禁用滚动的问题,并且在onTouch中返回false不会禁用滚动。 :( – Lukap

+1

不是'onTouch',它'onInterceptTouchEvent'方法 –

+0

:),你不理解我。我不能在onInterceptTouchEvent中返回false,因为我需要调用其他所有方法,像onTouch btw(我正在制作拖放应用程序)等方法。这就是为什么我按了我调用的onInterceptTouchEvent,但我不释放我的手指和onTouch多次调用,所以在这里我想禁用滚动.... – Lukap

40

如果动作事件动作为ACTION_MOVE,则不创建新的自定义ListView的另一种选择是将onTouchListener附加到您的ListView,并在onTouch()回调中返回true。

listView.setOnTouchListener(new OnTouchListener() { 

    public boolean onTouch(View v, MotionEvent event) { 
     return (event.getAction() == MotionEvent.ACTION_MOVE); 
    } 
}); 
+1

或者,这是更短,更清洁,'返回(event.getAction()== MotionEvent.ACTION_MOVE);' – aga

+7

这**不适用于所有**如果ListView包含ANY按钮或甚至拉刷新。它只是**不起作用**,如果用户恰好滚动其中一个按钮 - 滚动。这根本不可用。 – Fattie

8

如果您有一个绑定到列表项的事件,那么用这些解决方案中的任何一个拖动列表仍将触发该事件。你想用下面的方法来解释用户期望通过从所选择的项目(改编自指针空的答案)拖走取消事件:

@Override 
public boolean dispatchTouchEvent(MotionEvent ev) { 
    final int actionMasked = ev.getActionMasked() & MotionEvent.ACTION_MASK; 

    if (actionMasked == MotionEvent.ACTION_DOWN) { 
     // Record the position the list the touch landed on 
     mPosition = pointToPosition((int) ev.getX(), (int) ev.getY()); 
     return super.dispatchTouchEvent(ev); 
    } 

    if (actionMasked == MotionEvent.ACTION_MOVE) { 
     // Ignore move events 
     return true; 
    } 

    if (actionMasked == MotionEvent.ACTION_UP) { 
     // Check if we are still within the same view 
     if (pointToPosition((int) ev.getX(), (int) ev.getY()) == mPosition) { 
      super.dispatchTouchEvent(ev); 
     } else { 
      // Clear pressed state, cancel the action 
      setPressed(false); 
      invalidate(); 
      return true; 
     } 
    } 

    return super.dispatchTouchEvent(ev); 
} 

完全自定义视图类可供选择:https://gist.github.com/danosipov/6498490

+0

对我有帮助,很好! – bluesway

2

在列表视图中编写用于轻扫以删除的代码时,我想在检测到轻扫时防止垂直滚动。一旦滑动删除条件满足,我在ACTION_MOVE部分中设置一个布尔标志。 dispatchTouchEvent方法检查该条件并防止滚动工作。在ACTION_UP中,我将标志设置为false以重新启用滚动。

private float mY = Float.NaN; 
private boolean mStopScroll = false; 

@Override 
public boolean onTouch(View view, MotionEvent event) { 

    if(!mStopScroll) { 
     mY = event.getY(); 
    } 

    switch (event.getAction()) { 

     case MotionEvent.ACTION_MOVE: 

      if(<condition that stops the vertical scroll>) { 
       mStopScroll = true; 
      } 

      break; 

     case MotionEvent.ACTION_UP: 

      mStopScroll = false; 

      // your code here 
      return true; 

     default: 

    } 

    return false; 

} 

@Override 
public boolean dispatchTouchEvent(MotionEvent motionEvent) { 

    if(mStopScroll) { 
     motionEvent.setLocation(motionEvent.getX(), mY); 
    } 
    return super.dispatchTouchEvent(motionEvent); 
} 
1

我的答案对Xamarin和MvvmCross用户来说很有意思。主要概念是像在以前的文章一样,所以主要步骤是:

  1. 静音滚动事件
  2. 变化动态列出高度

在这里,你是辅助类,它允许在列表禁用滚动查看:

using System; 
using Cirrious.MvvmCross.Binding.Droid.Views; 
using Android.Content; 
using Android.Util; 
using Android.Views; 
using Android.Database; 

namespace MyProject.Android.Helpers 
{ 
    public class UnscrollableMvxListView 
     : MvxListView 
    { 
     private MyObserver _myObserver; 

     public UnscrollableMvxListView (Context context, IAttributeSet attrs, MvxAdapter adapter) 
      : base(context, attrs, adapter) 
     { 
     } 

     protected override void OnAttachedToWindow() 
     { 
      base.OnAttachedToWindow(); 
      var dtso = new MyObserver(this); 
      _myObserver = dtso; 
      Adapter.RegisterDataSetObserver (dtso); 
     } 

     protected override void OnDetachedFromWindow() 
     { 
      Log.Debug ("UnscrollableMvxListView", "OnDetachedFromWindow"); 
      if (_myObserver != null) { 
       Adapter.UnregisterDataSetObserver (_myObserver); 
       _myObserver = null; 
      } 
      base.OnDetachedFromWindow(); 
     } 

     //Make List Unscrollable 
     private int _position; 
     public override bool DispatchTouchEvent (MotionEvent ev) 
     { 
      MotionEventActions actionMasked = ev.ActionMasked & MotionEventActions.Mask; 

      if (actionMasked == MotionEventActions.Down) { 
       // Record the position the list the touch landed on 
       _position = PointToPosition((int) ev.GetX(), (int) ev.GetY()); 
       return base.DispatchTouchEvent(ev); 
      } 

      if (actionMasked == MotionEventActions.Move) { 
       // Ignore move events 
       return true; 
      } 

      if (actionMasked == MotionEventActions.Up) { 
       // Check if we are still within the same view 
       if (PointToPosition((int) ev.GetX(), (int) ev.GetY()) == _position) { 
        base.DispatchTouchEvent(ev); 
       } else { 
        // Clear pressed state, cancel the action 
        Pressed = false; 
        Invalidate(); 
        return true; 
       } 
      } 

      return base.DispatchTouchEvent(ev); 
     } 

     //Make List Flat 
     public void JustifyListViewHeightBasedOnChildren() { 
      if (Adapter == null) { 
       return; 
      } 
      var vg = this as ViewGroup; 
      int totalHeight = 0; 
      for (int i = 0; i < Adapter.Count; i++) { 
       View listItem = Adapter.GetView(i, null, vg); 
       listItem.Measure(0, 0); 
       totalHeight += listItem.MeasuredHeight; 
      } 

      ViewGroup.LayoutParams par = LayoutParameters; 
      par.Height = totalHeight + (DividerHeight * (Adapter.Count - 1)); 
      LayoutParameters = par; 
      RequestLayout(); 
     } 
    } 

    internal class MyObserver 
     : DataSetObserver 
    { 
     private readonly UnscrollableMvxListView _unscrollableMvxListView; 

     public MyObserver (UnscrollableMvxListView lst) 
     { 
      _unscrollableMvxListView = lst; 
     } 

     public override void OnChanged() { 
      Log.Debug("UnscrollableMvxListView", "OnChanged"); 
      base.OnChanged(); 
      _unscrollableMvxListView.JustifyListViewHeightBasedOnChildren(); 
     } 
    } 
} 
5

对我来说最好的答案是丹奥西波夫的那个。 我会像这样改进它。 (触发取消动作事件而不是手动删除按下的状态)。

@Override 
public boolean dispatchTouchEvent(MotionEvent ev) { 
    final int actionMasked = ev.getActionMasked() & MotionEvent.ACTION_MASK; 

    if (actionMasked == MotionEvent.ACTION_DOWN) { 
     // Record the position the list the touch landed on 
     mPosition = pointToPosition((int) ev.getX(), (int) ev.getY()); 
     return super.dispatchTouchEvent(ev); 
    } 

    if (actionMasked == MotionEvent.ACTION_MOVE) { 
     // Ignore move events 
     return true; 
    } 

    if (actionMasked == MotionEvent.ACTION_UP) { 
     // Check if we are still within the same view 
     if (pointToPosition((int) ev.getX(), (int) ev.getY()) != mPosition) { 
      // Clear pressed state, cancel the action 
      ev.setAction(MotionEvent.ACTION_CANCEL); 
     } 
    } 

    return super.dispatchTouchEvent(ev); 
} 
23

使用listview。的setEnabled(假)禁用列表视图滚动

注:这也行禁用选择

+4

为我工作,我不知道为什么其他人都采取这样复杂的路线。 – hordurh

+0

这个解决方案解决了我的问题!谢谢。 – JozeRi

+3

这不会工作,因为它也禁用列表视图行选择 – loadedion

1

这是代码乔吹动(评论OP后)指着上http://danosipov.com/?p=604,但我在这里张贴保护它在情况下,链接是孤立的:

public class ScrollDisabledListView extends ListView { 

private int mPosition; 

public ScrollDisabledListView(Context context) { 
    super(context); 
} 

public ScrollDisabledListView(Context context, AttributeSet attrs) { 
    super(context, attrs); 
} 

public ScrollDisabledListView(Context context, AttributeSet attrs, int defStyle) { 
    super(context, attrs, defStyle); 
} 

@Override 
public boolean dispatchTouchEvent(MotionEvent ev) { 
    final int actionMasked = ev.getActionMasked() & MotionEvent.ACTION_MASK; 

    if (actionMasked == MotionEvent.ACTION_DOWN) { 
     // Record the position the list the touch landed on 
     mPosition = pointToPosition((int) ev.getX(), (int) ev.getY()); 
     return super.dispatchTouchEvent(ev); 
    } 

    if (actionMasked == MotionEvent.ACTION_MOVE) { 
     // Ignore move events 
     return true; 
    } 

    if (actionMasked == MotionEvent.ACTION_UP) { 
     // Check if we are still within the same view 
     if (pointToPosition((int) ev.getX(), (int) ev.getY()) == mPosition) { 
      super.dispatchTouchEvent(ev); 
     } else { 
      // Clear pressed state, cancel the action 
      setPressed(false); 
      invalidate(); 
      return true; 
     } 
    } 

    return super.dispatchTouchEvent(ev); 
} 
} 

当您添加此ListView控件到您的布局记住其包的名字前面,否则当您试图夸大它的异常将被抛出。

1

试试这个:

listViewObject.setTranscriptMode(0); 

为我工作。

+0

不适用于棒棒糖 – Hamidreza