Android ViewPager喜欢instagram照片活动

时间:2017-11-24 11:10:58

标签: android android-viewpager

我需要在“照片和视频”标签中使用相同的片段,并且仍然有三个标签。 我在viewpager中有两个片段,在tablayout中有3个制表符。我希望实现viewpager改变效果,如instagram。我做了什么: 我在下面创建了自定义viewpager:

public class SwipableViewPager extends ViewPager {
    private float downX;
    private float downY;
    private float mStartDragX;
    private float upX;
    private float upY;
    private boolean dragDisabled;

    private SwipeListener mListener;

    public void setSwipeListener(SwipeListener listener) {
        mListener = listener;
    }

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

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        float x = ev.getX();
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                downX = ev.getX();
                downY = ev.getY();
                mStartDragX = x;
                break;
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
                upX = ev.getX();
                upY = ev.getY();

                float deltaX = downX - upX;
                if(deltaX>-getWidth() && deltaX< -getWidth()/4 && getCurrentItem() == getAdapter().getCount() - 1){
                    mListener.setPageAndEnableDrag();
                }
                break;
            case MotionEvent.ACTION_MOVE:
                if (mStartDragX - 30 > x && getCurrentItem() == getAdapter().getCount() - 1) {
                    mListener.onSwipeOutAtEnd();
                }
                break;
        }
        if(dragDisabled) {
            return false;
        }
        else{
            return super.onInterceptTouchEvent(ev);
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        if(dragDisabled) return false;
        return super.onTouchEvent(ev);
    }

    public void disableDrag(boolean disabled) {
        dragDisabled = disabled;
    }



    public interface SwipeListener {
        void setPageAndEnableDrag();
        void onSwipeOutAtEnd();
    }
}

当当前项目是适配器中的最后一项时,它将通知向右滑动(这需要您在照片选项卡中并且想要通过滑动进入视频选项卡)。 在活动中,我设置了这样的viewpager:

private void setupViewPager() {
        ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
        adapter.addFragment(GalleryFragment.newInstance(), getResources().getString(R.string.gallery_toolbar_title));
        TakePhotoFragment fragment = new TakePhotoFragment();
        adapter.addFragment(fragment, getResources().getString(R.string.photo));
        viewPager.setAdapter(adapter);
        viewPager.setSwipeListener(this);
        tabLayout.setupWithViewPager(viewPager);
        tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {

                switch (tab.getPosition()){
                    case 1:  //selected photo tab
                        viewPager.setCurrentItem(1);
                        toolbar.setTitle(R.string.photo);
                        viewPager.disableDrag(false);    //switch on default swipe
                        break;
                    case 2: // selected video tab
                        toolbar.setTitle(R.string.video);
                        viewPager.disableDrag(true);    // switch off default swipe
                        break;
                    default: // selected gallery tab
                        viewPager.setCurrentItem(tab.getPosition());
                        toolbar.setTitle(R.string.gallery_toolbar_title);
                        viewPager.disableDrag(false);    //switch on default swipe
                        break;
                }
            }

            @Override
            public void onTabUnselected(TabLayout.Tab tab) {

            }

            @Override
            public void onTabReselected(TabLayout.Tab tab) {

            }
        });
    }

    @Override
    public void setPageAndEnableDrag() {
        tabLayout.getTabAt(1).select();
        viewPager.disableDrag(false);
    }
    public void setPagerEnabledDrag(boolean enabled) {
        viewPager.disableDrag(!enabled);
    }
    @Override
    public void onSwipeOutAtEnd() {
        viewPager.disableDrag(true);
        tabLayout.getTabAt(2).select();
    }

一切都还可以,但是当您在图库标签中并且想要转到视频标签时,您无法通过点击视频标签来完成。当您单击视频选项卡时,它会生成活动的照片选项卡,然后如果您再单击视频选项卡,它将激活视频选项卡。也可以通过滑动工作来改变照片选项卡和视频选项卡。 我需要在点击视频标签时实现它必须转到视频标签而不是像现在这样的照片标签。

enter image description here

另见视频: https://youtu.be/tbT7mzkmydQ

  1. 为什么我只有两个片段,但有三个标签? 因为Camera对象只能创建一个Activity,所以我必须为照片和视频标签使用一个片段。
  2. 为什么我要处理无法阻止? 当用户进入第三个选项卡时,我必须禁用viewpager的默认滑动效果(如果我不这样做,当从第三个浏览器向第二个viewpager滑动时将转到第一个选项卡)
  3. 我不想要一个无限的观看者。
  4. 我不想简单地从右(第三)片段到左(第一)片段。
  5. 请看视频: Video of my activity in action

1 个答案:

答案 0 :(得分:4)

据我了解,您需要在“照片和视频”标签中使用相同的片段,并且仍然有三个标签。

从照片滑动到视频标签 - 在第三个标签中添加空白片段,在寻呼机适配器中将其宽度保持为零。从照片滑动到视频选项卡时,照片片段将继续显示。

private void setupViewPager(){
        SectionsPagerAdapter adapter =  new SectionsPagerAdapter(getSupportFragmentManager());

        adapter.addFragment(new GalleryFragment());
        adapter.addFragment(new PhotoFragment());
        adapter.addFragment(new Fragment()); //blank fragment

        mViewPager = (ViewPager) findViewById(R.id.viewpager_container);
        mViewPager.setAdapter(adapter);

        mTabLayout = (TabLayout) findViewById(R.id.tabsBottom);
        mTabLayout.setupWithViewPager(mViewPager);

        mTabLayout.getTabAt(0).setText(getString(R.string.gallery));
        mTabLayout.getTabAt(1).setText(getString(R.string.photo));
        mTabLayout.getTabAt(2).setText(getString(R.string.video));
        ...
    }

将空白标签的宽度设置为0

public class SectionsPagerAdapter extends FragmentPagerAdapter {
        ...
        @Override
        public float getPageWidth(int position) {
            if (position == 2) {
                return 0;
            }
            return super.getPageWidth(position);
        }
    }

从视频向照片选项卡滑动 - 增加“视频”标签的投射距离,以便在照片标签处停止滑动。将fling距离重置为其他选项卡的默认值。您需要Java Reflection API才能使fling距离字段可访问,因为它是ViewPager.class中的私有字段

final float density = getResources().getDisplayMetrics().density;
mTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
    @Override
    public void onTabSelected(TabLayout.Tab tab) {
        Field mFlingDistance;
        try {
            mFlingDistance = ViewPager.class.getDeclaredField("mFlingDistance");
            mFlingDistance.setAccessible(true);
            switch (tab.getPosition()){
                case 2: mFlingDistance.set(mViewPager, (int)(200 * density));
                        break;
                default: mFlingDistance.set(mViewPager, (int)(25 * density));
                         break;
            }
         } catch (NoSuchFieldException e) {
             e.printStackTrace();
         } catch (IllegalAccessException e) {
             e.printStackTrace();
         }
     }

     @Override
     public void onTabUnselected(TabLayout.Tab tab) {}

     @Override
     public void onTabReselected(TabLayout.Tab tab) {}
 });

视频链接:https://imgur.com/a/wA3e0

这是一个快速而又肮脏的解决方案。您可能需要对其进行微调。