Android自定义View学习之圆角图片(圆形图片)
来源:互联网 发布:局域网桌面监控软件 编辑:程序博客网 时间:2024/06/07 03:45
圆形图片的实现方式有很多种,首先我分享下自己所知道的一种实现方式,这种方式的实现对角度的控制很灵活,可以在xml中自由的设置,实现的过程中使用到了PorterDuffXfermode这个类,网络上对PorterDuffXfermode的解释:
类android.graphics.PorterDuffXfermode继承自android.graphics.Xfermode。在用Android中的Canvas进行绘图时,可以通过使用PorterDuffXfermode将所绘制的图形的像素与Canvas中对应位置的像素按照一定规则进行混合,形成新的像素值,从而更新Canvas中最终的像素颜色值,这样会创建很多有趣的效果。当使用PorterDuffXfermode时,需要将其作为参数传给Paint.setXfermode(Xfermode xfermode)方法,这样在用该画笔paint进行绘图时,Android就会使用传入的PorterDuffXfermode,如果不想再使用Xfermode,那么可以执行Paint.setXfermode(null)。
我的理解是canva在绘制俩个图像有重叠时,会以什么样的形式显示出来,只需要取决于你给它传入的什么模式就行了(其中总共16种模式,十六种模式图像网络上也有);PorterDuffXfermode功能挺强大的,想了解可以百度
效果图:
一、该自定义View同样继承ImageView,重写onDraw方法
@Override protected void onDraw(Canvas canvas) { //创建同等大小的位图 Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_4444); //创建带有位图的画布 mCanvas=new Canvas(bitmap); super.onDraw(mCanvas); //绘制矩形内接圆(椭圆)外部分,简单就是去掉的四个角所组成的图形 drawGraphical(); canvas.drawBitmap(bitmap,0,0,mPaintBitmap); }代码中创建了一个带有位图的画布,以参数的形式,通过super.onDraw(mCanvas)传给父类,我的理解是相当于两个画布mCanvas和canvas重叠在一起,mCanvas在上面,各自在自己上面绘制图形,上面的PorterDuffXfermode就使用在mCanvas上,来约束mCanvas绘制显示的区域
private void drawGraphical() { //限制mRadius值的规范性 checkRadius(); //左上 mPath.moveTo(0, mRadius); mPath.lineTo(0, 0); mPath.lineTo(mRadius, 0); //圆弧路径 mPath.arcTo(new RectF(0, 0, mRadius * 2, mRadius * 2), 270, -90); //左下 mPath.moveTo(0, getHeight() - mRadius); mPath.lineTo(0, getHeight()); mPath.lineTo(mRadius, getHeight()); mPath.arcTo(new RectF(0, getHeight() - mRadius * 2, mRadius * 2, getHeight()), 90, 90); //右下 mPath.moveTo(getWidth() - mRadius, getHeight()); mPath.lineTo(getWidth(), getHeight()); mPath.lineTo(getWidth(), getHeight() - mRadius); mPath.arcTo(new RectF(getWidth() - mRadius * 2, getHeight() - mRadius * 2, getWidth(), getHeight()), 0, 90); //右上 mPath.moveTo(getWidth(), mRadius); mPath.lineTo(getWidth(), 0); mPath.lineTo(getWidth() - mRadius, 0); mPath.arcTo(new RectF(getWidth() - mRadius * 2, 0, getWidth(),mRadius * 2), 270, 90); mCanvas.drawPath(mPath, mPaintPath); }绘制需要遮挡的图形区域,moveTo(x,y)从哪个点开始,lineTo(x,y)到哪个点,arcTo(new RectF())绘制圆弧路径,drawPath()根据规定的路径开始绘制,绘制完,大概的样子就是一个矩形去掉内接圆(长和宽相等)剩下的部分就是的了,自己不会画图,自己想象下吧
private void init(Context context, AttributeSet attrs) { TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CornerImageView); mRadius = typedArray.getDimension(R.styleable.CornerImageView_cornerRadius, -1); mPaintBitmap=new Paint(); mPaintBitmap.setAntiAlias(true); mPaintPath=new Paint(); mPaintPath.setAntiAlias(true); mPorterDuffXfermode=new PorterDuffXfermode(PorterDuff.Mode.DST_OUT); mPaintPath.setXfermode(mPorterDuffXfermode); //图形对象 mPath=new Path(); }初始化代码,
PorterDuff.Mode.DST_OUT取底部相交图形之外的部分
二、全部代码
package com.yufs.myimageview.view;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Bitmap;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.Path;import android.graphics.PorterDuff;import android.graphics.PorterDuffXfermode;import android.graphics.RectF;import android.util.AttributeSet;import android.widget.ImageView;import com.yufs.myimageview.R;/** * Created by yufs on 2017/5/22. */public class CornerImageView extends ImageView{ private Canvas mCanvas; private Paint mPaintBitmap;//绘制bitmap的画笔 private Paint mPaintPath;//绘制path的画笔 private Path mPath;//path对象 private float mRadius=0;//圆角弧度 private PorterDuffXfermode mPorterDuffXfermode;// public CornerImageView(Context context) { super(context); init(context, null); } public CornerImageView(Context context, AttributeSet attrs) { this(context,attrs,0); } public CornerImageView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context,attrs); } private void init(Context context, AttributeSet attrs) { TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CornerImageView); mRadius = typedArray.getDimension(R.styleable.CornerImageView_cornerRadius, -1); mPaintBitmap=new Paint(); mPaintBitmap.setAntiAlias(true); mPaintPath=new Paint(); mPaintPath.setAntiAlias(true); mPorterDuffXfermode=new PorterDuffXfermode(PorterDuff.Mode.DST_OUT); mPaintPath.setXfermode(mPorterDuffXfermode); //图形对象 mPath=new Path(); } @Override protected void onDraw(Canvas canvas) { //创建同等大小的位图 Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_4444); //创建带有位图的画布 mCanvas=new Canvas(bitmap); super.onDraw(mCanvas); //绘制矩形内接圆(椭圆)外部分,简单就是去掉的四个角所组成的图形 drawGraphical(); canvas.drawBitmap(bitmap,0,0,mPaintBitmap); } private void drawGraphical() { //限制mRadius值的规范性 checkRadius(); //左上 mPath.moveTo(0, mRadius); mPath.lineTo(0, 0); mPath.lineTo(mRadius, 0); //圆弧路径 mPath.arcTo(new RectF(0, 0, mRadius * 2, mRadius * 2), 270, -90); //左下 mPath.moveTo(0, getHeight() - mRadius); mPath.lineTo(0, getHeight()); mPath.lineTo(mRadius, getHeight()); mPath.arcTo(new RectF(0, getHeight() - mRadius * 2, mRadius * 2, getHeight()), 90, 90); //右下 mPath.moveTo(getWidth() - mRadius, getHeight()); mPath.lineTo(getWidth(), getHeight()); mPath.lineTo(getWidth(), getHeight() - mRadius); mPath.arcTo(new RectF(getWidth() - mRadius * 2, getHeight() - mRadius * 2, getWidth(), getHeight()), 0, 90); //右上 mPath.moveTo(getWidth(), mRadius); mPath.lineTo(getWidth(), 0); mPath.lineTo(getWidth() - mRadius, 0); mPath.arcTo(new RectF(getWidth() - mRadius * 2, 0, getWidth(),mRadius * 2), 270, 90); mCanvas.drawPath(mPath, mPaintPath); } /** * 如果未设置cornerRadius属性,或者设置的非法,默认是圆形 */ private void checkRadius() { float minValues; if(getWidth()>getHeight()){ minValues=getHeight(); }else{ minValues=getWidth(); } if(mRadius>minValues/2||mRadius<0){ mRadius=minValues/2; } }}
attrs文件
<?xml version="1.0" encoding="utf-8"?><resources> <declare-styleable name="CornerImageView"> <attr name="cornerRadius" format="dimension"></attr> </declare-styleable></resources>
xml中使用
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:mimage="http://schemas.android.com/apk/res-auto" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.yufs.myimageview.MainActivity"> <ScrollView android:layout_width="match_parent" android:layout_height="wrap_content"> <LinearLayout android:layout_width="match_parent" android:orientation="vertical" android:gravity="center_horizontal" android:layout_height="wrap_content"> <com.yufs.myimageview.view.CornerImageView android:layout_width="150dp" android:layout_height="50dp" android:layout_marginTop="24dp" android:scaleType="centerCrop" android:src="@mipmap/green" mimage:cornerRadius="12dp" /> <com.yufs.myimageview.view.CornerImageView android:layout_width="90dp" android:layout_height="90dp" android:layout_marginTop="12dp" android:scaleType="centerCrop" android:src="@mipmap/green" /> <com.yufs.myimageview.view.CornerImageView android:layout_width="90dp" android:layout_height="90dp" android:layout_marginTop="12dp" android:scaleType="centerCrop" mimage:cornerRadius="12dp" android:src="@mipmap/green" /> <com.yufs.myimageview.view.CornerImageView android:layout_width="120dp" android:layout_height="45dp" android:layout_marginTop="12dp" android:scaleType="centerCrop" android:src="@mipmap/green" /> </LinearLayout> </ScrollView></RelativeLayout>
使用自定义属性时别忘记在顶部加入声明
xmlns:mimage="http://schemas.android.com/apk/res-auto"mimage名字随意
green是一张图片,你可以用自己的演示看看,有什么问题,或者我说的有哪不对的,希望大神帮忙指点下,谢谢
阅读全文
0 0
- Android自定义View学习之圆角图片(圆形图片)
- Android自定义View之圆形图片--RoundImageView
- Android自定义view圆形图片
- 自定义view圆形图片
- 自定义View实现Android圆形图片
- Android开发旋转圆形图片自定义View
- Android自定义圆形和圆角图片
- Android自定义圆形圆角图片示例
- 自定义View(1)--圆形图片、圆角图片的实现
- Android自定义控件之自定义圆形图片和圆角图片
- [AndroidUI]自定义view(四):实现圆形圆角图片
- Android Drawable 自定义(圆角图片和圆形图片)
- android 自定义圆形图片与图片圆角
- Android使用BitmapShader图形渲染实现圆形、圆角和椭圆自定义图片View
- Android自定义圆形图片
- Android自定义圆形图片
- Android自定义圆形图片
- Android自定义圆形图片
- 用enum还是Constants?
- jsonp详解
- Code::Blocks导出MakeFile文件工具
- C# DataGridView运用
- Others4_京东联盟(京享街)与京东购物返利
- Android自定义View学习之圆角图片(圆形图片)
- 排序算法总结(9)--基数排序
- 编译安装Ambari2.5.0
- LeetCode 258. Add Digits (int转string)
- 读取字节太多导致STM32读取TF错误
- 不输入密码ssh直接登录Linux主机的实践与总结
- top-1 recall precise解释
- HDU2571(dp)
- C++ using namespace std 详解 与 命名空间的使用