zoukankan      html  css  js  c++  java
  • 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 = 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);
            }
        }
    
    
    }
  • 相关阅读:
    区别@ControllerAdvice 和@RestControllerAdvice
    Cannot determine embedded database driver class for database type NONE
    使用HttpClient 发送 GET、POST、PUT、Delete请求及文件上传
    Markdown语法笔记
    Property 'sqlSessionFactory' or 'sqlSessionTemplate' are required
    Mysql 查看连接数,状态 最大并发数(赞)
    OncePerRequestFilter的作用
    java连接MySql数据库 zeroDateTimeBehavior
    Intellij IDEA 安装lombok及使用详解
    ps -ef |grep xxx 输出的具体含义
  • 原文地址:https://www.cnblogs.com/ldq2016/p/6802517.html
Copyright © 2011-2022 走看看