package com.melonsapp.messenger.ui.popupuser; import android.os.Handler; import android.view.View; import android.view.WindowManager; import android.view.animation.DecelerateInterpolator; import java.util.Timer; /** * Created by lidaqiang on 17/5/3. */ public class SmoothScroll { private Handler mHandler = new Handler(); SmoothScrollThread smoothScrollThread; public static int noData = 0; /** * @param v 需要操控的视图 * @param fromX 起始Y坐标 * @param toX 终止Y坐标 * @param fps 帧率 * @param durtion 动画完成时间(毫秒) * @desc 平滑滚动 */ public SmoothScroll(View v, WindowManager windowManager, WindowManager.LayoutParams windowParams, int fromX, int toX, int fps, long durtion) { this(v, windowManager, windowParams, fromX, toX, noData, noData, 60, durtion); } public SmoothScroll(View v, WindowManager windowManager, WindowManager.LayoutParams windowParams, int fromX, int toX, int fromY, int toY, long durtion) { this(v, windowManager, windowParams, fromX, toX, fromY, toY, 60, durtion); } public SmoothScroll(View v, WindowManager windowManager, WindowManager.LayoutParams windowParams, int fromX, int toX, int fromY, int toY, int fps, long durtion) { smoothScrollThread = new SmoothScrollThread(v, windowManager, windowParams, fromX, toX, fromY, toY, durtion, fps); } public void start() { if (smoothScrollThread == null) { return; } smoothScrollThread.run(); } public void stop() { if (smoothScrollThread == null) { return; } smoothScrollThread.stop(); } /** * @desc 平滑滚动线程,用于递归调用自己来实现某个视图的平滑滚动 */ class SmoothScrollThread implements Runnable { WindowManager mWindowManager; WindowManager.LayoutParams mWindowParams; //需要操控的视图 private View v = null; //原X坐标 private int fromX = noData; //目标X坐标 private int toX = noData; //原Y坐标 private int fromY = noData; //目标Y坐标 private int toY = noData; //动画执行时间(毫秒) private long durtion = 0; //帧率 private int fps = 60; //间隔时间(毫秒),间隔时间 = 1000 / 帧率 private int interval = 0; //启动时间,-1 表示尚未启动 private long startTime = -1; // /减速插值器 private DecelerateInterpolator decelerateInterpolator = null; private int mChangeState = 0; // 0 x,y都不变 1 x变 2 y变 3 x,y都变 /** * @desc 构造方法,做好第一次配置 */ public SmoothScrollThread(View v, WindowManager windowManager, WindowManager.LayoutParams windowParams, int fromX, int toX, int fromY, int toY, long durtion, int fps) { mWindowManager = windowManager; mWindowParams = windowParams; this.v = v; this.fromX = fromX; this.toX = toX; this.fromY = fromY; this.toY = toY; this.durtion = durtion; this.fps = fps; this.interval = 1000 / this.fps; decelerateInterpolator = new DecelerateInterpolator(); mChangeState = 0; if (fromX != toX && fromY == toY) { mChangeState = 1; } else if (fromX == toX && fromY != toY) { mChangeState = 2; } else if (fromX != toX && fromY != toY) { mChangeState = 3; } } @Override public void run() { if (mChangeState == 0) { return; } //先判断是否是第一次启动,是第一次启动就记录下启动的时间戳,该值仅此一次赋值 if (startTime == -1) { startTime = System.currentTimeMillis(); } //得到当前这个瞬间的时间戳 long currentTime = System.currentTimeMillis(); //放大倍数,为了扩大除法计算的浮点精度 int enlargement = 1000; //算出当前这个瞬间运行到整个动画时间的百分之多少 float rate = (currentTime - startTime) * enlargement / durtion; //这个比率不可能在 0 - 1 之间,放大了之后即是 0 - 1000 之间 rate = Math.min(rate, 1000); //将动画的进度通过插值器得出响应的比率,乘以起始与目标坐标得出当前这个瞬间,视图应该滚动的距离。 int currentX = fromX; if (mChangeState == 1 || mChangeState == 3) { int changeDistanceX = (int) ((fromX - toX) * decelerateInterpolator.getInterpolation(rate / enlargement)); currentX = fromX - changeDistanceX; } int currentY = fromY; if (mChangeState == 2 || mChangeState == 3) { int changeDistanceY = (int) ((fromY - toY) * decelerateInterpolator.getInterpolation(rate / enlargement)); currentY = fromY - changeDistanceY; } notifyViewLayout(currentX, currentY); if (currentX != toX || currentY != toY) { mHandler.postDelayed(this, this.interval); } else { return; } } private void notifyViewLayout(int currentX, int currentY) { // v.scrollTo(0, currentY); if (mWindowParams == null || mWindowParams == null || v == null) { return; } if (mChangeState == 1 || mChangeState == 3) { mWindowParams.x = currentX; } if (mChangeState == 2 || mChangeState == 3) { mWindowParams.y = currentY; } if (v.getParent() != null) { mWindowManager.updateViewLayout(v, mWindowParams); } } public void stop() { mHandler.removeCallbacks(this); } } }
本文转自 一点点征服 博客园博客,原文链接:http://www.cnblogs.com/ldq2016/p/6802517.html,如需转载请自行联系原作者