android 自定义listview不能滑动,android-禁用在listview中滚动

当需要暂时禁用Android ListView的滚动功能时,可以使用多种方法。例如,可以通过将OnTouchListener附加到ListView并拦截ACTION_MOVE事件,或者重写dispatchTouchEvent()方法来实现。此外,还可以使用listView.setEnabled(false),但这会同时禁用行选择。还有其他更复杂的方法,如自定义ListView以处理特定的触摸事件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

android-禁用在listview中滚动

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

谢谢

10个解决方案

44 votes

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

listView.setOnTouchListener(new OnTouchListener() {

public boolean onTouch(View v, MotionEvent event) {

return (event.getAction() == MotionEvent.ACTION_MOVE);

}

});

Surya Wijaya Madjid answered 2020-08-02T20:02:30Z

42 votes

在您的自定义ListView中:

@Override

public boolean dispatchTouchEvent(MotionEvent ev){

if(ev.getAction()==MotionEvent.ACTION_MOVE)

return true;

return super.dispatchTouchEvent(ev);

}

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

Pointer Null answered 2020-08-02T20:02:09Z

28 votes

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

注意:这也会禁用行选择

Nikita answered 2020-08-02T20:02:54Z

8 votes

使您的CustomListView

@Override

public boolean onInterceptTouchEvent(MotionEvent ev) {

if(needToStop){

return false;}

return super.onInterceptTouchEvent(ev);

}

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

Mohammad Ersan answered 2020-08-02T20:03:18Z

8 votes

如果您有一个事件绑定到列表项,则使用任何这些解决方案拖动列表仍将触发该事件。 您想要使用以下方法来解决用户期望通过从所选项目上拖动(根据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]

Dan Osipov answered 2020-08-02T20:03:43Z

5 votes

对我来说,最好的答案是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);

}

Mauro Panzeri answered 2020-08-02T20:04:03Z

2 votes

在编写用于在列表视图上删除的滑动代码时,一旦检测到滑动,我想防止垂直滚动。 一旦满足删除条件的滑动操作,便在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() {

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

}

vilvic answered 2020-08-02T20:04:23Z

1 votes

对于Xamarin和MvvmCross用户,我的答案将很有趣。 主要概念与之前的文章相同,因此主要步骤如下:

静音滚动事件

动态更改列表高度

这是您的帮助器类,它允许禁用列表视图中的滚动:

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

}

}

}

user1700099 answered 2020-08-02T20:04:56Z

1 votes

这是Joe Blow(在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添加到布局中时,请记住在其包名称之前添加它,否则,当您尝试对其进行充气时,将引发异常。

Aspiring Dev answered 2020-08-02T20:05:21Z

1 votes

试试这个:

listViewObject.setTranscriptMode(0);

为我工作。

gopalj answered 2020-08-02T20:05:45Z

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值