简体   繁体   English

禁用listview中的滚动

[英]Disable scrolling in listview

I have a list view and depending on some logic I want to temporary disable the scrolling. 我有一个列表视图,根据一些逻辑,我想临时禁用滚动。 view.setOnScrollListener(null); view.setOnScrollListener(NULL); doesn't helps me I guess I need to write some code, can someone give me a hist or some snippet ? 没有帮助我我想我需要写一些代码,有人可以给我一个文件或一些片段吗?

Thanks 谢谢

Another option without creating a new custom ListView would be to attach an onTouchListener to your ListView and return true in the onTouch() callback if the motion event action is ACTION_MOVE . 另一个没有创建新自定义ListView的选项是将onTouchListener附加到ListView,如果运动事件操作是ACTION_MOVE ,则在onTouch()回调中返回true。

listView.setOnTouchListener(new OnTouchListener() {

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

In your CustomListView: 在CustomListView中:

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

Then ListView will react to clicks, but will not change scroll position. 然后ListView将对点击作出反应,但不会改变滚动位置。

use listview.setEnabled(false) to disable listview scrolling 使用listview.setEnabled(false)禁用listview滚动

Note: This also disables row selections 注意:这也会禁用行选择

If you have an event bound to the list items, then dragging the list with any of these solutions will still trigger the event. 如果您有一个绑定到列表项的事件,则使用任何这些解决方案拖动列表仍将触发该事件。 You want to use the following method to account for users expectation to cancel the event by dragging away from the selected item (adapted from Pointer Null's answer): 您希望使用以下方法来考虑用户期望通过拖离所选项目来取消事件(改编自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);
}

Full custom view class is available: https://gist.github.com/danosipov/6498490 提供完整的自定义视图类: https//gist.github.com/danosipov/6498490

make your CustomListView 制作您的CustomListView

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

on false the childs will handle the touch event, make sure you put your if condition to check you need to scroll or not. 如果false ,孩子们将处理触摸事件,请确保将if condition为检查是否需要滚动。

The best answer for me is the One from Dan Osipov. 对我来说最好的答案是丹·奥西波夫的一个人。 I'd improve it like this. 我会像这样改进它。 (firing a CANCEL action event instead of manually erasing the pressed state). (触发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);
}

When writing code for swipe to delete on a list view, I wanted to prevent the vertical scrolling once the swipe had been detected. 在列表视图上编写用于滑动删除的代码时,我想在检测到滑动后阻止垂直滚动。 I set a boolean flag in the ACTION_MOVE section once the swipe to delete conditions had been met. 一旦满足滑动删除条件,我在ACTION_MOVE部分设置了一个布尔标志。 The dispatchTouchEvent method checks that condition and prevents the scroll from working. dispatchTouchEvent方法检查该条件并阻止滚动工作。 In the ACTION_UP I set the flag back to false to re-enable the scroll. 在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);
}

My answer will be interesting for Xamarin and MvvmCross users. 我对Xamarin和MvvmCross用户的回答很有意思。 Main concept is the same like in previous posts, so main steps are: 主要概念与之前的帖子相同,因此主要步骤如下:

  1. Mute scroll events 静音滚动事件
  2. Change dynamically list height 动态更改列表高度

Here you are helper class, that allows to disable scroll in list view: 这里是helper类,允许在列表视图中禁用滚动:

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

This is the code Joe Blow (comment on OP post) pointed at on http://danosipov.com/?p=604 but I'm posting it here to preserve it in case the link is orphaned: 这是在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);
}
}

When you add this ListView to your layout remember to precede it with its package name, otherwise an exception will be thrown when you try to inflate it. 将此ListView添加到布局时,请记住在其前面加上其包名,否则在尝试对其进行充气时将引发异常。

Try this: 试试这个:

listViewObject.setTranscriptMode(0);

Works for me. 适合我。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM