ViewPager的fakeDragBy()或setCurrentItem()不能捕捉到当前项目 [英] ViewPager's fakeDragBy() or setCurrentItem() doesn't snap to current item

查看:207
本文介绍了ViewPager的fakeDragBy()或setCurrentItem()不能捕捉到当前项目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

已解决.请参阅标记为正确答案的答案以及我的评论.可以在必要时发布示例代码

Resolved. See answer marked as correct along with my comments. Can post example code if necessary

我正在使用 VelocityViewPager 来实现转移"行为.有一种已知的行为,即如果将页面拖动一定量,页面将无法对齐.我正在努力解决这个问题,但收效甚微...

I'm using the VelocityViewPager to implement a "fling" behavior. There is a known behavior with it where the page doesn't snap if you drag it by a certain amount. I'm trying to get around it with little success...

尝试1

通过使用setCurrentItem,我可以使快照操作正常工作.需要注意的是,仅当我在当前页面之前或之后的项目上调用该函数时,该快照才会捕捉到,例如setCurrentItem(getCurrentItem()+1)

I can get the snap action to work correctly by using setCurrentItem. The caveat is that it only snaps if I call the function on an item before or after the current page, for example setCurrentItem(getCurrentItem()+1)

因此,此解决方案有效,但是如果我必须将当前项目设置得比他们期望的要多,则会给用户带来糟糕的用户体验.

So this solution works, but it gives the user a bad user experience if I have to set the current item further than they expect it to.

有人对我如何称呼setCurrentItem(getCurrentItem())并使它实际上具有动画/滚动/捕捉效果有任何建议吗? .消息来源暗示应该这样做. r7代码似乎总是调用滚动功能.

Does anyone have any advice on how I can call setCurrentItem(getCurrentItem()) and have it actually animate/scroll/snap? The source implies that it should. The r7 code seems to always call the scroll function.

尝试2

作为另一个测试,我进行了许多fakeDragBy(1)调用来拖动ViewPager,以为它会在达到一定阈值后迅速捕捉,但事实并非如此. 是什么导致ViewPager无法捕捉?

As another test, I did many fakeDragBy(1) calls to drag the ViewPager thinking that it would snap after it reached a certain threshold, but that wasn't the case. What's preventing the ViewPager from snapping?

如果有兴趣,下面是重现此代码的代码.我使用相同的 VelocityViewPager 代码进行了以下更改

Below is code to reproduce this, if you're interested. I used the same VelocityViewPager code with the following changes

VelocityViewPager.java

public class VelocityViewPager extends ViewPager implements GestureDetector.OnGestureListener {
...
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // give all the events to the gesture detector. I'm returning true here so the viewpager doesn't
        // get any events at all, I'm sure you could adjust this to make that not true.
        mGestureDetector.onTouchEvent(event);
        if (event.getAction() == MotionEvent.ACTION_UP) {
            setCurrentItem(getCurrentItem(), true);
            Log.d("VelocityViewPager", "Setting to item " + getCurrentItem());
        }
        return true;
    }
....
}

MainActivity.java

package com.example.velocityviewpager;

import android.graphics.Color;
import android.os.Bundle;
import android.app.Activity;
import android.support.v4.view.PagerAdapter;
import android.view.Gravity;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        VelocityViewPager pager = (VelocityViewPager)findViewById(R.id.view);
        PagerAdapter adapter = new PagerAdapter() {
            @Override
            public int getCount() {
                return 20;
            }

            @Override
            public Object instantiateItem(ViewGroup container, int position) {
                TextView view = new TextView(MainActivity.this);
                view.setText("Item "+position);
                view.setGravity(Gravity.CENTER);
                view.setBackgroundColor(Color.argb(255, position * 10, position * 10, position * 10));
                view.setTextColor(Color.argb(255, 200, 200, 200));

                container.addView(view);
                return view;
            }

            @Override
            public void destroyItem(ViewGroup container, int position, Object object) {
                container.removeView((View)object);
            }

            @Override
            public boolean isViewFromObject(View view, Object o) {
                return (view == o);
            }
        };
        pager.setAdapter(adapter);
        adapter.notifyDataSetChanged();

        pager.setOffscreenPageLimit(3);
        pager.setCurrentItem(0, true);
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

}

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context=".MainActivity">

    <view
            android:layout_width="300dip"
            android:layout_height="300dip"
            class="com.example.velocityviewpager.VelocityViewPager"
            android:id="@+id/view"
            android:layout_alignParentTop="true"
            android:layout_alignParentLeft="true"
            android:layout_alignParentRight="true"/>

</RelativeLayout>

推荐答案

我找到了一种解决方法.我跟踪以前做过的动作,并且当MotionEvent.ACTION_UP发生时,我会触发新的猛冲.我不确定,如果这种方式在逻辑上是正确的(这是正确的方向吗?对于新的猛击来说,这是否是一个好的速度?),但是我对其进行了测试,并且它的工作原理是:

I have found a workaround. I track what movement was done previously, and when a MotionEvent.ACTION_UP occurs I trigger a new fling. I am not sure, if it's logically correct this way (is this the good direction? and is this a good velocity for a new fling?), but I tested it, and it works:

private boolean isLeftDirection = false;

@Override
public boolean onTouchEvent(MotionEvent event) {
    // give all the events to the gesture detector. I'm returning true here
    // so the viewpager doesn't
    // get any events at all, I'm sure you could adjust this to make that
    // not true.

    if (event.getAction() == MotionEvent.ACTION_UP) {
        int id = getCurrentItem();
        setCurrentItem(id, true);
        if (isLeftDirection){
            mFlingRunnable.startUsingVelocity((int) 1);
        } else {
            mFlingRunnable.startUsingVelocity((int) -1);
        }
    }
    mGestureDetector.onTouchEvent(event);
    return true;
}

@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distX,
        float distY) {
    trackMotion(-distX);
    if (distX > 0){ 
        isLeftDirection = true;}
    else{
        isLeftDirection = false;
    }
    return false;
}

这篇关于ViewPager的fakeDragBy()或setCurrentItem()不能捕捉到当前项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆