欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android开发之模仿微信打开网页的进度条效果(高仿)

程序员文章站 2024-03-04 13:48:29
一,为什么说是真正的高仿?   阐述这个问题前,先说下之前网上的,各位可以复制这段字,去百度一下  "仿微信打开网页的进度条效果" ,你会看到有很多类似的文...

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

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

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

/** 先实例化个进度条 */
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;
 }
 }
} 

Android开发之模仿微信打开网页的进度条效果(高仿)Android开发之模仿微信打开网页的进度条效果(高仿)

以上所述是小编给大家介绍的android开发之模仿微信打开网页的进度条效果(高仿)