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

我想启用 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>

我不能使用 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);

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

【问题讨论】:

    标签: android android-scrollview


    【解决方案1】:

    几点开始:

    1. 您不能禁用 ScrollView 的滚动。您需要扩展到 ScrollView 并覆盖 onTouchEvent 方法以在某些条件匹配时返回 false
    2. 无论是否在 ScrollView 中,Gallery 组件都会水平滚动 - ScrollView 仅提供垂直滚动(水平滚动需要 Horizo​​ntalScrollView)
    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 文件中(只需将 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_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>
            

            它适用于我的情况。

            【讨论】:

              【解决方案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);
                    

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

                    【讨论】:

                    • 这只会隐藏我猜想的酒吧.. 但不是滚动视图的效果
                    • 它不会让你滚动也不会隐藏画廊视图
                    猜你喜欢
                    • 1970-01-01
                    • 2022-10-19
                    • 1970-01-01
                    • 1970-01-01
                    • 2021-08-07
                    • 2010-10-15
                    • 1970-01-01
                    • 2016-11-21
                    • 1970-01-01
                    相关资源
                    最近更新 更多