Android Xfermode 真实 实现全面、圆角图片
转载请注明出处:http://blog.csdn.net/lmj623565791/article/details/42094215。本文出自:【张鸿洋的博客】
1、概述
事实上这篇本来准备Android BitmapShader 实战 实现圆形、圆角图片放到一篇里面。结果由于篇幅原因就独立出来了~在非常久曾经也写过一个利用Xfermode 实现圆形、圆角图片的,可是那个继承的是View。事实上继承ImageView能方便点,最起码省去了onMeasure里面自己去策略,以及不须要自己去提供设置图片的方法,最基本的是大家对ImageView的API会比較熟悉,用起来会比較顺手。
好了。本篇就当是个记录了~~~电脑上代码放几天就找不到了,还是放博客里面,有须要自己过来看看~~~
2、原理
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbG1qNjIzNTY1Nzkx/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />
原理就不多说了,这张图在我博客里出现的次数大概有3次以上了,我们这次使用的模式DST_IN;也就是先绘制图片,再绘制形状了~~
3、Xfermode实战
1、自己定义属性
首先依旧是自己定义属性,和上篇一致。
<?xml version="1.0" encoding="utf-8"? >
<resources> <attr name="borderRadius" format="dimension" />
<attr name="type">
<enum name="circle" value="0" />
<enum name="round" value="1" />
</attr> <declare-styleable name="RoundImageViewByXfermode">
<attr name="borderRadius" />
<attr name="type" />
</declare-styleable> </resources>
2、构造中获取属性
public class RoundImageViewByXfermode extends ImageView
{ private Paint mPaint;
private Xfermode mXfermode = new PorterDuffXfermode(Mode.DST_IN);
private Bitmap mMaskBitmap; private WeakReference<Bitmap> mWeakBitmap; /**
* 图片的类型,圆形or圆角
*/
private int type;
public static final int TYPE_CIRCLE = 0;
public static final int TYPE_ROUND = 1;
/**
* 圆角大小的默认值
*/
private static final int BODER_RADIUS_DEFAULT = 10;
/**
* 圆角的大小
*/
private int mBorderRadius; public RoundImageViewByXfermode(Context context)
{
this(context,null); mPaint = new Paint();
mPaint.setAntiAlias(true);
} public RoundImageViewByXfermode(Context context, AttributeSet attrs)
{
super(context, attrs); mPaint = new Paint();
mPaint.setAntiAlias(true); TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.RoundImageViewByXfermode); mBorderRadius = a.getDimensionPixelSize(
R.styleable.RoundImageViewByXfermode_borderRadius, (int) TypedValue
.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
BODER_RADIUS_DEFAULT, getResources()
.getDisplayMetrics()));// 默觉得10dp
Log.e("TAG", mBorderRadius+"");
type = a.getInt(R.styleable.RoundImageViewByXfermode_type, TYPE_CIRCLE);// 默觉得Circle a.recycle();
}
获取自己定义属性,然后还写些成员变量~~
3、onMeasure
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
super.onMeasure(widthMeasureSpec, heightMeasureSpec); /**
* 假设类型是圆形。则强制改变view的宽高一致,以小值为准
*/
if (type == TYPE_CIRCLE)
{
int width = Math.min(getMeasuredWidth(), getMeasuredHeight());
setMeasuredDimension(width, width);
} }
在onMeasure中。假设是圆形则又一次设置view大小。
4、onDraw
@SuppressLint("DrawAllocation")
@Override
protected void onDraw(Canvas canvas)
{
//在缓存中取出bitmap
Bitmap bitmap = mWeakBitmap == null ? null : mWeakBitmap.get(); if (null == bitmap || bitmap.isRecycled())
{
//拿到Drawable
Drawable drawable = getDrawable();
//获取drawable的宽和高
int dWidth = drawable.getIntrinsicWidth();
int dHeight = drawable.getIntrinsicHeight(); if (drawable != null)
{
//创建bitmap
bitmap = Bitmap.createBitmap(getWidth(), getHeight(),
Config.ARGB_8888);
float scale = 1.0f;
//创建画布
Canvas drawCanvas = new Canvas(bitmap);
//依照bitmap的宽高,以及view的宽高。计算缩放比例;由于设置的src宽高比例可能和imageview的宽高比例不同,这里我们不希望图片失真。
if (type == TYPE_ROUND)
{
// 假设图片的宽或者高与view的宽高不匹配,计算出须要缩放的比例;缩放后的图片的宽高,一定要大于我们view的宽高;所以我们这里取大值;
scale = Math.max(getWidth() * 1.0f / dWidth, getHeight()
* 1.0f / dHeight);
} else
{
scale = getWidth() * 1.0F / Math.min(dWidth, dHeight);
}
//依据缩放比例,设置bounds。相当于缩放图片了
drawable.setBounds(0, 0, (int) (scale * dWidth),
(int) (scale * dHeight));
drawable.draw(drawCanvas);
if (mMaskBitmap == null || mMaskBitmap.isRecycled())
{
mMaskBitmap = getBitmap();
}
// Draw Bitmap.
mPaint.reset();
mPaint.setFilterBitmap(false);
mPaint.setXfermode(mXfermode);
//绘制形状
drawCanvas.drawBitmap(mMaskBitmap, 0, 0, mPaint);
mPaint.setXfermode(null);
//将准备好的bitmap绘制出来
canvas.drawBitmap(bitmap, 0, 0, null);
//bitmap缓存起来,避免每次调用onDraw,分配内存
mWeakBitmap = new WeakReference<Bitmap>(bitmap);
}
}
//假设bitmap还存在,则直接绘制就可以
if (bitmap != null)
{
mPaint.setXfermode(null);
canvas.drawBitmap(bitmap, 0.0f, 0.0f, mPaint);
return;
} }
/**
* 绘制形状
* @return
*/
public Bitmap getBitmap()
{
Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(),
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.BLACK); if (type == TYPE_ROUND)
{
canvas.drawRoundRect(new RectF(0, 0, getWidth(), getHeight()),
mBorderRadius, mBorderRadius, paint);
} else
{
canvas.drawCircle(getWidth() / 2, getWidth() / 2, getWidth() / 2,
paint);
} return bitmap;
}
在onDraw中拿到drawable,然后获取drawable的宽和高。依据当前的type和view的宽和高。进行适当的缩放。详细原理:參考上篇的matrix的scale计算,原理一致。
然后就是设置Xfermode,getBitmap会依据type返回图形,直接绘制到内存中的bitmap上就可以。最后把bitmap缓存起来,避免每次onDraw都分配内存和重新启动画图。
大家能够进行扩展type,绘制心形、三角形什么的,直接在getBitmap里面加入分支就能够。
最后记得invalidate中做一些处理:
@Override
public void invalidate()
{
mWeakBitmap = null;
if (mMaskBitmap != null)
{
mMaskBitmap.recycle();
mMaskBitmap = null;
}
super.invalidate();
}
主要是由于我们缓存了,当调用invalidate时。将缓存清除。
4、布局文件及效果图
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:zhy="http://schemas.android.com/apk/res/com.zhy.variousshapeimageview"
android:layout_width="match_parent"
android:layout_height="wrap_content" > <LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" > <com.zhy.view.RoundImageViewByXfermode
android:layout_width="130dp"
android:layout_height="130dp"
android:layout_margin="10dp"
android:src="@drawable/qiqiu" >
</com.zhy.view.RoundImageViewByXfermode> <com.zhy.view.RoundImageViewByXfermode
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:src="@drawable/aa"
zhy:borderRadius="30dp"
zhy:type="round" >
</com.zhy.view.RoundImageViewByXfermode> <com.zhy.view.RoundImageViewByXfermode
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:src="@drawable/aa"
zhy:type="circle" >
</com.zhy.view.RoundImageViewByXfermode> <com.zhy.view.RoundImageViewByXfermode
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_margin="10dp"
android:src="@drawable/aa"
zhy:type="circle" >
</com.zhy.view.RoundImageViewByXfermode> </LinearLayout> </ScrollView>
效果图:
好了,比較简单~~
声明下:本例參考了:https://github.com/MostafaGazar/CustomShapeImageView ;只是对当中的部分代码进行了改变,比方CustomShapeImageView假设图片为长方形,可是设置为circle类型。效果依旧是矩形;以及会对bitmap比例和view比例不一致的直接进行压缩。相似fitxy的效果~~~主要对这两点进行了改动~~当然了,该案例比本博客功能要强大,看名字也知道,支持非常多形状,以及支持SVG~大家自行进行參考~
我新建了一个QQ群,方便大家交流。
群号:423372824
----------------------------------------------------------------------------------------------------------
博主部分视频已经上线。假设你不喜欢枯燥的文本。请猛戳(初录,期待您的支持):
Android Xfermode 真实 实现全面、圆角图片的更多相关文章
- 【Android】 图片编辑:创建圆角图片
创建圆角图片的方式大同小异,最简单的就是 9.png 美工做出来的就是.这种最省事直接设置就可以. 另外一种就是通过裁剪 这里的剪裁指的是依据原图我们自己生成一张新的bitmap,这个时候指定图片的目 ...
- Android Xfermode 实战 实现圆形、圆角图片
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/42094215,本文出自:[张鸿洋的博客] 1.概述 其实这篇本来准备Androi ...
- Android BitmapShader 实战 实现圆形、圆角图片
转载自:http://blog.csdn.net/lmj623565791/article/details/41967509 1.概述 记得初学那会写过一篇博客Android 完美实现图片圆角和圆形( ...
- Android实现圆形圆角图片
本文主要使用两种方法实现图形圆角图片 自定View加上使用Xfermode实现 Shader实现 自定View加上使用Xfermode实现 /** * 根据原图和变长绘制圆形图片 * * @param ...
- 【转】Android BitmapShader 实战 实现圆形、圆角图片
转载自:http://blog.csdn.net/lmj623565791/article/details/41967509 1.概述 记得初学那会写过一篇博客Android 完美实现图片圆角和圆形( ...
- Android 圆形/圆角图片的方法
Android 圆形/圆角图片的方法 眼下网上有非常多圆角图片的实例,Github上也有一些成熟的项目.之前做项目,为了稳定高效都是选用Github上的项目直接用.但这样的结束也是Android开发必 ...
- Android 高级UI设计笔记18:实现圆角图片
1. 下面我们经常在APP中看到的圆角图片,如下: 再比如:微信聊天会话列表的头像是圆角的. 2. 下面分析一个Github的经典: (1)Github库地址: https://github.com/ ...
- android 圆角图片的实现形式
android 圆角图片的实现形式,包括用第三方.也有系统的.比如makeramen:roundedimageview,系统的cardview , glide .fresco . compile 'c ...
- Android 使用自定义Drawable 设置圆角矩形或者圆形图片
转自 Android Drawable 那些不为人知的高效用法 本文出自:[张鸿洋的博客] http://blog.csdn.net/lmj623565791/article/details/437 ...
随机推荐
- ES5比较Jquery中的each与map 方法?
1.each es5: var arr = [1, 5, 7, 8, 9];var arr1 = []; arr.forEach(function (v, i) { arr1.push(v * 4) ...
- v-for一定要与v-bind:key="id"连用
1. v-for: <div v-for="(item,index) in todolist" v-bind:key="item.id"> < ...
- python基础--数值类型和序列类型
Python中数值类型:int(整数),float(浮点数),True/False(布尔值,首字母必须大写) int:1 #任意整数 float:2.3 #小数 python赋值: a = ...
- opencv cvPreCornerDetect
关于OpenCv中cvPreCornerDetect 运行出错解决方法 http://m.blog.csdn.net/blog/wode0239 由于书本上示例的不全,相信大家在做的时候,肯定是无从下 ...
- PatentTips - Method and Apparatus to Support Virtualization with Code Patches
BACKGROUND As recognized in Revision 2.0 of the Intel® Virtualization Technology Specification for t ...
- GOROOT,GOPATH,GOBIN,project
GOROOT,GOPATH,GOBIN,project目录 我们接下来一个一个来看关于Go语言中的三个目录的详细解释先通过go env查看go的环境变量(我这里是mac的环境,所以可能和你的不同) ...
- 1.5 Python基础知识 - while循环
在我们生活中有很多反复要做的事情,或者动作,我们称之为循环.在开发程序中也会有循环的事情要去做,就是需要反复的去执行某个代码,或者反复进行某种演算,直到达到某种条件的时候才会停止.在Python中我们 ...
- Android 快速下载 Android framework 源码
官网 Android framework源码git地址 github: https://github.com/android/platform_frameworks_base google 官方: h ...
- Altium Designer线如何跟着原件走
- 写给自己的TypeScript 入门小纲
前几日,在知乎上写了一些技术类的文章,有人私信问我,是不是要找一份工作,有没有想过要跳槽,然后我回到,你们公司都是用的什么框架什么技术,他罗列了一堆,其中就包含了TypeScript,我甚至不知道有这 ...