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 ...
随机推荐
- WEB前端--深入进去
在网站开发这条道路上做专做精,一个专题一个专题的深入探索,一个盲区一个盲区的理解和记忆,终有大成的那一天的.
- python内存增长问题
如果你的程序没有调用什么特殊的库, 只是用了很平常的库, 而且使再循环很多的情况下, 那么建议你把循环里的程序拆出来,写成一子函数,循环子函数. 如下面格式: for (循环) 子函数 这样程序每 ...
- Mysql5.7.19压缩版安装步骤及踩过的坑
安装Mysql5.7.19压缩版 一:下载压缩包 1.从MySQL官网下载MySQL Community Server 5.7.19,此版本为免费版. 2.下载完成之后解压缩,打开之后文件夹如下: ...
- web.config访问走代理的配置
<system.net> <defaultProxy> <proxy bypassonlocal="False" usesystemd ...
- Codeforces Round #367 (Div. 2) (A,B,C,D,E)
Codeforces Round 367 Div. 2 点击打开链接 A. Beru-taxi (1s, 256MB) 题目大意:在平面上 \(n\) 个点 \((x_i,y_i)\) 上有出租车,每 ...
- 低成本开始互联网创业:探讨域名、服务器、CDN、邮箱等节流之道
互联网创业一直是个热门话题,对这个问题我也有不断的思考. 今天,探讨下如何低成本开始互联网创业. 背景 愿意冒险去创业的同志,大多是"屌丝"而非"高富帅",大多 ...
- sea.js五分钟上手
SeaJS是一个遵循CommonJS规范的JavaScript模块加载框架.本文给大家分享sea.js知识总结,感兴趣的朋友一起学习吧http://reactjs.cn/http://reactjs. ...
- C语言深度剖析-----数组与指针分析
数组的本质: 指针的运算: 小标VS指针: a和&a的区别: 例: 数组参数: 所以下例返回4 指针和数组的对比小结:
- (转)yum & wget代理设置
转自 http://www.cnblogs.com/windows/archive/2012/12/14/2817533.html yum 配置代理服务器访问要设置所有 yum 操作都使用代理服 ...
- 【例题 6-6 UVA - 679】Dropping Balls
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 直接模拟会超时. 根据奇偶的规律.直接判断会往哪里走就好. 每个二叉树的节点.必然是左边和右边走的次数对半分.->奇数左边多一 ...