Android开发之模仿微信打开网页的进度条效果( * )
作者:指尖下的幽灵 发布时间:2021-09-02 10:17:04
一,为什么说是真正的 * ?
阐述这个问题前,先说下之前网上的,各位可以复制这段字,去百度一下 "仿微信打开网页的进度条效果" ,你会看到有很多类似的文章,不过他们有个共同点,就是实现方法都是一样的,而且,都忽略了微信加载网页时,进度条的缓慢动画效果,它不是生硬地一滑而过,而是用户体验很好,有个速度的变化,由慢到快的效果,语言难于描述,相信各位都有下载微信,可以随便打开个公众号的文章看看效果。
好了,上面说到,之前网上的方法都是都忽略了微信加载网页时,进度条的缓慢动画效果,实现代码也是千篇一律,如下:
/** 先实例化个进度条 */
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开发之模仿微信打开网页的进度条效果( * ),如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!
来源:http://www.cnblogs.com/linguanh/p/5666427.html


猜你喜欢
- 背景在接口请求过程中,传递json对象,springboot转换为实体VO对象后,所有属性都为null。post请求:后台接收请求:当时就懵
- Idea中directory和package的区别,要是错了就右键,make directory as 目录或者源代码目录(Source R
- SpringBoot配置文件中设置server.port不生效我的配置文件为:# application.ymlserver:
- 本文实例总结了Android横竖屏切换相关技巧。分享给大家供大家参考,具体如下:一、禁止横竖屏切换Android横竖屏切换在手机开发中比较常
- 刚开始我以为熔断和降级是一体的,以为他们必须配合使用; 只不过名字不一样而已,但是当我经过思考过后,发现他们其实不是一个东西;降级什么是服务
- 首先 函数指针是指向一组同类型的函数的指针;而类成员函数我们也可以相似的认为,它是指向同类中同一组类型的成员函数的指针,当然这里的成员函数更
- 前言最近遇到一个Jvm old过高的案例,现象是一个站点的jvm old区过高,分析原因是,原来的设计方案有问题,给前端返回的数据里面包含了
- 整理文档,搜刮出一个java Servlet 实现动态验证码图片的代码,稍微整理精简一下做下分享。package com.hacker;im
- 本文实例讲述了WinForm实现的图片拖拽与缩放功能。分享给大家供大家参考,具体如下:最近做项目的时候遇到上传施工平面布置图,查看,因为图片
- 一、简介日志打印是java代码开发中不可缺少的重要一步。日志可以排查问题,可以搜集数据二、常用日志框架比较常用的日志框架就是logback,
- 一、Future 接口当 call()方法完成时,结果必须存储在主线程已知的对象中,以便主线程可以知道该线程返回的结果。为此,可以使用 Fu
- SEATA概要seata 是alibaba 出的一款分布式事务管理器,他有侵入性小,实现简单等特点。我们能够使用seata 实现分布式事务管
- 收费版本:Rainbow Brackets免费版本:Rainbow Brackets Lite介绍一款可以将 (圆括号) [方括号] {花括
- 前言:先写个简单的地点签到功能,如果日后有时间细写的话,会更加好好研究一下百度地图api,做更多逻辑判断。这里主要是调用百度地图中的场景定位
- C# 中闭包(Closure)详解这个问题是在最近一次英格兰 Brighton ALT.NET Beers 活动中提出来的。我发现,如果不用
- Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册
- Android EditText输入手机号空格开发需求是在登录页面的手机EditText中间插入空格,让用户看起来方便点, 130 1234
- 经典排序算法 - 基数排序Radix sort原理类似桶排序,这里总是需要10个桶,多次使用首先以个位数的值进行装桶,即个位数为1则放入1号
- C++/java 继承类的多态详解学过C++和Java的人都知道,他们二者由于都可以进行面向对象编程,而面向对象编程的三大特性就是封装、继承
- 目录生成类注释生成类注解模板生成方法注释生成方法注解模板最近从eclipse转idea了,第一步当然是配置快捷键,模板等。但是!发生了一件贼