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);
            }
        }
    
    
    }
  • 相关阅读:
    【LeetCode】在排序数组中查找元素的第一个和最后一个位置
    【LeetCode】搜索旋转排序数组
    【LeetCode】组合总和
    【LeetCode】电话号码的字母组合
    【LeetCode】对称二叉树
    【LeetCode】验证二叉搜索树
    【LeetCode】分发糖果
    Go学习笔记
    mybatis
    redis
  • 原文地址:https://www.cnblogs.com/ldq2016/p/6802517.html
Copyright © 2011-2022 走看看