web-dev-qa-db-ja.com

ViewPagerを一方向のスワイプから無効にする方法

ユーザーがViewPagerを右から左にのみスワイプできるようにします。そのため、ページを渡すと、そのページに戻ることはできません。これをどのように行うことができますか?

私は試しました this 解決策:

public class CustomViewPager extends ViewPager {

float lastX = 0;

boolean lockScroll = false;

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

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

@Override
public boolean onTouchEvent(MotionEvent ev) {

    switch (ev.getAction()) {
    case MotionEvent.ACTION_DOWN:
        lastX = ev.getX();
        lockScroll = false;
        return super.onTouchEvent(ev);
    case MotionEvent.ACTION_MOVE:

        if (lastX > ev.getX()) {
            lockScroll = false;
        } else {
            lockScroll = true;
        }

        lastX = ev.getX();
        break;
    }

    lastX = ev.getX();

    if(lockScroll) {
        return false;
    } else {
        return super.onTouchEvent(ev);
    }
}
}

しかし、それでも私は他の方向にうまくスワイプできません。

29
Emil Adz

逃したイベントがもう1つあります:onInterceptTouchEventです。 onTouchEventと同じロジックが含まれている必要があります。

私の完全なソリューションは this answerに基づいています。必要なときにいつでもどの方向のページングを有効/無効にすることができます。

1。列挙型を作成

 public enum SwipeDirection {
    all, left, right, none ;
}

2.ViewPagerの拡張

public class CustomViewPager extends ViewPager {

    private float initialXValue;
    private SwipeDirection direction;

    public CustomViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.direction = SwipeDirection.all;
    }

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

        return false;
    }

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

        return false;
    }

    private boolean IsSwipeAllowed(MotionEvent event) {
        if(this.direction == SwipeDirection.all) return true;

        if(direction == SwipeDirection.none )//disable any swipe
            return false;

        if(event.getAction()==MotionEvent.ACTION_DOWN) {
            initialXValue = event.getX();
            return true;
        }

        if(event.getAction()==MotionEvent.ACTION_MOVE) {
            try {
                float diffX = event.getX() - initialXValue;
                if (diffX > 0 && direction == SwipeDirection.right ) {
                    // swipe from left to right detected
                    return false;
                }else if (diffX < 0 && direction == SwipeDirection.left ) {
                    // swipe from right to left detected
                    return false;
                }
            } catch (Exception exception) {
                exception.printStackTrace();
            }
        }

        return true;
    }

    public void setAllowedSwipeDirection(SwipeDirection direction) {
        this.direction = direction;
    }

3.viewPagerをレイアウトで使用する

 <package_name.customviewpager 
     Android:id="@+id/customViewPager" 
     Android:layout_height="match_parent" 
     Android:layout_width="match_parent" />

4。コードで任意のスワイプ方向を有効にします。デフォルトはすべて(左右)です。

mViewPager.setAllowedSwipeDirection(SwipeDirection.right);
70
andre719mv
package com.contacts_app.jamison.contacts__proprivacy4;

import Android.content.Context;
import Android.content.res.Resources;
import Android.support.v4.view.ViewPager;
import Android.util.AttributeSet;
import Android.util.Log;
import Android.view.MotionEvent;

public class ViewPager_Settings extends ViewPager
{
private final String TAG = ViewPager_Settings.class.getSimpleName();
public float startX;

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

 ////////////////////////////////////////////////////////////////////////////////////////////////
public static int dpTOpx(double dp)
{
    return (int) (dp * Resources.getSystem().getDisplayMetrics().density);
}
public static int pxTOdp(double px)
{
    return (int) (px / Resources.getSystem().getDisplayMetrics().density);
}
////////////////////////////////////////////////////////////////////////////////////////////////

/*****DispatchTouchEvent for the View Pager to intercept and block swipes Right*****/
@Override
public boolean dispatchTouchEvent(MotionEvent ev)
{
    final int actionMasked = ev.getActionMasked() & MotionEvent.ACTION_MASK;
    //int movement_limit = pxTOdp(50);
    switch (actionMasked)
    {
        case (MotionEvent.ACTION_DOWN):
        {
            startX = ev.getX();
            Log.i(TAG, "startX: " + startX);

            /*Should always be this below*/
            return super.dispatchTouchEvent(ev);
        }
        case (MotionEvent.ACTION_MOVE):
        {
            Log.i(TAG, "ev.getX() - startX:" + (ev.getX() - startX));

            /*Switching directional changes would be a matter of flipping the  "<" sign in the line below.*/
            if (ev.getX() - startX > 0)
            {
                /*The result is that the ViewPager will not swipe from left*/
                ev.setAction(MotionEvent.ACTION_CANCEL);;
            }

            /*Should always be this below*/
            super.dispatchTouchEvent(ev);
        }
        /**The ACTION_UP case statement is only needed if you don't want to pass down the touch event 
        * to buttons that may receive the click after the swipe is blocked.*/
        /*case (MotionEvent.ACTION_UP):
        {
            //Log.i(TAG, "movement_limit: " + movement_limit);

            //(-50) may need to be changed to something more broader in scope to accompany all screen densities
            if ( (ev.getX() - startX) < (-50) )
            {
                ev.setAction(MotionEvent.ACTION_CANCEL);
            }

            //Should always be this below
            super.dispatchTouchEvent(ev);
        }*/
    }
    /*Should always be this below*/
    return super.dispatchTouchEvent(ev);
}
 ////////////////////////////////////////////////////////////////////////////////////////////////

}/*****END OF FILE*****/

アプリのパッケージ名を入れるために、上部の行を変更することを忘れないでください。また、すべてではないにしても、ほとんどのコメントは、物事をいじりたいと判断した場合にコードが何をしているのかについての洞察を与えます。

1
JamisonMan111

このようにアダプターを定義します

public class MyFragmentStatePagerAdapter extends FragmentStatePagerAdapter {

    private final int totalPages = 10;
    private int currentPage = 0;

    public MyFragmentStatePagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int position) {
        // Use whatever logic you want here to
        // to select a fragment based on
        // currentPage instead of position

        if (currentPage % 2 == 0) {
            return new Fragment1();
        } else {
            return new Fragment2();
        }
    }

    @Override
    public int getCount() {
        return currentPage == totalPages ? 1 : 2;
    }

    @Override
    public int getItemPosition(Object object){
        return PagerAdapter.POSITION_NONE;
    }

    public void nextPage() {
        currentPage++;
        notifyDataSetChanged();
    }
}

ビューページャーを使用しているフラグメントで、これを行います

@Override
public void onPageSelected(int arg0) {
    if (arg0 > 0) {
        pagerAdapter.nextPage();
        pager.setCurrentItem(0, false);
    }
}
0
mpkuth

追加してみてください(onTouchEventと同じロジック)

@Override
public boolean onInterceptTouchEvent(MotionEvent arg0) {
    // allow/ not allow swiping to switch between pages
    return !lockScroll ;
}
0
NickF