转载请注明出处:王亟亟的大牛之路

从最開始的白页面等待,到后来的进度条告知用户。到如今的WebBO/微信这样的先下缩略图点击才又一次下大图的方式,我们开发人员对用户感知的注意度越来越高。昨天刷微博的时候看到他们是用一个灰色转圈圈的实现,所以就萌生的今天要做的内容的启示(我是在不知道给这样的实现取什么名字。就写了一大堆。感觉在哪见过相似的可是,忘了出自于哪了)

先上下效果:

GIF软件继续把我的效果给吃了。。大家能够自己跑一下,看效果。


HOW to do?

1.我们的图片来自于网络,假设是本地,也不须要这一系列的操作了,差点儿是瞬间。那么我们的下载过程中的进度通知得一直刷新。
2.我们得让图片一直在更新UI至少产生差异性,不然用户不知道这是干什么

带着这2个问题,我们来说一下,首先是下载,用Volley,和api自带的一些库都能够实现。往里面加回调传进度出来即可了,这里楼主用的是git大牛的https://github.com/hongyangAndroid/okhttp-utils

对okhttp的封装简单易用。

第二个问题就是怎么实现,我们有了进度。那就是画。这边用的是源生的bitmap canvas paint三剑客,详细怎么做。等会代码会贴。


包结构:

实现类:MainActivity

父类:Father(提供抽象方法)

图片数据源:Config(正常图片太小了,强行 试了好多次)

public class MainActivity extends Father {
private Button btn;
private ImageView imageView;
private Paint paint;
private Canvas canvas;
private Bitmap bitmap;
private String fileUrl;
private float imageWidth, imageHeight;
private Paint paint2; @Override
public int getLayout() {
return R.layout.activity_main;
} @Override
public void init() {
btn=(Button)findViewById(R.id.btn);
imageView = (ImageView) findViewById(R.id.imageView);
imageWidth = (int) getResources().getDimension(R.dimen.image_width);
imageHeight = (int) getResources().getDimension(R.dimen.image_height);
} @Override
public void setClick() {
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
fileUrl = Environment.getExternalStorageDirectory().getAbsolutePath() + "/wjj/" + "meizi.jpg"; if (checkFile(fileUrl)) {
LogUtils.d("--->onResume checkFile==true");
imageView.setImageBitmap(BitmapFactory.decodeFile(fileUrl));
Toast.makeText(MainActivity.this,"图片已经存在于SD卡内",Toast.LENGTH_SHORT).show();
} else {
LogUtils.d("--->onResume checkFile==false");
DownLoadImage(ConFig.ImageUrl);
}
}
});
} @Override
public void Logic() {
LogUtils.d("--->MainActivity Logic getWidth " + imageWidth + " getHeight " + imageHeight);
if (bitmap == null) {
bitmap = Bitmap.createBitmap((int) imageWidth,
(int) imageHeight, Bitmap.Config.ARGB_8888);
canvas = new Canvas(bitmap);
canvas.drawColor(getResources().getColor(R.color.Gray));
}
paint = new Paint();
paint.setColor(getResources().getColor(R.color.White));
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); paint2 = new Paint(); paint2.setColor(getResources().getColor(R.color.Gray));
paint2.setTextSize(90);
paint2.setTextAlign(Paint.Align.CENTER);
imageView.setImageBitmap(bitmap);
} @Override
protected void onResume() {
super.onResume();
} private void DownLoadImage(String ImageUrl) {
OkHttpUtils
.get()
.url(ImageUrl)
.build()
.execute(new FileCallBack(Environment.getExternalStorageDirectory().getAbsolutePath() + "/wjj/", "meizi.jpg") { @Override
public void inProgress(float progress) {
LogUtils.d((int) (100 * progress) + "高度等于 " + imageHeight * progress);
canvas.drawRect(0, 0, imageWidth, imageHeight * progress, paint);
canvas.drawText((int) (100 * progress) + "%", imageWidth / 2, imageHeight / 2 - 200, paint2); imageView.setImageBitmap(bitmap);
} @Override
public void onError(Request request, Exception e) {
LogUtils.e("onError :" + e.getMessage());
} @Override
public void onResponse(File file) {
LogUtils.d("onResponse :" + file.getAbsolutePath());
imageView.setImageBitmap(BitmapFactory.decodeFile(file.getAbsolutePath()));
}
});
} /**
* 控件的高度
*
* @param view 控件View
* @return 返回控件的高度
*/
public static int getHeight(View view) {
if (view == null) {
throw new IllegalArgumentException("view is null");
} view.measure(0, 0);
return view.getMeasuredHeight();
} /**
* 获取控件的宽度
*
* @param view 控件
* @return 返回控件的宽度
*/
public static int getWidth(View view) {
if (view == null) {
throw new IllegalArgumentException("view is null");
} view.measure(0, 0);
return view.getMeasuredWidth();
} private boolean checkFile(String checkFile) {
File mFile = new File(fileUrl);
//若该文件存在
if (mFile.exists()) {
return true;
} else {
return false;
}
}
}

代码都在上面了。来说一下里面的坑。

坑1

image.getHeight()和image.getWidth,粗略看来是不是假设我们设置的不是wrap_content那么一定能获取到參数?

事实是NO,不管怎么整他都是0,那怎么获取呢?方法例如以下!

//------------------------------------------------方法一
int w = View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.UNSPECIFIED);
int h = View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.UNSPECIFIED);
imageView.measure(w, h);
int height =imageView.getMeasuredHeight();
int width =imageView.getMeasuredWidth();
LogUtils.d("\n"+height+","+width); //-----------------------------------------------方法二
ViewTreeObserver vto = imageView.getViewTreeObserver();
vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
public boolean onPreDraw() {
int height = imageView.getMeasuredHeight();
int width = imageView.getMeasuredWidth();
LogUtils.d("\n"+height+","+width);
return true;
}
});
//-----------------------------------------------方法三
ViewTreeObserver vto2 = imageView.getViewTreeObserver();
vto2.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
imageView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
LogUtils.d("\n\n"+imageView.getHeight()+","+imageView.getWidth());
}
});

这些都能获取到參数。可是仅仅要离开那行代码。东西就没了还是0 .WHY 什么鬼。?

onCreate方法运行完了,我们定义的控件才会被度量(measure),所以我们在onCreate方法里面通过view.getHeight()获取控件的高度或者宽度肯定是0,由于它自己还没有被度量,也就是说他自己都不知道自己有多高,而你这时候去获取它的尺寸,是不行的.

那有两个办法,1.我去设一张图片。然后图片的大小就是我控件的大小。

2.也就是我用的方法,人工控件的大小。脑洞来源于:http://stackoverflow.com/questions/19271609/imageview-getwidth-returns-0

文章中是这样

  imageWidth = (int) getResources().getDimension(R.dimen.image_width);
imageHeight = (int) getResources().getDimension(R.dimen.image_height);

那么有人要问了,我实际场景下也设定死吗?

我们的业务层不可能整一个页面都是一张图。那么UI给与我们界面定稿的时候总有一个相对大小,而我们的控件大小能够在适配的大小区间里来游走(反正在现实场景时,这图片总是点击放大才去载入。而那时候不已经全屏看了?你还在意控件大小么?)

所以。这个实现的使用场景就是在看大图时(一定得大。不然怎么都是瞬间),才有他的使用价值。


小解释:

代码中的paint 是用来画背景的 paint2 是用来画进度的文字的。

文字位置是 x=宽/2 y=长/2

图片更新方式:总长/100=每1%的Y向长度,然后每次更新的进度数*这个1%Y长度即可。

文章中的图片最后还是存于SD卡里的,假设想直接下载完Set到ImageView上的话就别存把流转一下就好了。

源代码地址:https://github.com/ddwhan0123/BlogSample/tree/master/ImageLoadingAnim

记得点个赞哦!!

改善用户体验,用图片的自身变化以及进度通知摆脱传统的进度条,okhttp,Canvas,Paint实现的更多相关文章

  1. 改善用户体验之wordpress添加图片弹出层效果 (插件 FancyBox)

    下面说说在改善用户体验之wordpress添加图片弹出层效果.效果图如下:   像这篇文章如何在百度搜索结果中显示网站站点logo? 文章内有添加图片,没加插件之前用户点击图片时,是直接_black打 ...

  2. paip.提升用户体验--radio图片选择器 easyui 实现..

    #paip.提升用户体验--radio图片选择器 easyui 实现.. =================================== ##原因... ------------------- ...

  3. 自己定义progressdialog,改善用户体验

    自己定义progressdialog,改善用户体验 效果图: 详细实现方式: 1.定义Dialog的Layout布局 2.设置动画anim 3.创建自己定义dialog的样式 4.创建共同拥有方法来控 ...

  4. 自定义progressdialog,改善用户体验

    自定义progressdialog,改善用户体验

  5. 提升网站用户体验—WebP 图片的高效使用

    一.WebP 的由来 现代图像压缩技术对我们的生活方式影响很大.数码相机能将上千张高质量图片存储到一张内存卡里.智能手机可以与邻近设备快速分享高分辨率的图片.网站与手机等移动设备能快速展示各种富媒体. ...

  6. 改善用户体验 Web前端优化策略总结

    前端是庞大的,包括HTML.CSS.Javascript.Image.Flash等等各种各样的资源.前端优化是复杂的,针对方方面面的资源都有不同的方式.那么,前端优化的目的是什么? 1. 从用户角度而 ...

  7. 使用JS&jQuery改善用户体验

    第一章  JavaScript基本语法 一.运算符 运算符就是完成操作的一系列符号,它有七类: 赋值运算符(=,+=,-=,*=,/=,%=,<<=,>>=,|=,&= ...

  8. 【读书笔记】iOS-反溃网络信息改善用户体验

    一,iOS6表视图刷新控件的使用. 二,使用等待指示器控件. 三,使用网络等待指示器. 四,使用MBProgressHUD等待指示器. 参考资料:<iOS网络编程与云端应用-最佳实践>

  9. web设计经验<二>设计华丽的用户体验的6个热门技巧

    你是否曾经下载了一个应用,却发现它“很难使用”?对于大多数智能手机用户来说,答案是肯定的. 有趣的是,每四个手机应用中就有一个应用在下载后被“打入冷宫”. 如果一个应用能够吸引一个人下载并且打开它,但 ...

随机推荐

  1. [Android Pro] 有关Broadcast作为内部类时注册的一些问题

    很经常Broadcast都会写成一个Activity或者Service的内部类.这时候的注册和普通有点小区别. 有两种情况 1.假如是再Manifest文件里面静态注册的话,需要注意. ex: < ...

  2. 数学图形(2.12)spherical cycloid球面外摆曲线

    查了半天也没搜到其具体的定义,先把脚本代码和截图发下. #http://www.mathcurve.com/courbes3d/cycloidspheric/cycloidspheric.shtml ...

  3. C/C++下scanf的%匹配以及过滤字符串问题

    最近在写一个测试的小程序,由于用到了sscanf函数对字符串进行标准读入,而sscanf在很多方面都与scanf比较相像,于是对scanf进行了一番测试,遇到了一系列基础性的问题,恶补基础的同时也体现 ...

  4. Sql从一张表中更改另一张表数据

    语法: update table1 set table1.列=table2.列 from table2 where table2.列=table1.列update dbo.PATIENT     se ...

  5. jdk1.7下载路径

    http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html

  6. 利用kettle中的JS来完成ETL数据校验

    最近参与了一个信托行业的BI项目,由于信托业务系统设计的问题,很多都是用户手工录入的数据,也有一些是需要分析的但是用户没有录入的数据,针对这样的数据质量,我们就要在ETL抽取的过程中来对数据流进行校验 ...

  7. 从头认识java-13.11 对照数组与泛型容器,观察类型擦除给泛型容器带来什么问题?

    这一章节我们继续类型擦除的话题,我们将通过对照数组与泛型容器,观察类型擦除给泛型容器带来什么问题? 1.数组 package com.ray.ch13; public class Test { pub ...

  8. ASP服务器I I S出现authentication mode=Windows错误解决办法

    网上下载的asp.net源码出现 <authentication mode="Windows"/>错误信息 属性 说明 mode 必选的属性. 指定应用程序的默认身份验 ...

  9. Python网络爬虫 - 2. Beautiful Soup小试牛刀

    目标: 我们解析百度首页的logo bs_baidu_logo.py from urllib.request import urlopen from bs4 import BeautifulSoup ...

  10. [原创-性能调优]借助AWR报告分析解决oracleCPU过高的问题

    简介:在oracle数据库中,有两个非常实用的自带监控工具EM(Enterprise Manager)和AWR(Automatic Workload Repository).其中,通过AWR报告可以生 ...