ViewPager에서 스크롤을 비활성화 할 수 있습니까


138

나는이 ViewPager을 인스턴스화하는가 View. 검색 결과가보기로 반환되는 동안 뷰 페이저와 자식 버튼의 스크롤을 일시적으로 비활성화하고 싶습니다. 전화를 걸 viewPager.setEnabled(false)었지만 비활성화하지는 않습니다.

누구든지 아이디어가 있습니까?


답변:


355

간단한 해결책은 플래그 ViewPager가있는 자체 하위 클래스를 만드는 것 입니다. 그런 다음 and 메소드를 대체하십시오 . 경우 인보 진정한 동일 그렇지 않으면, 방법 .private booleanisPagingEnabledonTouchEventonInterceptTouchEventisPagingEnabledsuperreturn

public class CustomViewPager extends ViewPager {

    private boolean isPagingEnabled = true;

    public CustomViewPager(Context context) {
        super(context);
    }

    public CustomViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return this.isPagingEnabled && super.onTouchEvent(event);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        return this.isPagingEnabled && super.onInterceptTouchEvent(event);
    }

    public void setPagingEnabled(boolean b) {
        this.isPagingEnabled = b;
    }
}

그런 다음 Layout.XML파일 에서 <com.android.support.V4.ViewPager>태그를 <com.yourpackage.CustomViewPager>태그 로 바꿉니다.

이 코드는이 블로그 게시물 에서 수정되었습니다 .


2
큰 해결책, 잘 작동합니다. 원숭이처럼 스 와이프를 중지하려면 @Override public void onPageScrollStateChanged (final int state) {switch (state) {case ViewPager.SCROLL_STATE_SETTLING : mPager.setPagingEnabled (false); 단절; case ViewPager.SCROLL_STATE_IDLE : mPager.setPagingEnabled (true); 단절; } // noop}
Informatic0re

13
추신 : XML에서 <com.android, support.v4.ViewPager 대신 <yourpkgname.CustomViewPager ...를 사용하십시오.
thecr0w

비슷한 솔루션을 추가하려면 "JazzyViewPager"라는 라이브러리를 사용하십시오 : github.com/jfeinstein10/JazzyViewPager , 그냥 setPagingEnabled (boolean)을 호출하십시오
android developer

오른쪽 스크롤 만 중지 할 수 있습니까? 난 단지 왼쪽으로 스크롤 할 수 있습니다
사이프 하메드

예를 들어 게임 컨트롤러 나 키보드를 사용할 때 페이지의 요소 (버튼 등)에 포커스를 두어 "스크롤"할 수 있습니다. 완전히 비활성화하는 방법? 인터셉트해야 할 또 다른 유형의 이벤트 인 것 같습니다.
David Ferrand

34

이것에 대한 쉬운 수정이 있습니다 :

viewpager 스크롤을 비활성화하려면 다음을 수행하십시오.

mViewPager.setOnTouchListener(new OnTouchListener() {

   public boolean onTouch(View arg0, MotionEvent arg1) {
      return true;
   }
}); 

그리고 다시 활성화하려면 다음을 수행하십시오.

mViewPager.setOnTouchListener(null);

그 트릭을 할 것입니다.


46
거의, 그러나 아주 아닙니다. 터치 다운은 여전히 ​​발생하므로 작은 스 와이프를 많이 사용하여 페이지를 이동할 수 있습니다.
Flynny75

@Akhil Sekharan이 답변을 사용할 때 Flynny가 직면하고있는 문제에 정확히 직면하고있었습니다. 그러나 불행히도 그 오류가 얼마나 갑자기 사라 졌는지 알지 못합니다. :))
좀비

당신은 여전히 공공 부울 onInterceptTouchEvent 이상 (MotionEvent 이벤트)에 그래서 slatons 대답에 따라 당신은 {타고 작은 와이프의 많은 작업을 수행 할 수 있습니다
라이언 Heitner

28

다음은 slayton의 대답에 대한 경량 변형입니다.

public class DeactivatableViewPager extends ViewPager {
    public DeactivatableViewPager(Context context) {
        super(context);
    }

    public DeactivatableViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return !isEnabled() || super.onTouchEvent(event);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        return isEnabled() && super.onInterceptTouchEvent(event);
    }
}

내 코드를 사용하면와 페이징을 비활성화 할 수 있습니다 setEnable().


재정의 onInterceptTouchEvent()하면 자식 뷰가 입력을받지 못하게됩니다. 대부분의 경우 이것은 의도 된 동작 이 아닙니다 .
Alex Semeniuk

19

간단한 해결책을 찾았습니다.

//disable swiping
mViewPager.beginFakeDrag();

//enable swiping
mViewPager.endFakeDrag();

이것이 당신이 사용한 모든 코드입니까? 이것은 나를 위해 작동하지 않습니다.
Jared Burrows

17
나를 위해 작동하지 않습니다. 여전히 작은 슬쩍을 많이 할 수 있습니다.
DYS

이 코드는 적절한 bcz가 아닙니다. 교수형보기처럼 매우 느리게 스크롤됩니다
Ghanshyam Nayma

이것은 운이 좋을 수도 있습니다. ViewPager로 업데이트하면이 해킹이 중단 될 수 있습니다.
포인터 널

아직 (드래그하지만 조금씩 있어요.
ekashking

14

이 문제를 해결하는 다른 방법을 제안합니다. 아이디어는 viewPager를 scrollView로 래핑 하므로이 scrollView를 스크롤 할 수 없을 때 viewPager도 스크롤 할 수 없습니다.

내 XML 레이아웃은 다음과 같습니다.

        <HorizontalScrollView
            android:id="@+id/horizontalScrollView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fillViewport="true" >

            <android.support.v4.view.ViewPager
                android:id="@+id/viewPager"
                android:layout_width="wrap_content"
                android:layout_height="match_parent" />

        </HorizontalScrollView>

코드가 필요하지 않습니다.

나를 위해 잘 작동합니다.


1
이 모든 답변 중, 나는 이것이 간단하고 잘 작동한다고 생각합니다!
SREE

당신이 다음 ViewPager의 단편 중 하나로지도가있을 때 OK ...하지만 ... 그것은 문제입니다
ekashking

4

스 와이프를 비활성화하려면

 mViewPager.beginFakeDrag();

스 와이프를 사용하려면

 mViewPager.endFakeDrag();

2
스크롤은 여전히 ​​가능하지만 더 이상 유창하지 않습니다. 이것은 기본적으로 문제를 해결하지 않고 품질을 악화시키는 것입니다.
Benjamin Basmaci

1
중복 답변
Ricardo A.

3

나를 위해 일한 가장 좋은 해결책은 다음과 같습니다.

public class DeactivatedViewPager extends ViewPager {

    public DeactivatedViewPager (Context context) {
        super(context);
    }

    public DeactivatedViewPager (Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean canScrollHorizontally(int direction) {
        return false;
    }
}

이 후 스크롤은 터치로 비활성화되며 여전히 setCurrentItem방법을 사용 하여 페이지를 변경할 수 있습니다 .


이유를 모르지만 간단하게 작동하지 않았습니다. 스크롤이 여전히 발생합니다.
Ricardo A.

1
canScrollHorizontally()방법은 현재 시나리오에는 영향을 미치지 않습니다. 스 와이프가 발생해도 호출되지 않습니다.
Alex Semeniuk

3

다음은 Kotlin과 androidX의 답변입니다.

import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import androidx.viewpager.widget.ViewPager

class DeactivatedViewPager @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null
) : ViewPager(context, attrs) {

    var isPagingEnabled = true

    override fun onTouchEvent(ev: MotionEvent?): Boolean {
        return isPagingEnabled && super.onTouchEvent(ev)
    }

    override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
        return isPagingEnabled && super.onInterceptTouchEvent(ev)
    }
}

2

이 방법에 대해 :
내가 사용 CustomViewPager
하고 다음, scrollTo 방법 오버라이드 (override)
작은 와이프를 많이 할 때 나는 움직임을 확인, 다른 페이지로 이동하지 않습니다.

public class CustomViewPager extends ViewPager {

    private boolean enabled;

    public CustomViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.enabled = true;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (this.enabled) {
            return super.onTouchEvent(event);
        }

        return false;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        if (this.enabled) {
            return super.onInterceptTouchEvent(event);
        }

        return false;
    }

    public void setPagingEnabled(boolean enabled) {
        this.enabled = enabled;
    } 

    @Override
    public void scrollTo(int x, int y) {
       if(enabled) {
          super.scrollTo(x, y);
       }
    }
}

나는 viewpager가 여전히 약간의 스 와이프를하고 있다는 문제가 있었지만 재정의 View.scrollTo(int x, int y)하면이 문제가 해결되었습니다. 감사합니다
Palm

경우에 따라 이상한 동작이 발생합니다. 빈칸에 가서 빈 페이지 '-'를 남겨 두는 것처럼
Ricardo A.

2

ViewPager 2 alpha 2를 사용하는 경우 아래 스 니펫이 작동합니다.

viewPager.isUserInputEnabled = false

사용자 입력을 비활성화하는 기능 (setUserInputEnabled, isUserInputEnabled)

viewpager2 1.0.0-alpha02의 더 많은 변경 사항은 이것을 참조하십시오

또한 일부 변경 사항이 최신 버전이었습니다 ViewPager 2 alpha 4

orientation 및 isUserScrollable 속성이 더 이상 SavedState의 일부가 아닙니다.

viewpager2 # 1.0.0-alpha04의 더 많은 변경 사항은 이것을 참조하십시오


1

androidx의 새로운 클래스 ViewPager2는 setUserInputEnabled (false) 메소드를 사용하여 스크롤을 비활성화 할 수 있습니다

private val pager: ViewPager2 by bindView(R.id.pager)

override fun onCreate(savedInstanceState: Bundle?) {
    pager.isUserInputEnabled = false
}

0

Slayton의 대답은 잘 작동합니다. 원숭이처럼 쓸어 넘기지 않으려면 OnPageChangeListener를 재정 의하여

@Override public void onPageScrollStateChanged(final int state) { 
        switch (state) { 
            case ViewPager.SCROLL_STATE_SETTLING: 
                mPager.setPagingEnabled(false); 
                break; 
            case ViewPager.SCROLL_STATE_IDLE: 
                mPager.setPagingEnabled(true); 
                break; 
        } 
    }

나란히 스 와이프 할 수 있습니다


1
setPagingEnabled (boolean value)와 같은 ViewPager의 메소드를 찾지 못했습니다
Rakesh Yadav

setPagingEnabled (boolean value)는 사용자가 작성해야하므로 대체 할 메소드가 없습니다.
Kharak

setPagingEnabled()방법이 무엇인지 확실 하지 않습니다. 완전한 코드를 포함하십시오.
Alex Semeniuk

0
import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.animation.DecelerateInterpolator;
import android.widget.Scroller;
import java.lang.reflect.Field;

public class NonSwipeableViewPager extends ViewPager {

public NonSwipeableViewPager(Context context) {
    super(context);
}

public NonSwipeableViewPager(Context context, AttributeSet attrs) {
    super(context, attrs);
}

@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
    // stop swipe 
    return false;
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    // stop switching pages
    return false;
}

private void setMyScroller() {
    try {
        Class<?> viewpager = ViewPager.class;
        Field scroller = viewpager.getDeclaredField("mScroller");
        scroller.setAccessible(true);
        scroller.set(this, new MyScroller(getContext()));
    } catch (Exception e) {
        e.printStackTrace();
    }
}

public class MyScroller extends Scroller {
    public MyScroller(Context context) {
        super(context, new DecelerateInterpolator());
    }

    @Override
    public void startScroll(int startX, int startY, int dx, int dy, int 
duration) {
        super.startScroll(startX, startY, dx, dy, 350 /*1 secs*/);
    }
}
}

그런 다음 Layout.XML 파일에서 --- com.android.support.V4.ViewPager --- 태그를 --- com.yourpackage.NonSwipeableViewPager --- 태그로 바꿉니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.