改善用户体验,用图片的自身变化以及进度通知摆脱传统的进度条,okhttp,Canvas,Paint实现
转载请注明出处:王亟亟的大牛之路
从最開始的白页面等待,到后来的进度条告知用户。到如今的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实现
- 改善用户体验,用图片的自身变化以及进度通知摆脱传统的进度条,okhttp,Canvas,Paint实现
- MVP,购物车啊,图片加载用Fresco,OKhttp+Retrofit实现
- ajax:改善用户体验之进度条
- 前端图片懒加载(lazyload)的实现方法(提高用户体验)
- 安卓开发-进度条上方显示各个进度的视频片段,如何实现 安卓开发问题,请问这种进度条上弹框显示各个时间段视频片段是怎么实现的?![图片](http://img.ask.csdn.net/upload/2
- 【收藏】iOS将图片写入原生相册以及进度条实现
- Paint&Canvas实现一个点(图片)在圆形(轨迹)上运动
- Android_OkHttp+Picasso+RecyclerView实现网络图片下载瀑布流
- ListView异步加载图片是非常实用的方法,凡是是要通过网络获取图片资源一般使用这种方法比较好,用户体验好,下面就说实现方法,先贴上主方法的代码:
- UIScrollView+UIPageControl+NSTimer实现图片的自动滑动以及用户可手动切换,UIPageControl可点击
- Volley-XUtils-OkHttp三种方式实现单张多张图片上传
- android实现用户体验超棒的微信WebView进度条
- UIScrollView+UIPageControl+NSTimer实现图片的自动滑动以及用户可手动切换,UIPageControl可点击
- 嵌入式 C语言实现进度条以及实现带进度条的CP命令等编程示例收集一
- java session HttpSessionListener、HttpSessionBindingListener使用区别,实现在线人数统计以及踢出用户
- Canvas实现图片裁剪、移动、放大缩小以及图片的合成
- Paip.提升用户体验------在C++ Builder 不规则图片按钮实现总结
- android实现下载图片在(Notification)通知栏上显示进度。
- java session HttpSessionListener、HttpSessionBindingListener使用区别,实现在线人数统计以及踢出用户