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

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

Ответы:


187

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

  1. Вы не можете отключить прокрутку ScrollView. Вам нужно будет перейти на ScrollView и переопределить onTouchEventметод, который будет возвращаться falseпри совпадении какого-либо условия.
  2. Компонент галереи прокручивается по горизонтали независимо от того, находится он в 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), чтобы узнать, какие свойства у каждого из них и как они себя ведут.


Вот как выглядит класс: pastebin.com/dsWSWR4x Но я получаю сообщение об ошибке «Метод onTouch (View, MotionEvent) типа LockableScrollView должен переопределять или реализовывать метод супертипа»
Омар

Извините, исправил ошибки в моем коде - так и должно было бытьonTouchEvent(MotionEvent ev)
Джозеф Эрл

1
Хорошо, теперь код соответствует, хотя когда я запускаю приложение, оно вылетает ... и когда я удаляю этот класс и возвращаю <ScrollView вместо вашего класса, приложение работает нормально!
Омар

Привет, Омар, не могли бы вы опубликовать полученную ошибку? Не забудьте изменить com.mypackagename в <com.mypackagename.LockableScrollView> на свой собственный
Джозеф Эрл,

1
Хороший ответ. Если вы измените регистр MotionEvent.ACTION_DOWN: на регистр MotionEvent.ACTION_MOVE: case MotionEvent.ACTION_DOWN: вы также сможете отключить прокрутку при перетаскивании. Но, конечно, каждому решать, как ему это использовать.
luky

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 06

5
@PeteH, я не знаю почему, но у меня ListViewработает наоборот: true, когда прокрутка отключена, и false, когда она включена.
Machado

@Holmes: вы правы, правда, когда вы хотите заблокировать прокрутку
lily

1
Работает прекрасно.Кроме того, у меня есть дочерние представления (кнопки) внутри scrollview, и я все еще могу взаимодействовать с ними, несмотря на то, что не переопределяю onInterceptTouchEvent ()! Элегантное решение.
Коди,

1
@Machado Причина, по которой вы должны вернуть true, чтобы заблокировать прокрутку, заключается в том, что слушатель касания принимает возвращаемое логическое значение, чтобы определить, следует ли использовать событие касания или нет. Если вы вернете false, представление прокрутки продолжит передачу события касания его слушателю прокрутки.
Винс

11

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

ScrollView.requestDisallowInterceptTouchEvent(true);

5
requestDisallowInterceptTouchEventработает только для блокировки дочернего элемента View. Так было бы больше похоже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

Если вы сначала коснетесь кнопки или чего-то еще, что перехватывает касания, прокрутка все равно будет прокручиваться
Кристи Бэлуцэ

3

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

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

1
! isScrollable, поскольку возвращаемое значение true означает, что событие было перехвачено.
goRGon

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, использующий событие касания и отключивший прокрутку:

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
Я не думаю, что это имело какое-то значение, у меня все еще та же проблема
Омар

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
Это также скроет галерею, так что это не решение, я отредактировал сообщение с более подробной информацией
Омар

-6

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

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

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

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


2
Я думаю, это только скрывает полосы ... но не эффект прокрутки
Омар

1
он не позволит вам прокручивать, также он не будет скрывать вид галереи
Sumant
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.