【问题标题】:Disable scrolling in listview禁用列表视图中的滚动
【发布时间】:2011-11-28 11:49:01
【问题描述】:

我有一个列表视图,根据某些逻辑,我想暂时禁用滚动。 view.setOnScrollListener(null);对我没有帮助我想我需要编写一些代码,有人可以给我一个 hist 或一些 sn-p 吗?

谢谢

【问题讨论】:

标签: android listview scroll listener


【解决方案1】:

另一个不创建新的自定义 ListView 的选项是将 onTouchListener 附加到您的 ListView 并在运动事件操作为 ACTION_MOVE 时在 onTouch() 回调中返回 true。

listView.setOnTouchListener(new OnTouchListener() {

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

【讨论】:

  • 或者,更短更简洁,return (event.getAction() == MotionEvent.ACTION_MOVE);
  • 如果 ListView 包含任何按钮甚至是拉动刷新,则此 根本不起作用。它只是不起作用,如果用户碰巧滚动到其中一个按钮上 - 它会滚动。它根本不可用。
【解决方案2】:

在您的 CustomListView 中:

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

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

【讨论】:

  • 很久以前我就遇到了这个问题,但我认为这是正确的解决方案(我解决了管理可见性的问题)
  • 看起来这个解决方案只是部分解决方案,并且在任何连接了外部键盘或 BT/USB 键盘的设备上都会失败。
  • 不幸的是,这也根本行不通。如果您在按钮或任何东西上滑动,您仍然会获得滚动效果。
  • 使用 Nikita 的解决方案,方法很简单
【解决方案3】:

使用 listview.setEnabled(false) 禁用列表视图滚动

注意:这也会禁用行选择

【讨论】:

  • 为我工作,我不知道为什么其他人都在走这么复杂的路线。
  • 这个解决方案也为我解决了这个问题!谢谢。
  • 这不起作用,因为它还会禁用列表视图行选择
  • 为我工作,因为我尝试禁用所有列表视图
  • 这是最好最简单的方法。
【解决方案4】:

让你的CustomListView

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

false 上,孩子们将处理触摸事件,请确保您输入您的if condition 以检查您是否需要滚动。

【讨论】:

  • 嗯,这是一个很好的提示,但对我不起作用。这是我在 onTouch 时需要禁用滚动的问题,并且在 onTouch 中返回 false 不会禁用滚动。 :(
  • :),你不明白我的意思。我不能在 onInterceptTouchEvent 中返回 false,因为我需要调用所有其他方法,例如 onTouch btw 之类的方法(我正在制作拖放应用程序)。这就是为什么我按下了我调用的 onInterceptTouchEvent 但我没有松开我的手指并且 onTouch 被调用了很多次所以在这里我想禁用滚动....
  • @MoshErsan :你能解释一下我们如何禁用父 TochEvent 而孩子需要它进行内部滚动吗?我真的需要这个。
【解决方案5】:

如果您将事件绑定到列表项,则使用这些解决方案中的任何一个拖动列表仍会触发该事件。您想使用以下方法来说明用户期望通过拖离所选项目来取消事件(改编自 Pointer Null 的答案):

@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

【讨论】:

  • 对我有帮助,很好!
【解决方案6】:

对我来说最好的答案是来自 Dan Osipov 的那个。 我会像这样改进它。 (触发 CANCEL 动作事件,而不是手动擦除按下状态)。

@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);
}

【讨论】:

    【解决方案7】:

    在为列表视图上的滑动删除编写代码时,我想在检测到滑动后阻止垂直滚动。一旦满足滑动删除条件,我就会在 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);
    }
    

    【讨论】:

      【解决方案8】:

      我的回答对于 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 ();
              }
          }
      }
      

      【讨论】:

        【解决方案9】:

        这是 http://danosipov.com/?p=604 上的 Joe Blow(对 OP 帖子的评论)指出的代码,但我将其发布在这里以防链接被孤立:

        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 到你的布局时,记得在它前面加上它的包名,否则当你尝试膨胀它时会抛出异常。

        【讨论】:

          【解决方案10】:

          试试这个:

          listViewObject.setTranscriptMode(0);
          

          为我工作。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2013-12-30
            • 2017-02-11
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多