以编程方式禁用ScrollView?


108

我想启用ScrollView并通过单击按钮禁用它。
禁用意味着ScrollView不存在..并启用它返回ScrollView。

我想要这样做是因为我有一个带有文本图像的画廊,然后单击按钮,屏幕方向会发生变化,因此在“横向”中,文本会变大。而且我希望使用ScrollView,以便图像不会自身拉伸并且文本变得不可读。

scrollview.Enabled=false / setVisibility(false) 什么都不做。

xml:

<ScrollView 
android:id="@+id/QuranGalleryScrollView" 
android:layout_height="fill_parent" 
android:layout_width="fill_parent">
<Gallery android:id="@+id/Gallery" 
android:layout_width="fill_parent" 
android:layout_height="fill_parent"
android:scrollbars="horizontal"></Gallery>
</ScrollView>

谢谢

Edit1:我不能使用“可见性”,因为那样会同时隐藏Gallery,所以我想隐藏ScrollView的效果。当使用ScrollView时,“图库”中的图像将变为滚动状态,并且不适合屏幕,因此您必须滚动才能查看整个图像,我不想在单击按钮时禁用/启用该功能。

我尝试了这个:

((ScrollView)findViewById(R.id.QuranGalleryScrollView)).setOnTouchListener(null);
                        ((ScrollView)findViewById(R.id.QuranGalleryScrollView)).setHorizontalScrollBarEnabled(false);
                        ((ScrollView)findViewById(R.id.QuranGalleryScrollView)).setVerticalScrollBarEnabled(false);
                        ((ScrollView)findViewById(R.id.QuranGalleryScrollView)).setEnabled(false);

但是图库中的图像仍然可以滚动并且不适合屏幕。.解决方案是什么?

Answers:


187

首先要注意以下几点:

  1. 您不能禁用ScrollView的滚动。您将需要扩展到ScrollView并重写该onTouchEvent方法以false在满足某些条件时返回。
  2. Gallery组件无论是否在ScrollView中都可以水平滚动-ScrollView仅提供垂直滚动(水平滚动需要水平滚动视图)
  3. 您似乎在说图像扩展本身有问题-与ScrollView无关,您可以使用android:scaleType属性(XML)或setScaleType方法更改ImageView缩放的方式-例如,ScaleType.CENTER将不会拉伸图像并且会以原始大小居中

您可以ScrollView进行如下修改以禁用滚动

class LockableScrollView extends ScrollView {

    ...

    // true if we can scroll (not locked)
    // false if we cannot scroll (locked)
    private boolean mScrollable = true;

    public void setScrollingEnabled(boolean enabled) {
        mScrollable = enabled;
    }

    public boolean isScrollable() {
        return mScrollable;
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                // if we can scroll pass the event to the superclass
                return mScrollable && super.onTouchEvent(ev);
            default:
                return super.onTouchEvent(ev);
        }
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        // Don't do anything with intercepted touch events if
        // we are not scrollable
        return mScrollable && super.onInterceptTouchEvent(ev);
    }

}

然后,您将使用

<com.mypackagename.LockableScrollView 
    android:id="@+id/QuranGalleryScrollView" 
    android:layout_height="fill_parent" 
    android:layout_width="fill_parent">

    <Gallery android:id="@+id/Gallery" 
        android:layout_width="fill_parent" 
        android:layout_height="fill_parent"
        android:scrollbars="horizontal">
    </Gallery>

</com.mypackagename.LockableScrollView>

在您的XML文件中(只需将更改为ScrollViewspecial LockableScrollView)。

然后打电话

((LockableScrollView)findViewById(R.id.QuranGalleryScrollView)).setScrollingEnabled(false);

禁用视图滚动。

我认为您不仅仅可以通过滚动来实现所需的效果(例如,画廊可以使用上面的代码进行滚动)-我建议您对这三个组件(画廊, ScrollView,ImageView)以查看每个属性具有的属性以及其行为。


该类的外观如下:pastebin.com/dsWSWR4x 但我收到错误消息:“ LockableScrollView类型的onTouch(View,MotionEvent)方法必须重写或实现超类型方法”
Omar

抱歉,改正了我代码中的错误-应该是onTouchEvent(MotionEvent ev)
Joseph Earl

1
好的,现在代码符合了,尽管当我运行应用程序时它崩溃了……当我删除此类并返回<ScrollView而不是您的类时,应用程序运行良好!
奥马尔

嗨,奥马尔,您能发帖看到错误吗?确保将<com.mypackagename.LockableScrollView>中的com.mypackagename更改为您自己的名称
Joseph Earl

1
好答案。如果将大小写MotionEvent.ACTION_DOWN:更改为大小写MotionEvent.ACTION_MOVE:大小写MotionEvent.ACTION_DOWN:您还可以在拖动时禁用滚动。但是,每个人当然都需要如何使用它。
幸运

70

我走了这样:

        scrollView.setOnTouchListener(new View.OnTouchListener() {

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            // TODO Auto-generated method stub
            return isBlockedScrollView;
        }
    });

3
简单,效果很好。关键是要使用变量(例如isBlockedScrollView)来控制何时要启用滚动。在应允许滚动时将其设置为true,否则将其设置为false。
PeteH 2014年

5
@PeteH,我不知道为什么,但是我的ListView工作却相反:禁用滚动时为true,启用滚动时为false。
马查多

@霍姆斯:你是对的,当你想阻止滚动时,这是正确的
lily

1
效果漂亮 优雅的解决方案。
科迪

1
@Machado您必须返回true才能阻止滚动的原因是,触摸侦听器采用返回的布尔值来确定是否应该使用touch事件。如果返回false,则滚动视图将继续将touch事件传递给其滚动侦听器。
文斯

11

找到了刚刚设置的简单解决方案

ScrollView.requestDisallowInterceptTouchEvent(true);

5
requestDisallowInterceptTouchEvent仅适用于要锁定的视图子级。所以它更像是mLinearLayout.requestDisallowInterceptTouchEvent(true);
Muz

6

禁用ScrollView

ScrollView sw = (ScrollView) findViewById(R.id.scrollView1);
sw.setOnTouchListener(new OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        return true;
    }
});

5

首先,我使用了第一个评论中发布的代码,但我将其更改为:

    public class LockableScrollView extends ScrollView {

    public LockableScrollView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        // TODO Auto-generated constructor stub
    }
    public LockableScrollView(Context context, AttributeSet attrs) 
    {
        super(context, attrs);
    }

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

    // true if we can scroll (not locked)
    // false if we cannot scroll (locked)
    private boolean mScrollable = true;

    public void setScrollingEnabled(boolean enabled) {
        mScrollable = enabled;
    }

    public boolean isScrollable() {
        return mScrollable;
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                // if we can scroll pass the event to the superclass
                if (mScrollable) return super.onTouchEvent(ev);
                // only continue to handle the touch event if scrolling enabled
                return mScrollable; // mScrollable is always false at this point
            default:
                return super.onTouchEvent(ev);
        }
    }



@Override  
public boolean onInterceptTouchEvent(MotionEvent ev) {
    switch (ev.getAction()) {     
    case MotionEvent.ACTION_DOWN:         
        // if we can scroll pass the event to the superclass      
        if (mScrollable) return super.onInterceptTouchEvent(ev);      
        // only continue to handle the touch event if scrolling enabled    
        return mScrollable; // mScrollable is always false at this point     
        default:          
            return super.onInterceptTouchEvent(ev);      
            }
    }

}

然后我就这样叫了

((LockableScrollView)findViewById(R.id.scrollV)).setScrollingEnabled(false);

因为我尝试过

((LockableScrollView)findViewById(R.id.scrollV)).setIsScrollable(false);

但它说setIsScrollable是不确定的

我希望这能帮到您


注意:如果您ScrollView是布局类的主布局容器,则需要前两个构造函数。
actaram

如果您触摸某个按钮或其他先拦截触摸的内容,则滚动视图仍会滚动
Cristi Băluță

3

这是一个更简单的解决方案。如果要通过触摸绕过滚动,请覆盖onTouch()for ScrollView OnTouchListener并返回false。编程滚动仍然有效,无需扩展ScrollView类。

mScroller.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
  return isScrollable;
}
});

1
!isScrollable,因为返回值为true表示事件已被拦截。
goRGon '16

3

我没有足够的分数来评论答案,但我想说的是mikec的答案对我有用,只是我必须将其更改为返回!isScrollable,如下所示:

mScroller.setOnTouchListener(new OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
      return !isScrollable;
    }
});

1
@Override  
public boolean onInterceptTouchEvent(MotionEvent ev) {
    switch (ev.getAction()) {     
    case MotionEvent.ACTION_DOWN:         
        // if we can scroll pass the event to the superclass      
        if (mScrollable) return super.onInterceptTouchEvent(ev);      
        // only continue to handle the touch event if scrolling enabled    
        return mScrollable; // mScrollable is always false at this point     
        default:          
            return super.onInterceptTouchEvent(ev);      
            }
    }

1

@JosephEarl +1他在这里有一个很好的解决方案,对我来说非常适合,但需要进行一些小的修改以编程方式进行。


这是我所做的较小更改:

LockableScrollView类别:

public boolean setScrollingEnabled(boolean enabled) {
    mScrollable = enabled;
    return mScrollable;
}

主要活动:

LockableScrollView sv;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    sv = new LockableScrollView(this);
    sv.setScrollingEnabled(false);
}

1

我在NestedScrollView上有一个布局,使用了touch事件并禁用了滚动:

progressBarLayout.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                return true;
            }
        });

并启用:

progressBarLayout.setOnTouchListener(null);

1

您可以创建一个CustomScrollView,可以为其禁用对其他视图的干扰。尽管这有时可能会给最终用户带来不便。请谨慎使用。

这是代码:

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.ViewParent;

public class CustomScrollView extends android.widget.ScrollView {

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

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

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

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev)
    {
        /* Prevent parent controls from stealing our events once we've gotten a touch down */
        if (ev.getActionMasked() == MotionEvent.ACTION_DOWN)
        {
            ViewParent p = getParent();
            if (p != null)
                p.requestDisallowInterceptTouchEvent(true);
        }

        return false;
    }
}

如何使用CustomScrollView?

您可以将CustomScrollView作为父级添加到要在其中添加另一个Scrollview作为子级视图的屏幕,并且整个屏幕都是可滚动的。我将此用于RelativeLayout。

<?xml version="1.0" encoding="utf-8"?>
<**package.**CustomScrollView 
xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/some_id"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    xmlns:tools="http://schemas.android.com/tools">
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    #**Inside this I had a TableLayout and TableRow. Inside the TableRow,**
    #**I had a TextView which I made scrollable from Java Code.**
    #**textView.setMovementMethod(new ScrollingMovementMethod());**
    </RelativeLayout>
</ankit.inventory.ankitarora.inventorymanagementsimple.CustomScrollView>

它适合我的情况。


1
public class LockableScrollView extends ScrollView {

    private boolean mScrollable = true;

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

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

    public LockableScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public LockableScrollView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    public void setScrollable(boolean enabled) {
        mScrollable = enabled;
    }

    public boolean isScrollable() {
        return mScrollable;
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        return mScrollable && super.onTouchEvent(ev);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return mScrollable && super.onInterceptTouchEvent(ev);
    }
}

0

这有帮助吗?

((ScrollView)findViewById(R.id.QuranGalleryScrollView)).setOnTouchListener(null);

1
我不认为这有什么不同,我仍然有同样的问题
Omar

0

您可以扩展图库并在需要时使用一些标志来禁用滚动:

public class MyGallery extends Gallery {

public boolean canScroll;

public MyGallery(Context context, AttributeSet attrs) {
    canScroll = true;
    super(context, attrs);
}

public void setCanScroll(boolean flag)
{
    canScroll = flag;
}

@Override
public boolean onScroll(android.view.MotionEvent e1, android.view.MotionEvent e2, float distanceX, float distanceY) {
    if (canScroll)
        return super.onScroll(e1,e2,distancex,distancey);
    else
        return false;
}

@Override
public boolean onSingleTapUp(MotionEvent e)
{
    if (canScroll)
        return super.onSingleTapUp(ey);
    else
        return false;
}

@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
{
    if (canScroll)
        return super.onFling(e1,e2,velocityX,velocityY);
    else
        return false;
}
}

-3

正如您在文档中所看到的,您不能将可见性设置为false。在您的情况下,您可能应该使用:

scrollview.setVisibility(Visibility.GONE);

2
这也会隐藏图库,因此不是解决方案,我编辑了更多详细信息
Omar

-6

在按钮上单击监听器就可以了

ScrollView sView = (ScrollView)findViewById(R.id.ScrollView01);

sView.setVerticalScrollBarEnabled(false);
sView.setHorizontalScrollBarEnabled(false);

因此在单击按钮时不会启用滚动条


2
这只隐藏了我猜的小节..但是没有scrollview的效果
Omar

1
它不会允许您滚动也不会隐藏画廊视图
Sumant 2011年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.