Отключить 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>
Спасибо
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);
Но все же изображения в Галерее прокручиваются и не умещаются на экране. Какое это решение?
20 ответов
Несколько пунктов для начала:
- Вы не можете отключить прокрутку ScrollView. Вам нужно будет расширить ScrollView и переопределить
onTouchEvent
способ вернутьfalse
когда какое-то условие соответствует. - Компонент "Галерея" прокручивается по горизонтали независимо от того, находится ли он в ScrollView или нет - ScrollView обеспечивает только вертикальную прокрутку (для горизонтальной прокрутки необходим горизонтальный просмотр)
- Вы, кажется, говорите, что у вас есть проблема с самим растяжением изображения - это не имеет ничего общего с 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), чтобы увидеть, какие свойства у каждого есть и как он себя ведет.
Я пошел по этому пути:
scrollView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
return isBlockedScrollView;
}
});
Нашел это простое решение, просто установил
ScrollView.requestDisallowInterceptTouchEvent(true);
Отключить ScrollView
ScrollView sw = (ScrollView) findViewById(R.id.scrollView1);
sw.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return true;
}
});
У меня недостаточно очков, чтобы комментировать ответ, но я хотел сказать, что ответ mikec работал на меня, за исключением того, что мне пришлось изменить его, чтобы вернуть! IsScrollable примерно так:
mScroller.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return !isScrollable;
}
});
Для начала я использовал код, опубликованный в первом комментарии, но изменил его так:
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 не определена
Я надеюсь, что это поможет вам
У меня был макет поверх NestedScrollView, потребляющий событие касания и отключающий прокрутку:
progressBarLayout.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
return true;
}
});
и включить:
progressBarLayout.setOnTouchListener(null);
Вот более простое решение. Переопределить onTouch()
для ScrollView
OnTouchListener
и верните false, если вы хотите обойти прокрутку касанием. Программная прокрутка все еще работает, и нет необходимости расширять ScrollView
учебный класс.
mScroller.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return isScrollable;
}
});
Расширить и переопределить
onInterceptTouchEvent
вернуться
false
, в Котлине:
class SV(context: Context) : HorizontalScrollView(context) {
var allowUserScroll = false
override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
return if (allowUserScroll) super.onInterceptTouchEvent(ev) else false
}
}
Достаточно!
(Преимущество перед использованием
setOnTouchListener
это так инвалид
ScrollView
никак не мешает обработке сенсорных событий потомков)
Котлин:
scrollView.setOnTouchListener { _, _ -> true }
PS. Vel_daN: Люби то, что ты делаешь.
@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);
}
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);
}
}
Вы можете создать 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>
Это сработало для моего случая.
@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);
}
}
Вы можете расширить галерею и использовать некоторые флажки, чтобы отключить прокрутку, когда хотите:
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;
}
}
Я могу опоздать, но все же...
Этот ответ основан на динамическом удалении и добавлении представлений.
Чтобы отключить прокрутку:
View child = scoll.getChildAt(0);// since scrollView can only have one direct child
ViewGroup parent = (ViewGroup) scroll.getParent();
scroll.removeView(child); // remove child from scrollview
parent.addView(child,parent.indexOfChild(scroll));// add scroll child at the position of scrollview
parent.removeView(scroll);// remove scrollView from parent
Чтобы включить ScrollView, просто отмените процесс
Это помогает?
((ScrollView)findViewById(R.id.QuranGalleryScrollView)).setOnTouchListener(null);
Вот расширение Котлина
@SuppressLint("ClickableViewAccessibility")
fun NestedScrollView.disableScroll() {
this.setOnTouchListener { _, _ ->
true
}
}
@SuppressLint("ClickableViewAccessibility")
fun NestedScrollView.enableScroll() {
this.setOnTouchListener { _, _ ->
false
}
}
@SuppressLint("ClickableViewAccessibility")
fun ScrollView.disableScroll() {
this.setOnTouchListener { _, _ ->
true
}
}
@SuppressLint("ClickableViewAccessibility")
fun ScrollView.enableScroll() {
this.setOnTouchListener { _, _ ->
false
}
}
Как вы можете видеть в документации, вы не можете установить видимость на false. В вашем случае вы, вероятно, должны использовать:
scrollview.setVisibility(Visibility.GONE);
При нажатии кнопки слушатель просто сделать
ScrollView sView = (ScrollView)findViewById(R.id.ScrollView01);
sView.setVerticalScrollBarEnabled(false);
sView.setHorizontalScrollBarEnabled(false);
чтобы при нажатии кнопки полоса прокрутки не была включена