zoukankan      html  css  js  c++  java
  • Android -- 真正的 高仿微信 打开网页的进度条效果

    (本博客为原创,http://www.cnblogs.com/linguanh/)

    目录:

      一,为什么说是真正的高仿?

      二,为什么要搞缓慢效果?

      三,我的实现思路

      四,代码,内含注释

      五,使用方法与截图

      六,完整项目

    一,为什么说是真正的高仿?

      阐述这个问题前,先说下之前网上的,各位可以复制这段字,去百度一下  "仿微信打开网页的进度条效果" ,你会看到有很多类似的文章,不过他们有个共同点,就是实现方法都是一样的,而且,都忽略了微信加载网页时,进度条的缓慢动画效果,它不是生硬地一滑而过,而是用户体验很好,有个速度的变化,由慢到快的效果,语言难于描述,相信各位都有下载微信,可以随便打开个公众号的文章看看效果。

      好了,上面说到,之前网上的方法都是都忽略了微信加载网页时,进度条的缓慢动画效果,实现代码也是千篇一律,如下:

    /** 先实例化个进度条 */
    ProgressBar mProgressBar = (ProgressBar) findViewById(R.id.ProgressBar);
    
    /** 再实例化个 webView */
    WebView webView = (WebView) findViewById(R.id.webview);
    
    /** 然后就直接在 webClient 回调函数里面set 进度,这样的做法是生硬的效果 */
    webView.setWebChromeClient(new WebChromeClient(){
    
         @Override
         public void onProgressChanged(WebView view, int newProgress) {
                super.onProgressChanged(view, newProgress);
                mProgressBar.setProgress(newProgress);
          }
    
    });
    
    /** 其他是颜色样式等,不是重点 */
    .....

      我以为是 ProgressBar 控件可能自身提供了动画的 API,可惜,没有,故自己动手写了这个,你如果找到了,告诉下我。

    二,为什么要搞缓慢效果?

      对,为什么要这么麻烦,你如果要搞个网页加载进度条,上面的代码不过 10 行,妥妥地实现了。因为用户体验,我不是产品经理,我是个程序员,而且这个效果也不是有谁叫我这样去做的,我就是看着别扭,微信的成功,我相信不仅仅是个朋友圈那么简单!

      程序员应该具备注重用户体验的想法。

    三,我的实现思路

      方法很多,这话我说在前面,我的这种肯定不是最好的,但不失一用或改进。

      主要是通过改变 view 的 LayoutParam 来实现有不同速度的移动效果,在每一次的进度段,例如第一次0~24,第二次24~56,这就是两个进度段,这两个进度段,具有不同的速度,这个需要计算出来,先根据手机屏幕宽度和 0~100 的进度数值来等比计算出实际的宽度,再计算出移动的速度,计算出来每个进度段的数据后,讲它们放进一个列表容器里面,然后通过一个 handler 来循环提取同期数据,不断地发消息,不停地 setLayoutParam。在达到 100 后,就证明加载完毕。

      在这个过程需要处理计算的误差,例如第一个加载 20,第二次24,24-20 = 4,4/100,程序里面是 0 ,如果计算速度的话,就会差生0,所以要稍微加个 if 判断。

    四,代码,内涵注释

      核心类:

    package com.slowlyprogressbar;
    
    import android.os.Handler;
    import android.os.Message;
    import android.util.Log;
    import android.view.View;
    import android.widget.RelativeLayout;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * Created by 林冠宏 on 2016/7/11.
     *
     * 真正的仿微信网页打开的进度条
     *
     * 下面的所有属性都可以自己采用 get set 来自定义
     *
     */
    
    public class SlowlyProgressBar {
    
        private static final int StartAnimation = 0x12;
    
        private Handler handler;
        private View view;
    
        /** 当前的位移距离和速度 */
        private int thisWidth = 0;
        private int thisSpeed = 0;
    
        private int progress = 0;  /** 当前的进度长度 */
        private int record = 0;    /** 移动单位 */
        private int width = 10;    /** 10dp each time */
        private int height = 3;    /** 3dp */
    
        private boolean isStart = false;
    
        private int phoneWidth = 0; /** 屏幕宽度 */
        private int i = 0;
    
        /** 每次的移动记录容器,位移对应每帧时间 */
        private List<Integer> progressQuery = new ArrayList<>();
        private List<Integer> speedQuery    = new ArrayList<>();
    
        public SlowlyProgressBar(View view, int phoneWidth) {
            initHandler();
            this.phoneWidth = phoneWidth;
            this.view = view;
        }
    
        /** 善后工作,释放引用的持有,方能 gc 生效 */
        public void destroy(){
            if(progressQuery!=null){
                progressQuery.clear();
                progressQuery = null;
            }
            if(speedQuery!=null){
                speedQuery.clear();
                speedQuery = null;
            }
            view = null;
            handler.removeCallbacksAndMessages(null);
            handler = null;
        }
    
        public void setProgress(int progress){
            if(progress>100 || progress <= 0){ /** 不能超过100 */
                return;
            }
            /** 每次传入的 width 应该是包含之前的数值,所以下面要减去 */
            /** 下面记得转化比例,公式 (屏幕宽度 * progress / 100) */
            this.width = (progress * phoneWidth)/100;
    
            /** lp.width 总是获取前一次的 大小 */
            /** 移动 100px 时的速度一次倍率 是 2 */
            int size = progressQuery.size();
            if(size != 0){
                size = progressQuery.get(size-1);
            }
            Log.d("zzzzz","width - size = "+(width - size));
            /** 计算倍率,2/100 = x/width */
            int distance = width - size;
            int speedTime;
            if(distance<=100){
                speedTime = 2;
            }else{
                speedTime = (int) ((2 * distance)/100.0);
            }
            /** 添加 */
            progressQuery.add(this.width);
            speedQuery.add(speedTime);
            /** 开始 */
            if(!isStart){
                isStart = true;
                handler.sendEmptyMessage(StartAnimation);
            }
        }
    
        public SlowlyProgressBar setViewHeight(int height){
            this.height = height;
            return this;
        }
    
        private void initHandler(){
            handler = new Handler(){
                @Override
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);
                    switch (msg.what){
                        case StartAnimation:
                            /** 提取队列信息 */
                            if(progress >= thisWidth){ /** 如果已经跑完,那么移出 */
                                if(progressQuery.size() == i){
                                    Log.d("zzzzz","break");
                                    if(progress >= 100){ /** 全部走完,隐藏进度条 */
                                        view.setVisibility(View.INVISIBLE);
                                    }
                                    isStart = false;
                                    break;
                                }
                                Log.d("zzzzz", "size is " + progressQuery.size());
                                thisWidth = progressQuery.get(i);
                                thisSpeed = speedQuery.get(i);
                                i ++;
                            }
                            move(thisSpeed,view.getLayoutParams().width);
                            Log.d("zzzzz", "send 100 "+thisSpeed);
                            /** 发信息的延时长度并不会影响速度 */
                            handler.sendEmptyMessageDelayed(StartAnimation,1);
                            break;
                    }
                }
            };
        }
    
        /** 移动 */
        private void move(int speedTime,int lastWidth){
            if(speedTime > 9){
                speedTime = 9; /** 控制最大倍率 */
            }
            /** 乘 3 是纠正误差 */
            progress = (record * speedTime);
            /** 纠正 */
            if(progress >= lastWidth){
                view.setLayoutParams(new RelativeLayout.LayoutParams(progress,height*3));
            }else{
                Log.d("zzzzz","hit "+progress+"---"+lastWidth);
            }
            record ++;
        }
    }

    五,使用方法与截图

      超简单引入,view 可以是随便一个,例如 TextView,给它一个 background 就行了,就有颜色了。

    public class MainActivity extends AppCompatActivity {
    
        private SlowlyProgressBar slowlyProgressBar;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            slowlyProgressBar =
                    new SlowlyProgressBar
                            (
                                    findViewById(R.id.p),
                                    getWindowManager().getDefaultDisplay().getWidth()
                            )
                    .setViewHeight(3);
    
            WebView webView = (WebView) findViewById(R.id.webview);
            webView.setWebChromeClient(new WebChromeClient(){
    
                @Override
                public void onProgressChanged(WebView view, int newProgress) {
                    super.onProgressChanged(view, newProgress);
                    slowlyProgressBar.setProgress(newProgress);
                }
    
            });
            webView.loadUrl("http://www.cnblogs.com/linguanh");
        }
    
        @Override
        public void finish() {
            super.finish();
            if(slowlyProgressBar!=null){
                slowlyProgressBar.destroy();
                slowlyProgressBar = null;
            }
        }
    }

          

    六,完整项目

      https://github.com/af913337456/SlowlyProgressBar

     

  • 相关阅读:
    聚类算法初探(六)OPTICS
    滚动视差效果——background-attachment
    Working with Strings(使用Oracle字符串)
    netstat详解
    lua的学习
    C# 基础知识 (一).概念与思想篇
    11gR2 RAC启用iptables导致节点宕机问题处理
    sqlplus中隐患组合键
    paip.vs2010 或.net 4.0安装出错解决大法.
    paip.svn使用最佳实践
  • 原文地址:https://www.cnblogs.com/linguanh/p/5666427.html
Copyright © 2011-2022 走看看