Android编程实现自定义ImageView圆图功能的方法

本文实例讲述了Android编程实现自定义ImageView圆图功能的方法。分享给大家供大家参考,具体如下:

首先很感谢开源项目Universal Image Loader图片加载框架。之前也看过一段时间框架源码,但是却没有时间进行知识点的总结。

今天项目遇到了需要实现圆头像的编辑显示,Universal就已经提供了这个显示RoundedBitmapDisplayer这个类实现了圆图功能。看它的代码可以发现是实现的Drawable

public static class RoundedDrawable extends Drawable { protected final float cornerRadius; protected final int margin; protected final RectF mRect = new RectF(), mBitmapRect; protected final BitmapShader bitmapShader; protected final Paint paint; public RoundedDrawable(Bitmap bitmap, int cornerRadius, int margin) { this.cornerRadius = cornerRadius; this.margin = margin; bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); mBitmapRect = new RectF (margin, margin, bitmap.getWidth() - margin, bitmap.getHeight() - margin); paint = new Paint(); paint.setAntiAlias(true); paint.setShader(bitmapShader); } @Override protected void onBoundsChange(Rect bounds) { super.onBoundsChange(bounds); mRect.set(margin, margin, bounds.width() - margin, bounds.height() - margin); // Resize the original bitmap to fit the new bound Matrix shaderMatrix = new Matrix(); shaderMatrix.setRectToRect(mBitmapRect, mRect, Matrix.ScaleToFit.FILL); bitmapShader.setLocalMatrix(shaderMatrix); } @Override public void draw(Canvas canvas) { canvas.drawRoundRect(mRect, cornerRadius, cornerRadius, paint); } @Override public int getOpacity() { return PixelFormat.TRANSLUCENT; } @Override public void setAlpha(int alpha) { paint.setAlpha(alpha); } @Override public void setColorFilter(ColorFilter cf) { paint.setColorFilter(cf); } }

其实总结下来,上面圆图实现步骤就是:

1、通过bitmap初始化位图着色器BitmapShader类
2、计算bitmap原始图片的rect
3、计算放置图片需要的rect
4、使用Matrix类对两个rect进行压缩,然后复制给BitmapShader着色器里去。最后是画布画图。
(刚开始一直以为shader是阴影的意思,原来有道一下是着色器的意思,这个翻译其实对我理解代码还是很重要的,所以不要想当然,要勤奋点,这个是优秀程序员必备要素。)

最后我要实现的是继承ImageView实现圆图

public class URoundedImageView extends ImageView { private Paint mBitmapPaint,mBackgroundPaint; private BitmapShader mBitmapShader; private RectF mBitmapRect , mRect; private int borderWidth; private Bitmap mBitmap; private Matrix shaderMatrix; public URoundedImageView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } public URoundedImageView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public URoundedImageView(Context context) { super(context); init(); } private void init(){ mBitmapPaint = new Paint(); mBitmapPaint.setAntiAlias(true); mBackgroundPaint = new Paint(); mBackgroundPaint.setAntiAlias(true); mBackgroundPaint.setColor(Color.WHITE); borderWidth = 5; mRect = new RectF(); shaderMatrix = new Matrix(); } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { // TODO Auto-generated method stub super.onLayout(changed, left, top, right, bottom); } @Override protected void onDraw(Canvas canvas) { mBitmap = ((BitmapDrawable) getDrawable()).getBitmap(); if (getWidth() == 0 || getHeight() == 0 || mBitmap == null) { return; } int w = getWidth(); int h = getHeight(); int radius = Math.min(w, h) / 2; canvas.drawCircle(w / 2, h / 2, radius, mBackgroundPaint); //传入bitmap初始化位图着色器 if (mBitmapShader == null) { mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); } if (mBitmapRect == null) { mBitmapRect = new RectF(borderWidth, borderWidth, mBitmap.getWidth() - borderWidth, mBitmap.getHeight() - borderWidth); } mBitmapPaint.setShader(mBitmapShader); mRect.set(borderWidth, borderWidth, w - borderWidth, h - borderWidth); //对bitmap原始图进行缩放 shaderMatrix.setRectToRect(mBitmapRect, mRect, Matrix.ScaleToFit.FILL); mBitmapShader.setLocalMatrix(shaderMatrix); canvas.drawRoundRect(mRect, radius, radius, mBitmapPaint); } }

刚开始写的不够规范,直接在ondraw方法里面new一些需要的对象,lint提醒我们Avoid object allocations during draw/layout operations (preallocate and reuse instead)这个warning。因为ondraw会不断调用,如果一直new对象的话会吃内存。所以为了避免重复new对象,根据自己的需求进行判空操作。具体根据自己需求来优化代码,有时候为了达到需求也没办法做到在ondraw方法里不出现重复new对象的现象。

总结:多参考优秀的开源项目,用正确的方法做正确的事情!

更多关于Android相关内容感兴趣的读者可查看本站专题:《Android图形与图像处理技巧总结》、《Android开发入门与进阶教程》、《Android调试技巧与常见问题解决方法汇总》、《Android基本组件用法总结》、《Android视图View技巧总结》、《Android布局layout技巧总结》及《Android控件用法总结》

希望本文所述对大家Android程序设计有所帮助。

时间: 2024-07-28 22:03:47

Android编程实现自定义ImageView圆图功能的方法的相关文章

Android编程实现自定义Tab选项卡功能示例

本文实例讲述了Android编程实现自定义Tab选项卡功能.分享给大家供大家参考,具体如下: import android.app.TabActivity; import android.content.Intent; import android.os.Bundle; import android.widget.*; import android.widget.TabHost.OnTabChangeListener; import android.os.Build; import androi

Android编程简单实现拨号器功能的方法

本文实例讲述了Android编程简单实现拨号器功能的方法.分享给大家供大家参考,具体如下: 学习Android已经有2天时间了,没学习的时候觉得android可能很枯燥,但是学过之后我发觉其实这个比什么javaweb好玩多了.学习android可以见到一些很有趣的东西,这里呢也建议学习javaME的人不要在煎熬了,学习android吧.在写程序之前也需要知道android的工作原理 1.获取组件清单 2.登记或注册组件 3.将组件封装成意图 4.把意图交给意图处理器进行处理 5.把界面显示给用户

Android编程实现自定义系统菜单背景的方法_Android

本文实例讲述了Android编程实现自定义系统菜单背景的方法.分享给大家供大家参考,具体如下: 不多说,上图,见代码. package lab.sodino.menutest; import android.content.Context; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.util.AttributeSet; import androi

Android编程实现自定义进度条颜色的方法_Android

本文实例讲述了Android编程实现自定义进度条颜色的方法.分享给大家供大家参考,具体如下: android 自定义进度条颜色 先看图 基于产品经理各种自定义需求,经过查阅了解,下面是自己对android自定义进度条的学习过程! 这个没法了只能看源码了,还好下载了源码, sources\base\core\res\res\  下应有尽有,修改进度条颜色只能找progress ,因为是改变样式,首先找styles.xml 找到xml后,进去找到 <style name="Widget.Pro

Android编程实现自定义系统菜单背景的方法

本文实例讲述了Android编程实现自定义系统菜单背景的方法.分享给大家供大家参考,具体如下: 不多说,上图,见代码. package lab.sodino.menutest; import android.content.Context; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.util.AttributeSet; import androi

Android编程实现自定义title功能示例

本文实例讲述了Android编程实现自定义title功能.分享给大家供大家参考,具体如下: 这里我在前面加了个logo,而且改变了title的背景和高度. 首先编写title的布局文件,title.xml: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

Android编程实现自定义分享列表ACTION_SEND功能的方法

本文实例讲述了Android编程实现自定义分享列表ACTION_SEND功能的方法.分享给大家供大家参考,具体如下: 看到最近都在做自定义的东西,因为比较灵活,还可以摆脱系统自身不怎么漂亮的UI,(大家都懂得)所以自己也做了下自定义的分享列表,用PopupWindow的方式弹出. 先上效果图: 1.布局: popup_share.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xml

Android编程实现自定义手势的方法详解_Android

本文实例讲述了Android编程实现自定义手势的方法.分享给大家供大家参考,具体如下: 之前介绍过如何在Android程序中使用手势,主要是系统默认提供的几个手势,这次介绍一下如何自定义手势,以及如何对其进行管理. 先介绍一下Android系统对手势的管理,Android系统允许应用程序把用户的手势以文件的形式保存以前,以后要使用这些手势只需要加载这个手势库文件即可,同时Android系统还提供了诸如手势识别.查找及删除等的函数接口,具体如下: 一.加载手势库文件: staticGestureL

Android编程之自定义锁屏实例分析_Android

本文实例讲述了Android编程之自定义锁屏.分享给大家供大家参考,具体如下: 花了半天时间研究下了自定义锁屏,发现其实实现并不是很神秘.不过有些地方还是值得注意. 首先说流程,锁屏界面一般是在关闭屏幕时启用,打开屏幕时展现在我们面前,所以我们知道了锁屏的时机,恰好屏幕开关会发出相应的广播,所以我们也可以像系统一样捕获到屏幕开关的事件. 广播对应的两个action 引用 android.intent.action.SCREEN_ON android.intent.action.SCREEN_OF