photoView中的fling事件分析

上一篇大概介绍了photoView的touch事件的传递,写的惨不忍睹,也比较简单,想要理解还是得去看源码;这一篇主要介绍下其中对fling事件的分析,顾名思义,就是当图片放大之后,单手快速一滑动,图片会有个惯性移动,而在photoView中,就是在onFling方法中处理的。

源码长这样:
 @Override
    public void onFling(float startX, float startY,float velocityX,float velocityY) {
        ImageView imageView = getImageView();
        mCurrentFlingRunnable = new FlingRunnable(imageView.getContext());
                mCurrentFlingRunnable.fling(getImageViewWidth(imageView),getImageViewHeight(imageView), (int) velocityX, (int) velocityY);

     imageView.post(mCurrentFlingRunnable);
    }

我们可以看到这里有个FlingRunnable这个东西,目测就是执行那个惯性运动的动画。详细一看

public FlingRunnable(Context context) {
            mScroller = ScrollerProxy.getScroller(context);
        }

构造里面有个scoller,应该就是靠他执行滚动的事件,首先执行了该runnable里的fling方法:

public void fling(int viewWidth, int viewHeight, int velocityX,
                          int velocityY) {
            final RectF rect = getDisplayRect();
            if (null == rect) {
                return;
            }
            final int startX = Math.round(-rect.left);
            final int minX, maxX, minY, maxY;

            if (viewWidth < rect.width()) {
                minX = 0;
                maxX = Math.round(rect.width() - viewWidth);
            } else {
                minX = maxX = startX;
            }

            final int startY = Math.round(-rect.top);
            if (viewHeight < rect.height()) {
                minY = 0;
                maxY = Math.round(rect.height() - viewHeight);
            } else {
                minY = maxY = startY;
            }

            mCurrentX = startX;
            mCurrentY = startY;

            if (startX != maxX || startY != maxY) {
                mScroller.fling(startX, startY, velocityX, velocityY, minX,
                        maxX, minY, maxY, 0, 0);
            }
        }

这里面处理了我们可以fling的范围,设置在我们scroller里面,比如他的x范围,通过放大后的RectF 和实际imageview的大小算出范围。

public void run() {
            if (mScroller.isFinished()) {
                return; // remaining post that should not be handled
            }

            ImageView imageView = getImageView();
            if (null != imageView && mScroller.computeScrollOffset()) {

                final int newX = mScroller.getCurrX();
                final int newY = mScroller.getCurrY();

                if (DEBUG) {
                    LogManager.getLogger().d(
                            LOG_TAG,
                            "fling run(). CurrentX:" + mCurrentX + " CurrentY:"
                                    + mCurrentY + " NewX:" + newX + " NewY:"
                                    + newY);
                }

                mSuppMatrix.postTranslate(mCurrentX - newX, mCurrentY - newY);
                setImageViewMatrix(getDrawMatrix());

                mCurrentX = newX;
                mCurrentY = newY;

                // Post On animation
                Compat.postOnAnimation(imageView, this);
            }

最后执行runnable这个线程,这里用到了scroller里的知识,不会的同学自行百度;通过:

mSuppMatrix.postTranslate(mCurrentX - newX, mCurrentY - newY);
                setImageViewMatrix(getDrawMatrix());

这俩句不断设置新的matrix,声明重绘,我们还看到这里有个

Compat.postOnAnimation(imageView, this);

这里其实是个递归调用,不断调用该runnable,达到连续的绘制过程,代码如下:

public class Compat {

    private static final int SIXTY_FPS_INTERVAL = 1000 / 60;

    public static void postOnAnimation(View view, Runnable runnable) {
        if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN) {
            postOnAnimationJellyBean(view, runnable);
        } else {
            view.postDelayed(runnable, SIXTY_FPS_INTERVAL);
        }
    }

    @TargetApi(16)
    private static void postOnAnimationJellyBean(View view, Runnable runnable) {
        view.postOnAnimation(runnable);
    }

最后会到view.postOnAnimation(runnable)这句,又重新调用了我们的runnable,知道滚动完毕。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值