以编程方式禁用 ScrollView?

Posted

技术标签:

【中文标题】以编程方式禁用 ScrollView?【英文标题】:Disable ScrollView Programmatically? 【发布时间】:2011-08-11 10:07:38 【问题描述】:

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

我想要那个,因为我有一个带有文本图像的画廊,并且在一个按钮上单击屏幕方向会发生变化,所以在横向中,文本会变得更大。而且我想要 ScrollView,这样图像就不会自行拉伸并且文本变得不可读。

scrollview.Enabled=false / setVisibility(false) 什么也没做。

xml:

<ScrollView 
android:id="@+id/QuranGalleryScrollView" 
android:layout_ 
android:layout_>
<Gallery android:id="@+id/Gallery" 
android:layout_ 
android:layout_
android:scrollbars="horizontal"></Gallery>
</ScrollView>

我不能使用 Visibility (gone),因为那样也会隐藏 Gallery,我想要的是隐藏 ScrollView 的效果。当有 ScrollView 时,Gallery 中的图像变得可滚动并且不适合屏幕,因此您必须滚动才能看到整个图像。我不想在单击按钮时禁用/启用它。

我试过这个:

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

但图库中的图像仍然是可滚动的,并且不适合屏幕。有什么办法解决这个问题?

【问题讨论】:

【参考方案1】:

几点开始:

    您不能禁用 ScrollView 的滚动。您需要扩展到 ScrollView 并覆盖 onTouchEvent 方法以在某些条件匹配时返回 false。 无论是否在 ScrollView 中,Gallery 组件都会水平滚动 - ScrollView 仅提供垂直滚动(水平滚动需要 Horizo​​ntalScrollView) 您似乎说图像拉伸本身存在问题-这与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_ 
    android:layout_>

    <Gallery android:id="@+id/Gallery" 
        android:layout_ 
        android:layout_
        android:scrollbars="horizontal">
    </Gallery>

</com.mypackagename.LockableScrollView>

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

然后调用

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

禁用视图的滚动。

我认为,为了达到您想要的结果(例如,画廊将保持可滚动使用上面的代码),我认为您不仅仅是禁用滚动的问题 - 我建议您对这三个组件中的每一个进行更多研究(Gallery、ScrollView、ImageView)来查看每个属性具有哪些属性以及其行为方式。

【讨论】:

类的外观如下:pastebin.com/dsWSWR4x 但我收到错误“LockableScrollView 类型的 onTouch(View, MotionEvent) 方法必须覆盖或实现超类型方法” 抱歉,更正了我的代码中的错误——应该是onTouchEvent(MotionEvent ev) 好的,现在代码符合要求,虽然当我运行应用程序时它崩溃了......当我删除这个类并返回 嗨奥马尔你能发布你得到的错误吗?确保将 中的 com.mypackagename 更改为您自己的 好答案。如果您将 case MotionEvent.ACTION_DOWN: 更改为 case MotionEvent.ACTION_MOVE: case MotionEvent.ACTION_DOWN: 您还可以在拖动时禁用滚动。当然,每个人都需要如何使用它。【参考方案2】:

我是这样走的:

        scrollView.setOnTouchListener(new View.OnTouchListener() 

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

【讨论】:

简单而且效果很好。关键点是使用一个变量(例如,isBlockedScrollView)来控制何时启用滚动。应允许滚动时将其设置为 true,否则设置为 false。 @PeteH,我不知道为什么,但我的ListView 工作方式相反:禁用滚动时为 true,启用滚动时为 false。 @Holmes:你是对的,当你想阻止滚动时是真的 工作得很好。此外,我在滚动视图中有子视图(按钮),尽管没有覆盖 onInterceptTouchEvent(),我仍然可以与它们交互!优雅的解决方案。 @Machado 必须返回 true 才能阻止滚动的原因是触摸侦听器采用返回的布尔值来确定是否应该消耗触摸事件。如果您返回 false,则滚动视图将继续将触摸事件传递给其滚动侦听器。【参考方案3】:

发现这个简单的解决方案刚刚设置

ScrollView.requestDisallowInterceptTouchEvent(true);

【讨论】:

requestDisallowInterceptTouchEvent 仅适用于要锁定的 View 的 child。所以它更像是mLinearLayout.requestDisallowInterceptTouchEvent(true); 这正是我所需要的。谢谢。【参考方案4】:

禁用滚动视图

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 是布局类的主布局容器,则需要前两个构造函数。 如果你先触摸一个按钮或其他拦截触摸的东​​西,滚动视图仍然会滚动【参考方案6】:

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

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

【讨论】:

【参考方案7】:

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

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

);

【讨论】:

!isScrollable 因为真正的返回值意味着事件被拦截了。【参考方案8】:

我在 NestedScrollView 上有一个布局,消耗了触摸事件并禁用了滚动:

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

并启用:

progressBarLayout.setOnTouchListener(null);

【讨论】:

我在androidx.core.widget.NestedScrollView 上使用了setOnTouchListener,效果很好。然后将其设置为 null 以重新启用它。【参考方案9】:
@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);      
            
    

【讨论】:

【参考方案10】:

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


以下是我所做的小改动:

LockableScrollView 类:

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

MainActivity:

LockableScrollView sv;

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

【讨论】:

【参考方案11】:

你可以制作一个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_
    android:layout_
    xmlns:tools="http://schemas.android.com/tools">
    <RelativeLayout
        android:layout_
        android:layout_>
    #**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>

它适用于我的情况。

【讨论】:

【参考方案12】:
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);
    

【讨论】:

【参考方案13】:

科特林:


scrollView.setOnTouchListener  _, _ -> true 

附言。 Vel_daN:爱​​你所做的事情?。

【讨论】:

【参考方案14】:

这有帮助吗?

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

【讨论】:

我认为它没有任何区别,我仍然有同样的问题【参考方案15】:

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

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;


【讨论】:

【参考方案16】:

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

scrollview.setVisibility(Visibility.GONE);

【讨论】:

这也将隐藏画廊,所以它不是解决方案,我编辑了更多细节的帖子 天啊,你怎么能把这个作为严肃的答案发布......【参考方案17】:

按钮点击监听器就可以了

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

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

这样在按钮单击时滚动条不会启用

【讨论】:

这只会隐藏我猜想的酒吧.. 但不是滚动视图的效果 它不会让你滚动也不会隐藏画廊视图

以上是关于以编程方式禁用 ScrollView?的主要内容,如果未能解决你的问题,请参考以下文章

UIColectionView Vertical Scrolling inside a Scrollview - 在集合视图区域中滚动时禁用滚动视图的滚动

Storyboard Scrollview with StackView inside not scrolling

禁用 ScrollView 操作

如何以编程方式设置scrollview高度

如何以编程方式将 ScrollView 滚动到底部

我可以在 Android 中以编程方式滚动 ScrollView 吗?