转载请注明出处: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

----------------------------------------------------------------------------------------------------------

博主部分视频已经上线。假设你不喜欢枯燥的文本。请猛戳(初录,期待您的支持):

1、Android 自己定义控件实战 电商活动中的刮刮卡

2、Android自己定义控件实战  打造Android流式布局和热门标签

3、Android智能机器人“小慕”的实现

4、高仿QQ5.0側滑

5、高仿微信5.2.1主界面和信息提示

Android Xfermode 真实 实现全面、圆角图片的更多相关文章

  1. 【Android】 图片编辑:创建圆角图片

    创建圆角图片的方式大同小异,最简单的就是 9.png 美工做出来的就是.这种最省事直接设置就可以. 另外一种就是通过裁剪 这里的剪裁指的是依据原图我们自己生成一张新的bitmap,这个时候指定图片的目 ...

  2. Android Xfermode 实战 实现圆形、圆角图片

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/42094215,本文出自:[张鸿洋的博客] 1.概述 其实这篇本来准备Androi ...

  3. Android BitmapShader 实战 实现圆形、圆角图片

    转载自:http://blog.csdn.net/lmj623565791/article/details/41967509 1.概述 记得初学那会写过一篇博客Android 完美实现图片圆角和圆形( ...

  4. Android实现圆形圆角图片

    本文主要使用两种方法实现图形圆角图片 自定View加上使用Xfermode实现 Shader实现 自定View加上使用Xfermode实现 /** * 根据原图和变长绘制圆形图片 * * @param ...

  5. 【转】Android BitmapShader 实战 实现圆形、圆角图片

    转载自:http://blog.csdn.net/lmj623565791/article/details/41967509 1.概述 记得初学那会写过一篇博客Android 完美实现图片圆角和圆形( ...

  6. Android 圆形/圆角图片的方法

    Android 圆形/圆角图片的方法 眼下网上有非常多圆角图片的实例,Github上也有一些成熟的项目.之前做项目,为了稳定高效都是选用Github上的项目直接用.但这样的结束也是Android开发必 ...

  7. Android 高级UI设计笔记18:实现圆角图片

    1. 下面我们经常在APP中看到的圆角图片,如下: 再比如:微信聊天会话列表的头像是圆角的. 2. 下面分析一个Github的经典: (1)Github库地址: https://github.com/ ...

  8. android 圆角图片的实现形式

    android 圆角图片的实现形式,包括用第三方.也有系统的.比如makeramen:roundedimageview,系统的cardview , glide .fresco . compile 'c ...

  9. Android 使用自定义Drawable 设置圆角矩形或者圆形图片

    转自  Android Drawable 那些不为人知的高效用法 本文出自:[张鸿洋的博客] http://blog.csdn.net/lmj623565791/article/details/437 ...

随机推荐

  1. 1.1 Introduction中 Guarantees官网剖析(博主推荐)

    不多说,直接上干货! 一切来源于官网 http://kafka.apache.org/documentation/ Guarantees Kafka的保证(Guarantees) At a high- ...

  2. AVCaptureSession音频视频采集

    // // AudioVideoCaptureViewController.m // live // // Created by lujunjie on 2016/10/31. // Copyrigh ...

  3. Scala具体解释---------数组、元组、映射

    一.数组 1.定长数组 声明数组的两种形式: 声明指定长度的数组 val 数组名= new Array[类型](数组长度) 提供数组初始值的数组,无需newkeyword Scala声明数组时.须要带 ...

  4. Android车载导航的一些困境

    车载导航从最初的用解码芯片,过渡到用WinCE系统,已经形成了一个较大的产业.车载导航使用上的一些大原则,基本上被固定了下来.如今WinCE走到了尽头,Android车载导航開始发力,但由于Andro ...

  5. vue中监听路由参数变化

    今天遇到一个这样的业务场景:在同一个路由下,只改变路由后面的参数值, 比如在这个页面  /aaa?id=1 ,在这个页面中点击一个按钮后 跳转到 /aaa?id=2 , 但从“/aaa?id=1”到“ ...

  6. C++ tab键实现自动补全输入功能

    一.简介 由于项目中写了个测试的控制台程序,是每次读取一行,即通过getline()来实现的,所以每次必须输入全路径名称,才能实现运行. 大家都觉得麻烦,就写了个tab键自动选择补全的. 目前基本可实 ...

  7. SpringMVC学习记录(五)--表单标签

    在使用SpringMVC的时候我们能够使用Spring封装的一系列表单标签,这些标签都能够訪问到ModelMap中的内容. 以下将对这些标签一一介绍. 1.引入标签头文件 在正式介绍SpringMVC ...

  8. 切换根控制器UIApplication 主屏幕UIScreen 读取文件资源NSBundle

    //主屏幕设为webView CGRect frame = [UIScreen mainScreen].applicationFrame; UIWebView *webView = [[[UIWebV ...

  9. Android中各种drawable的使用

    转载请说明出处.本文来自Android菜鸟:http://blog.csdn.net/android_cai_niao/article/details/46854767  QQ:2717521606 ...

  10. layui是什么

    layui是什么 一.总结 一句话总结:初步看起来比amazeui好看一点点.移动端显示看起来效果真心不错.还有即时聊天那个组件下载,感觉真心不错,可以多去看看. 二.Layui 1.简介 经典模块化 ...