正文
android开发教程之使用线程实现视图平滑滚动示例 改
小程序:扫一扫查出行
【扫一扫了解最新限行尾号】
复制小程序
【扫一扫了解最新限行尾号】
复制小程序
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 = ; /**
* @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, , 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, , 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 = ;
//帧率
private int fps = ;
//间隔时间(毫秒),间隔时间 = 1000 / 帧率
private int interval = ;
//启动时间,-1 表示尚未启动
private long startTime = -;
// /减速插值器
private DecelerateInterpolator decelerateInterpolator = null; private int mChangeState = ; // 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 = / this.fps;
decelerateInterpolator = new DecelerateInterpolator();
mChangeState = ; if (fromX != toX && fromY == toY) {
mChangeState = ;
} else if (fromX == toX && fromY != toY) {
mChangeState = ;
} else if (fromX != toX && fromY != toY) {
mChangeState = ;
}
} @Override
public void run() { if (mChangeState == ) {
return;
} //先判断是否是第一次启动,是第一次启动就记录下启动的时间戳,该值仅此一次赋值
if (startTime == -) {
startTime = System.currentTimeMillis();
}
//得到当前这个瞬间的时间戳
long currentTime = System.currentTimeMillis();
//放大倍数,为了扩大除法计算的浮点精度
int enlargement = ;
//算出当前这个瞬间运行到整个动画时间的百分之多少
float rate = (currentTime - startTime) * enlargement / durtion;
//这个比率不可能在 0 - 1 之间,放大了之后即是 0 - 1000 之间
rate = Math.min(rate, );
//将动画的进度通过插值器得出响应的比率,乘以起始与目标坐标得出当前这个瞬间,视图应该滚动的距离。 int currentX = fromX;
if (mChangeState == || mChangeState == ) {
int changeDistanceX = (int) ((fromX - toX) * decelerateInterpolator.getInterpolation(rate / enlargement));
currentX = fromX - changeDistanceX;
} int currentY = fromY;
if (mChangeState == || mChangeState == ) {
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 == || mChangeState == ) {
mWindowParams.x = currentX;
} if (mChangeState == || mChangeState == ) {
mWindowParams.y = currentY;
} if (v.getParent() != null) {
mWindowManager.updateViewLayout(v, mWindowParams);
} } public void stop() {
mHandler.removeCallbacks(this);
}
} }