NavigationDrawer和ViewPager - 滑动问题

时间:2018-01-03 14:27:27

标签: android android-viewpager navigation-drawer drawerlayout

我有一个ViewPager,里面有3个片段。我已延长ViewPager并因特定于我的应用的原因而停用了其滑动功能。因此,为了在这些片段之间进行导航,我在活动中添加了TabLayout

在我的第二个片段(中间的那个片段)中,左边有一个DrawerLayout。 每当我在该片段中从左向右进行滑动动作时,即使我在屏幕中间滑动,也会显示DawerLayout。只有当我靠近屏幕的左边缘时才会发生这种情况。

我一直很难理解Android中的触摸和动作事件处理...是否有办法保持ViewPager(禁用滑动)并限制触摸事件DrawerLayout'侦听到'到屏幕的边缘(正如它应该的那样)?

如果我不修改ViewPager(即,如果我继续启用滑动),它也不起作用,因为从左边缘滑动将开始打开DrawerLayout,但是同时,将开始ViewPager的过渡。

我在一个小应用程序中重新创建了这个问题。

这是MyViewPager:

public class MyViewPager extends ViewPager {

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


    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        return false;
    }


    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return false;
    }
}

这是MainActivity:

public class MainActivity extends AppCompatActivity {

    Fragment Fragment1;
    Fragment Fragment2;
    Fragment Fragment3;
    MyViewPager viewPager;
    TabLayout tabLayout;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Fragment1 = new Fragment1();
        Fragment2 = new Fragment2();
        Fragment3 = new Fragment3();

        viewPager = findViewById(R.id.ViewPager);

        tabLayout = findViewById(R.id.TabLayout);

        viewPager.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()) {
            @Override
            public Fragment getItem(int position) {
                switch (position) {
                    case 0:
                        if (Fragment1 == null) {
                            Fragment1 = new Fragment1();
                        }
                        return Fragment1;
                    case 1:
                        if (Fragment2 == null) {
                            Fragment2 = new Fragment2();
                        }
                        return Fragment2;
                    case 2:
                        if (Fragment3 == null) {
                            Fragment3 = new Fragment3();
                        }
                        return Fragment3;
                    default:
                        return null;
                }
            }


            @Override
            public int getCount() {
                return 3;
            }


            @Override
            public CharSequence getPageTitle(int position) {
                switch (position) {
                    case 0:
                        return "frag1";
                    case 1:
                        return "frag2";
                    case 2:
                        return "frag3";
                    default:
                        return "0";
                }
            }
        });

        viewPager.setOffscreenPageLimit(2);
        viewPager.setCurrentItem(0);
        tabLayout.setupWithViewPager(viewPager);
    }
}

ActivityMain'布局:

<?xml version="1.0" encoding="utf-8"?>

<FrameLayout
    android:id="@+id/main_frame"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#4dea21">

    <com.example.android.navbarviewpager.MyViewPager
        android:id="@+id/ViewPager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center"
        android:background="#ea3ee2"/>

    <android.support.design.widget.TabLayout
        android:id="@+id/TabLayout"
        android:layout_width="wrap_content"
        android:layout_height="45dp"
        android:layout_gravity="left|bottom"
        app:tabMode="scrollable">

        <android.support.design.widget.TabItem
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="frag1"/>

        <android.support.design.widget.TabItem
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="frag2"/>

        <android.support.design.widget.TabItem
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="frag3"/>

    </android.support.design.widget.TabLayout>

</FrameLayout>

片段1:

public class Fragment1 extends Fragment {


    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        return inflater.inflate(R.layout.fragment1, container, false);

    }
}

Fragment2:

public class Fragment1 extends Fragment {


    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        return inflater.inflate(R.layout.fragment2, container, false);

    }
}

Fragment3:

public class Fragment1 extends Fragment {


    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        return inflater.inflate(R.layout.fragment3, container, false);

    }
}

片段TWO的布局(带有DrawerLayout的布局):

<?xml version="1.0" encoding="utf-8"?>

<android.support.v4.widget.DrawerLayout
    android:id="@+id/drawer_layout"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <FrameLayout
        android:id="@+id/frag_1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#a2a2ee"
        android:padding="0dp">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center"
            android:text="fragmento DOIS"/>

    </FrameLayout>

    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="left|center_vertical"
        android:background="#b9b9b9"
        android:clickable="true"
        android:orientation="vertical"
        android:paddingBottom="20dp"
        android:paddingTop="20dp">
        <TextView
            android:id="@+id/notified_nav"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="TTTTT"/>
        <TextView
            android:id="@+id/overdue_nav"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="XXXXX"/>
    </LinearLayout>
</android.support.v4.widget.DrawerLayout>

其他片段的布局:

Fragment ONE

<?xml version="1.0" encoding="utf-8"?>

<FrameLayout
    android:id="@+id/frag_1"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#eea2a2"
    android:padding="0dp">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="fragmento UM"
        android:gravity="center"/>

</FrameLayout>

片段三

<?xml version="1.0" encoding="utf-8"?>

<FrameLayout
    android:id="@+id/frag_1"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#abeea2"
    android:padding="0dp">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="fragmento TRÊS"
        android:gravity="center"/>

</FrameLayout>

2 个答案:

答案 0 :(得分:1)

虽然我不认为水平ViewPager和水平DrawerLayout可能在彼此的顶部,但你可以将其中一个旋转90度并使其垂直滑动view(在DrawerLayout的情况下很容易,如果你使用库 - 在github上有一个数字,在ViewPager的情况下也很容易。)

关于你问题的核心内容:可以将DrawerLayout的敏感区域限制在它滑动的边缘。为此,您需要覆盖DrawerLayout并在DrawerLayout中使用/layout/fragment2.xml代替public class MyDrawerLayout extends DrawerLayout { Context context; public MyDrawerLayout(Context context) { this(context, null); } public MyDrawerLayout(Context context, AttributeSet attrs) { this(context, attrs, 0); } public MyDrawerLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); this.context = context; } @Override public boolean onInterceptTouchEvent(MotionEvent motionEvent) { // if the drawer is open already, pass motionEvent upwards if (this.isDrawerOpen(Gravity.START)) { return super.onInterceptTouchEvent(motionEvent); } // sensitive area is set to 1/4 of the drawer's full width // adopt to your needs int sensitiveWidth = ((Activity) context).findViewById(R.id.drawer_layout).getWidth() / 4; // if the drawer is not (fully) open AND // motionEvent.getX() is close to the left edge, // fully open the drawer and pass motionEvent upwards if (motionEvent.getX() < sensitiveWidth) { this.openDrawer(Gravity.START); return super.onInterceptTouchEvent(motionEvent); } // otherwise eat motionEvent return false; } }

这是代码:

onInterceptTouchEvent

两个注释:

  1. 抽屉打开后,您可能希望在任何交互后关闭它,即使它位于“敏感区域”之外。这就是MotionEvent中第一个 if -clause的用途。

  2. 当抽屉未完全打开时,在“敏感区域”之外的DrawerLayout上执行吞下 {{1}}。因此,“甩”手势的空间很窄。为了方便打开抽屉,以编程方式打开它是我在这里建议的选项。如果您的应用不依赖于半开/关抽屉,这在可用性方面似乎是一个很好的解决方案。

答案 1 :(得分:0)

Here我解释了如何使用TabLayout向所有方向移动,这可以提供帮助。

对于您的情况,您可以使用手势检测器

gestureDetectorCompat = new GestureDetectorCompat(this, new GestureDetector.SimpleOnGestureListener() {
    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
        float angle = (float) Math.toDegrees(Math.atan2(e1.getY() - e2.getY(), e2.getX() - e1.getX()));

        if (angle > -45 && angle <= 45) {
            if(goRight != 5) mainContainer.setCurrentItem(goRight);
            return true;
        }

        if (angle >= 135 && angle < 180 || angle < -135 && angle > -180) {
            if(goLeft != 5) mainContainer.setCurrentItem(goLeft);
            return true;
        }

        if (angle < -45 && angle >= -135) {
            if(goUp != 5)mainContainer.setCurrentItem(goUp);
            return true;
        }

        if (angle > 45 && angle <= 135) {
            if(goDown != 5)mainContainer.setCurrentItem(goDown);
            return true;
        }

        return false;
    }


});

这个

someView.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View view, MotionEvent motionEvent) {
            gestureDetectorCompat.onTouchEvent(motionEvent);
            return false;
        }
    });

重要的一步是将.xml中的“ someView ”设置为您想要移动的区域。您无需观看整个屏幕

希望有所帮助