Отключить ScrollView программно?

Я хотел бы включить 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>

Я не могу использовать видимость (ушел), так как это также скроет галерею, я хочу скрыть эффект 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);

Но все же изображения в галерее можно прокручивать и не умещать на экране. Что с этим делать?


person Omar    schedule 23.04.2011    source источник


Ответы (15)


Для начала несколько моментов:

  1. Вы не можете отключить прокрутку ScrollView. Вам нужно будет расширить до ScrollView и переопределить метод onTouchEvent, чтобы он возвращал false, когда выполняется какое-либо условие.
  2. Компонент Gallery прокручивается по горизонтали независимо от того, находится он в ScrollView или нет - ScrollView обеспечивает только вертикальную прокрутку (вам нужен HorizontalScrollView для горизонтальной прокрутки)
  3. Кажется, вы говорите, что у вас проблема с растяжением самого изображения - это не имеет ничего общего с ScrollView, вы можете изменить масштаб ImageView с помощью свойства android:scaleType (XML) или метода setScaleType - например, 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);

для отключения прокрутки обзора.

Я думаю, что у вас есть больше, чем просто проблема отключения прокрутки для достижения желаемого результата (например, галерея останется прокручиваемой с помощью приведенного выше кода) - я бы рекомендовал провести дополнительные исследования по каждому из трех компонентов (Галерея, ScrollView, ImageView), чтобы узнать, какие свойства у каждого из них и как они себя ведут.

person Joseph Earl    schedule 23.04.2011
comment
Вот как выглядит класс: pastebin.com/dsWSWR4x Но я получаю сообщение об ошибке «Метод onTouch (View, MotionEvent) типа LockableScrollView должен переопределять или реализовывать метод супертипа ' - person Omar; 23.04.2011
comment
Извиняюсь, исправил ошибки в моем коде - должно было быть onTouchEvent(MotionEvent ev) - person Joseph Earl; 23.04.2011
comment
Хорошо, теперь код соответствует, хотя когда я запускаю приложение, оно вылетает ... и когда я удаляю этот класс и возвращаю ‹ScrollView вместо вашего класса, приложение работает нормально! - person Omar; 24.04.2011
comment
Привет, Омар, не могли бы вы опубликовать полученную ошибку? Убедитесь, что измените com.mypackagename в ‹com.mypackagename.LockableScrollView› на свой собственный - person Joseph Earl; 24.04.2011
comment
В конце концов мне удалось заставить его работать, хотя я столкнулся с другими проблемами, поэтому я использовал грязное исправление, имея 2 галереи, одну в пределах прокрутки, а другую вне, и я просто спрячу / покажу их .. спасибо за ваше время хотя - person Omar; 24.04.2011
comment
Слил ответ Беовульфа Бьёрнсона с этим. - person Joseph Earl; 25.07.2012
comment
Этот код отлично работает, но по какой-то причине scrollview сбрасывается наверх при каждом событии касания, поэтому вы получаете действительно резкую прокрутку. Кто-нибудь еще имел дело с этим? - person Jacksonkr; 26.09.2012
comment
Я хочу вычислить значение mScrollable, вычислив горизонтальное отклонение моего движения касания внутри метода onInterceptTouchEvent. Может ли кто-нибудь сказать мне для ScrollView, как мне вычислить это внутри onInterceptTouchEvent - person chiranjib; 06.06.2013
comment
Хороший ответ. Если вы измените регистр MotionEvent.ACTION_DOWN: на регистр MotionEvent.ACTION_MOVE: case MotionEvent.ACTION_DOWN: вы также сможете отключить прокрутку при перетаскивании. Но, конечно, каждый знает, как ему это использовать. - person luky; 21.11.2016
comment
Как уже упоминалось, для завершения требуется дополнительный MotionEvent.ACTION_MOVE. Разработчик должен иметь возможность отключать / включать прокрутку во время выполнения жеста. - person DnR; 05.07.2020

Я прошел этот путь:

        scrollView.setOnTouchListener(new View.OnTouchListener() {

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            // TODO Auto-generated method stub
            return isBlockedScrollView;
        }
    });
person lily    schedule 15.03.2013
comment
Просто и отлично работает. Ключевым моментом является использование переменной (например, isBlockedScrollView) для управления тем, когда вы хотите включить прокрутку. Установите значение true, если прокрутка должна быть разрешена, и false в противном случае. - person PeteH; 06.09.2014
comment
@PeteH, я не знаю почему, но мой ListView работает наоборот: true, когда прокрутка отключена, и false, когда она включена. - person Machado; 19.08.2015
comment
@Holmes: вы правы, правда, когда вы хотите заблокировать прокрутку - person lily; 21.08.2015
comment
Работает прекрасно.Кроме того, у меня есть дочерние представления (кнопки) в режиме прокрутки, и я все еще могу взаимодействовать с ними, несмотря на то, что не переопределяю onInterceptTouchEvent ()! Элегантное решение. - person Cody; 07.03.2016
comment
@Machado Причина, по которой вы должны вернуть истину, чтобы заблокировать прокрутку, заключается в том, что слушатель касания принимает возвращаемое логическое значение, чтобы определить, следует ли использовать событие касания или нет. Если вы вернете false, представление прокрутки продолжит передачу события касания его слушателю прокрутки. - person Vince; 13.08.2018
comment
Ницца. Мне понравилось. - person Reza; 10.01.2021

Нашел это простое решение, просто установил

ScrollView.requestDisallowInterceptTouchEvent(true);
person JWqvist    schedule 20.01.2014
comment
requestDisallowInterceptTouchEvent работает только для блокировки дочернего представления. Так было бы больше похоже на mLinearLayout.requestDisallowInterceptTouchEvent(true); - person Muz; 22.02.2014

Отключить ScrollView

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

Для начала я использовал код, опубликованный в первом комментарии, но изменил его следующим образом:

    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 не определен

Я надеюсь, что это поможет вам

person Souhaieb    schedule 27.02.2014
comment
Примечание: первые два конструктора необходимы, если ваш ScrollView является основным контейнером макета вашего класса макета. - person actaram; 28.02.2015
comment
Если вы нажмете кнопку или что-то еще, что сначала перехватит касания, прокрутка все равно будет прокручиваться - person Cristi Băluță; 16.04.2019

У меня недостаточно очков, чтобы прокомментировать ответ, но я хотел сказать, что ответ mikec сработал для меня, за исключением того, что мне пришлось изменить его, чтобы вернуть! IsScrollable вот так:

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

Вот более простое решение. Переопределите onTouch() для ScrollView OnTouchListener и верните false, если вы хотите обойти прокрутку прикосновением. Программная прокрутка по-прежнему работает, и нет необходимости расширять класс ScrollView.

mScroller.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
  return isScrollable;
}
});
person mikec    schedule 26.06.2012
comment
! isScrollable, поскольку возвращаемое значение true означает, что событие было перехвачено. - person goRGon; 14.05.2016

У меня был макет над NestedScrollView, использующий событие касания и отключивший прокрутку:

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

и включить:

progressBarLayout.setOnTouchListener(null);
person SpyZip    schedule 19.12.2016
comment
Я использовал setOnTouchListener на androidx.core.widget.NestedScrollView, и это отлично сработало. Затем установите для него значение null, чтобы включить его обратно. - person Ray Hunter; 19.03.2021

@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);
}
person jnthnjns    schedule 07.11.2012

Вы можете создать 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>

В моем случае это сработало.

person Ankit Arora    schedule 02.03.2017

Это помогает?

((ScrollView)findViewById(R.id.QuranGalleryScrollView)).setOnTouchListener(null);
person rajath    schedule 23.04.2011
comment
Я не думаю, что это имело какое-либо значение, у меня все еще та же проблема - person Omar; 23.04.2011

Вы можете расширить галерею и использовать какой-либо флаг для отключения прокрутки, когда хотите:

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;
}
}
person Megarushing    schedule 28.10.2012

Kotlin:


scrollView.setOnTouchListener { _, _ -> true }

PS. Vel_daN: Любите то, что делаете ????.

person Владислав Шестернин    schedule 14.07.2021

Как видно из документации, вы не может установить для видимости значение false. В вашем случае вам, вероятно, следует использовать:

scrollview.setVisibility(Visibility.GONE);
person Community    schedule 23.04.2011
comment
Это также скроет галерею, поэтому это не решение, я отредактировал сообщение с более подробной информацией - person Omar; 23.04.2011

при нажатии кнопки слушатель просто делает

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

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

так что полоса прокрутки не включается при нажатии кнопки

person Sumant    schedule 23.04.2011
comment
Я думаю, это только скрывает полосы ... но не эффект прокрутки - person Omar; 23.04.2011
comment
он не позволит вам прокручивать, а также не скроет просмотр галереи - person Sumant; 23.04.2011