프로그래밍 방식으로 ScrollView를 비활성화 하시겠습니까?


108

ScrollView를 활성화하고 버튼 클릭으로 비활성화하고 싶습니다.
Disable은 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가있을 때 Gallery의 이미지가 scrollabale이되고 화면에 맞지 않으므로 전체 이미지를 보려면 스크롤해야하므로 버튼 클릭으로 비활성화 / 활성화하고 싶지 않습니다.

나는 이것을 시도했다 :

((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. 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)를 사용하여 각각의 속성과 작동 방식을 확인합니다.


클래스 모양은 다음과 같습니다. pastebin.com/dsWSWR4x 하지만 'LockableScrollView 유형의 onTouch (View, MotionEvent) 메서드는 수퍼 타입 ​​메서드를 재정의하거나 구현해야합니다'라는 오류가 발생합니다.
Omar

사과, 내 코드의 오류 수정onTouchEvent(MotionEvent ev)
Joseph Earl

1
좋아, 이제 코드가 준수되지만 앱을 실행할 때 충돌이 발생합니다 ...이 클래스를 제거하고 클래스 대신 <ScrollView를 반환하면 앱이 제대로 작동합니다!
Omar

안녕하세요 Omar에서 발생한 오류를 게시 할 수 있습니까? 확인 변경 사항을 확인합니다 com.mypackagename에서 <com.mypackagename.LockableScrollView> 자신의 일에
조셉 얼

1
좋은 대답입니다. MotionEvent.ACTION_DOWN : case MotionEvent.ACTION_MOVE : case MotionEvent.ACTION_DOWN : case MotionEvent.ACTION_DOWN : case를 변경하면 드래그하는 동안에도 스크롤을 비활성화 할 수 있습니다. 그러나 그가 그것을 사용하는 방법은 물론 모든 사람에게 있습니다.
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

5
@PeteH, 왜 그런지 모르겠지만 내 ListView작업은 반대로 작동합니다. 스크롤링이 비활성화되면 true이고 활성화되면 false입니다.
Machado

@Holmes : 당신 말이 맞아요, 스크롤을 막고 싶을 때 진실입니다
lily

1
또한 스크롤 뷰 내에 자식 뷰 (버튼)가 있으며 onInterceptTouchEvent ()를 재정의하지 않아도 여전히 상호 작용할 수 있습니다! 우아한 솔루션.
코디

1
@Machado 스크롤을 차단하기 위해 true를 반환해야하는 이유는 터치 리스너가 터치 이벤트를 소비해야하는지 여부를 결정하기 위해 반환 된 부울 값을 사용하기 때문입니다. false를 반환하면 스크롤 뷰는 터치 이벤트를 스크롤 리스너에 전달합니다.
Vince

11

이 간단한 솔루션이 방금 설정되었습니다.

ScrollView.requestDisallowInterceptTouchEvent(true);

5
requestDisallowInterceptTouchEvent잠긴 뷰 의 자식 에 대해서만 작동합니다 . 그래서 그것은 더 비슷할 것입니다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()for를 재정의하고 ScrollView OnTouchListenerfalse를 반환합니다. 프로그래밍 방식 스크롤은 여전히 ​​작동하며 ScrollView클래스 를 확장 할 필요가 없습니다 .

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

1
true 반환 값은 이벤트가 차단되었음을 의미하므로! isScrollable입니다.
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를 사용하는 방법?

다른 Scrollview를 자식보기로 추가하려는 화면에 CustomScrollView를 부모로 추가 할 수 있으며 전체 화면을 스크롤 할 수 있습니다. 나는 이것을 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
이것은 또한 갤러리를 숨길 것이므로 해결책이 아닙니다. 자세한 내용으로 게시물을 편집했습니다
Omar

-6

버튼 클릭 리스너에서

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

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

버튼 클릭시 스크롤바가 활성화되지 않도록


2
이것은 내가 추측하는 바만 숨 깁니다. 그러나 scrollview의 효과는 아닙니다
Omar

1
그것은 당신이 스크롤하는 것을 허용하지 않을 것입니다 또한 갤러리보기를 숨기지 않을 것입니다
Sumant
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.