Android中设置图片的圆形遮罩的几种方式
来源:互联网 发布:光纤网络监控方案 编辑:程序博客网 时间:2024/05/16 15:48
编写不易,如有转载,请声明出处: 梦回河口:http://blog.csdn.net/zxc514257857/article/details/63834235
方式一 采用paint.setXfermode() 设置一个简单的圆形遮罩
效果图如下:
布局代码如下:
//(layout)activity_main.xml<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" > <ImageView android:id="@+id/imageview" android:src="@mipmap/pic" android:layout_width="wrap_content" android:layout_height="wrap_content"/></RelativeLayout>
Activity代码如下:
//(activity)MainActivityimport android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.PorterDuff;import android.graphics.PorterDuffXfermode;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.widget.ImageView;public class MainActivity extends AppCompatActivity { private ImageView mImageview; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); initData(); } private void initView() { mImageview = (ImageView) findViewById(R.id.imageview); } private void initData() { //原图 Bitmap before = BitmapFactory.decodeResource(getResources(), R.mipmap.pic); //遮罩图 Bitmap shade = BitmapFactory.decodeResource(getResources(), R.mipmap.circle); //遮罩后图 Bitmap after = Bitmap.createBitmap(shade.getWidth(), shade.getHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(after); Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); //关键代码 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN)); canvas.drawBitmap(before, 0, 0, null); canvas.drawBitmap(shade, 0, 0, paint); paint.setXfermode(null); mImageview.setImageBitmap(after); mImageview.setScaleType(ImageView.ScaleType.CENTER); }}
注:如果要改变圆形图片的大小,需要修改遮罩图的分辨率大小,原图大小也要相应改变
Demo下载请移步:http://download.csdn.net/detail/zxc514257857/9833165
方式二 如果是从网络上加载出来的图片,可以使用图片加载框架中封装的方法轻松实现圆形遮罩效果
//例如Glide:Context context = MainActivity.this;String url = (String)list.get(1);ImageView pic = (ImageView)findViewById(R.id.pic);Glide.with(context).load(url).asBitmap().diskCacheStrategy(DiskCacheStrategy.ALL).centerCrop().into(new BitmapImageViewTarget(pic) { @Override protected void setResource(Bitmap resource) { RoundedBitmapDrawable circularBitmapDrawable = RoundedBitmapDrawableFactory.create(getResources(), resource); circularBitmapDrawable.setCircular(true); pic.setImageDrawable(circularBitmapDrawable); }});
方式三 鸿神的两种实现方法
自定义View实现:
http://blog.csdn.net/lmj623565791/article/details/24555655
使用BitmapShader实现:
http://blog.csdn.net/lmj623565791/article/details/41967509
方式四 使用自定义的ImageView
效果图如下:
自定义ImageView代码如下:
//CustomRoundViewimport android.content.Context;import android.content.res.TypedArray;import android.graphics.Bitmap;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.PorterDuff;import android.graphics.PorterDuffXfermode;import android.graphics.Rect;import android.graphics.drawable.BitmapDrawable;import android.graphics.drawable.Drawable;import android.graphics.drawable.NinePatchDrawable;import android.util.AttributeSet;import android.widget.ImageView;public class CustomRoundView extends ImageView{ private int mBorderThickness = 0; private Context mContext; private int defaultColor = 0xFFFFFFFF; // 如果只有其中一个有值,则只画一个圆形边框 private int mBorderOutsideColor = 0; private int mBorderInsideColor = 0; // 控件默认长、宽 private int defaultWidth = 0; private int defaultHeight = 0; public CustomRoundView(Context context) { super(context); mContext = context; } public CustomRoundView(Context context, AttributeSet attrs) { super(context, attrs); mContext = context; setCustomAttributes(attrs); } public CustomRoundView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); mContext = context; setCustomAttributes(attrs); } private void setCustomAttributes(AttributeSet attrs) { TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.roundview); mBorderThickness = a.getDimensionPixelSize( R.styleable.roundview_border_thickness, 0); mBorderOutsideColor = a .getColor(R.styleable.roundview_border_outside_color, defaultColor); mBorderInsideColor = a.getColor( R.styleable.roundview_border_inside_color, defaultColor); } @Override protected void onDraw(Canvas canvas) { Drawable drawable = getDrawable(); if (drawable == null) { return; } if (getWidth() == 0 || getHeight() == 0) { return; } this.measure(0, 0); if (drawable.getClass() == NinePatchDrawable.class) return; Bitmap b = ((BitmapDrawable) drawable).getBitmap(); Bitmap bitmap = b.copy(Bitmap.Config.ARGB_8888, true); if (defaultWidth == 0) { defaultWidth = getWidth(); } if (defaultHeight == 0) { defaultHeight = getHeight(); } int radius = 0; if (mBorderInsideColor != defaultColor && mBorderOutsideColor != defaultColor) { // 定义画两个边框,分别为外圆边框和内圆边框 radius = (defaultWidth < defaultHeight ? defaultWidth : defaultHeight) / 2 - 2 * mBorderThickness; // 画内圆 drawCircleBorder(canvas, radius + mBorderThickness / 2, mBorderInsideColor); // 画外圆 drawCircleBorder(canvas, radius + mBorderThickness + mBorderThickness / 2, mBorderOutsideColor); } else if (mBorderInsideColor != defaultColor && mBorderOutsideColor == defaultColor) { // 定义画一个边框 radius = (defaultWidth < defaultHeight ? defaultWidth : defaultHeight) / 2 - mBorderThickness; drawCircleBorder(canvas, radius + mBorderThickness / 2, mBorderInsideColor); } else if (mBorderInsideColor == defaultColor && mBorderOutsideColor != defaultColor) { // 定义画一个边框 radius = (defaultWidth < defaultHeight ? defaultWidth : defaultHeight) / 2 - mBorderThickness; drawCircleBorder(canvas, radius + mBorderThickness / 2, mBorderOutsideColor); } else { // 没有边框 radius = (defaultWidth < defaultHeight ? defaultWidth : defaultHeight) / 2; } Bitmap roundBitmap = getCroppedRoundBitmap(bitmap, radius); canvas.drawBitmap(roundBitmap, defaultWidth / 2 - radius, defaultHeight / 2 - radius, null); } // 获取裁剪后的圆形图片 public Bitmap getCroppedRoundBitmap(Bitmap bmp, int radius) { Bitmap scaledSrcBmp; int diameter = radius * 2; // 为了防止宽高不相等,造成圆形图片变形,因此截取长方形中处于中间位置最大的正方形图片 int bmpWidth = bmp.getWidth(); int bmpHeight = bmp.getHeight(); int squareWidth = 0, squareHeight = 0; int x = 0, y = 0; Bitmap squareBitmap; if (bmpHeight > bmpWidth) { // 高大于宽 squareWidth = squareHeight = bmpWidth; x = 0; y = (bmpHeight - bmpWidth) / 2; // 截取正方形图片 squareBitmap = Bitmap.createBitmap(bmp, x, y, squareWidth, squareHeight); } else if (bmpHeight < bmpWidth) { // 宽大于高 squareWidth = squareHeight = bmpHeight; x = (bmpWidth - bmpHeight) / 2; y = 0; squareBitmap = Bitmap.createBitmap(bmp, x, y, squareWidth, squareHeight); } else { squareBitmap = bmp; } if (squareBitmap.getWidth() != diameter || squareBitmap.getHeight() != diameter) { scaledSrcBmp = Bitmap.createScaledBitmap(squareBitmap, diameter, diameter, true); } else { scaledSrcBmp = squareBitmap; } Bitmap output = Bitmap.createBitmap(scaledSrcBmp.getWidth(), scaledSrcBmp.getHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(output); Paint paint = new Paint(); Rect rect = new Rect(0, 0, scaledSrcBmp.getWidth(), scaledSrcBmp.getHeight()); paint.setAntiAlias(true); paint.setFilterBitmap(true); paint.setDither(true); canvas.drawARGB(0, 0, 0, 0); canvas.drawCircle(scaledSrcBmp.getWidth() / 2, scaledSrcBmp.getHeight() / 2, scaledSrcBmp.getWidth() / 2, paint); paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); canvas.drawBitmap(scaledSrcBmp, rect, rect, paint); bmp = null; squareBitmap = null; scaledSrcBmp = null; return output; } //边缘画圆 private void drawCircleBorder(Canvas canvas, int radius, int color) { Paint paint = new Paint(); //去锯齿 paint.setAntiAlias(true); paint.setFilterBitmap(true); paint.setDither(true); paint.setColor(color); //设置paint的 style 为STROKE:空心 paint.setStyle(Paint.Style.STROKE); //设置paint的外框宽度 paint.setStrokeWidth(mBorderThickness); canvas.drawCircle(defaultWidth / 2, defaultHeight / 2, radius, paint); }}
布局代码如下:
//(layout)activity_main.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" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <com.test.customroundview.CustomRoundView android:src="@mipmap/pic" android:id="@+id/roundview" android:layout_width="200dp" android:layout_height="200dp"/></RelativeLayout>-----------------------------------------------------------//(values)attrs.xml<?xml version="1.0" encoding="utf-8"?><resources> <declare-styleable name="roundview"> <attr name="border_thickness" format="dimension" /> <attr name="border_inside_color" format="color" /> <attr name="border_outside_color" format="color"/> </declare-styleable></resources>-----------------------------------------------------------
Activity代码如下:
//MainActivityimport android.support.v7.app.AppCompatActivity;import android.os.Bundle;public class MainActivity extends AppCompatActivity { //截取长方形中处于中间位置最大的正方形图片,只要头像处于图片中间不要太偏就可以很好的截出效果 private CustomRoundView mRoundView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); initData(); } private void initView(){ mRoundView = (CustomRoundView) findViewById(R.id.roundview); } private void initData(){ mRoundView.setImageResource(R.mipmap.pic); }}
注:如果要改变圆形图片的大小,修改:
<com.test.customroundview.CustomRoundView android:src="@mipmap/pic" android:id="@+id/roundview" android:layout_width="XXXdp" android:layout_height="XXXdp"/>
Demo下载请移步:http://download.csdn.net/detail/zxc514257857/9833264
方式五 CircleImageView (也是自定义View 经常和Glide搭配使用)
效果图如下:
自定义ImageView代码如下:
//(view)CircleImageViewimport android.content.Context;import android.content.res.TypedArray;import android.graphics.Bitmap;import android.graphics.BitmapShader;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.ColorFilter;import android.graphics.Matrix;import android.graphics.Paint;import android.graphics.RectF;import android.graphics.Shader;import android.graphics.drawable.BitmapDrawable;import android.graphics.drawable.ColorDrawable;import android.graphics.drawable.Drawable;import android.net.Uri;import android.support.annotation.DrawableRes;import android.util.AttributeSet;import android.widget.ImageView;import com.test.circleimageview.R;public class CircleImageView extends ImageView { private static final ScaleType SCALE_TYPE = ScaleType.CENTER_CROP; private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888; private static final int COLORDRAWABLE_DIMENSION = 2; private static final int DEFAULT_BORDER_WIDTH = 0; private static final int DEFAULT_BORDER_COLOR = Color.BLACK; private static final int DEFAULT_FILL_COLOR = Color.TRANSPARENT; private static final boolean DEFAULT_BORDER_OVERLAY = false; private final RectF mDrawableRect = new RectF(); private final RectF mBorderRect = new RectF(); private final Matrix mShaderMatrix = new Matrix(); private final Paint mBitmapPaint = new Paint(); private final Paint mBorderPaint = new Paint(); private final Paint mFillPaint = new Paint(); private int mBorderColor = DEFAULT_BORDER_COLOR; private int mBorderWidth = DEFAULT_BORDER_WIDTH; private int mFillColor = DEFAULT_FILL_COLOR; private Bitmap mBitmap; private BitmapShader mBitmapShader; private int mBitmapWidth; private int mBitmapHeight; private float mDrawableRadius; private float mBorderRadius; private ColorFilter mColorFilter; private boolean mReady; private boolean mSetupPending; private boolean mBorderOverlay; public CircleImageView(Context context) { super(context); init(); } public CircleImageView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public CircleImageView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView, defStyle, 0); mBorderWidth = a.getDimensionPixelSize(R.styleable.CircleImageView_civ_border_width, DEFAULT_BORDER_WIDTH); mBorderColor = a.getColor(R.styleable.CircleImageView_civ_border_color, DEFAULT_BORDER_COLOR); mBorderOverlay = a.getBoolean(R.styleable.CircleImageView_civ_border_overlay, DEFAULT_BORDER_OVERLAY); mFillColor = a.getColor(R.styleable.CircleImageView_civ_fill_color, DEFAULT_FILL_COLOR); a.recycle(); init(); } private void init() { super.setScaleType(SCALE_TYPE); mReady = true; if (mSetupPending) { setup(); mSetupPending = false; } } @Override public ScaleType getScaleType() { return SCALE_TYPE; } @Override public void setScaleType(ScaleType scaleType) { if (scaleType != SCALE_TYPE) { throw new IllegalArgumentException(String.format("ScaleType %s not supported.", scaleType)); } } @Override public void setAdjustViewBounds(boolean adjustViewBounds) { if (adjustViewBounds) { throw new IllegalArgumentException("adjustViewBounds not supported."); } } @Override protected void onDraw(Canvas canvas) { if (mBitmap == null) { return; } if (mFillColor != Color.TRANSPARENT) { canvas.drawCircle(getWidth() / 2.0f, getHeight() / 2.0f, mDrawableRadius, mFillPaint); } canvas.drawCircle(getWidth() / 2.0f, getHeight() / 2.0f, mDrawableRadius, mBitmapPaint); if (mBorderWidth != 0) { canvas.drawCircle(getWidth() / 2.0f, getHeight() / 2.0f, mBorderRadius, mBorderPaint); } } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); setup(); } public int getBorderColor() { return mBorderColor; } public int getFillColor() { return mFillColor; } public int getBorderWidth() { return mBorderWidth; } public void setBorderWidth(int borderWidth) { if (borderWidth == mBorderWidth) { return; } mBorderWidth = borderWidth; setup(); } public boolean isBorderOverlay() { return mBorderOverlay; } public void setBorderOverlay(boolean borderOverlay) { if (borderOverlay == mBorderOverlay) { return; } mBorderOverlay = borderOverlay; setup(); } @Override public void setImageBitmap(Bitmap bm) { super.setImageBitmap(bm); mBitmap = bm; setup(); } @Override public void setImageDrawable(Drawable drawable) { super.setImageDrawable(drawable); mBitmap = getBitmapFromDrawable(drawable); setup(); } @Override public void setImageResource(@DrawableRes int resId) { super.setImageResource(resId); mBitmap = getBitmapFromDrawable(getDrawable()); setup(); } @Override public void setImageURI(Uri uri) { super.setImageURI(uri); mBitmap = uri != null ? getBitmapFromDrawable(getDrawable()) : null; setup(); } @Override public void setColorFilter(ColorFilter cf) { if (cf == mColorFilter) { return; } mColorFilter = cf; mBitmapPaint.setColorFilter(mColorFilter); invalidate(); } private Bitmap getBitmapFromDrawable(Drawable drawable) { if (drawable == null) { return null; } if (drawable instanceof BitmapDrawable) { return ((BitmapDrawable) drawable).getBitmap(); } try { Bitmap bitmap; if (drawable instanceof ColorDrawable) { bitmap = Bitmap.createBitmap(COLORDRAWABLE_DIMENSION, COLORDRAWABLE_DIMENSION, BITMAP_CONFIG); } else { bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), BITMAP_CONFIG); } Canvas canvas = new Canvas(bitmap); drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); drawable.draw(canvas); return bitmap; } catch (Exception e) { e.printStackTrace(); return null; } } private void setup() { if (!mReady) { mSetupPending = true; return; } if (getWidth() == 0 && getHeight() == 0) { return; } if (mBitmap == null) { invalidate(); return; } mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); mBitmapPaint.setAntiAlias(true); mBitmapPaint.setShader(mBitmapShader); mBorderPaint.setStyle(Paint.Style.STROKE); mBorderPaint.setAntiAlias(true); mBorderPaint.setColor(mBorderColor); mBorderPaint.setStrokeWidth(mBorderWidth); mFillPaint.setStyle(Paint.Style.FILL); mFillPaint.setAntiAlias(true); mFillPaint.setColor(mFillColor); mBitmapHeight = mBitmap.getHeight(); mBitmapWidth = mBitmap.getWidth(); mBorderRect.set(0, 0, getWidth(), getHeight()); mBorderRadius = Math.min((mBorderRect.height() - mBorderWidth) / 2.0f, (mBorderRect.width() - mBorderWidth) / 2.0f); mDrawableRect.set(mBorderRect); if (!mBorderOverlay) { mDrawableRect.inset(mBorderWidth, mBorderWidth); } mDrawableRadius = Math.min(mDrawableRect.height() / 2.0f, mDrawableRect.width() / 2.0f); updateShaderMatrix(); invalidate(); } private void updateShaderMatrix() { float scale; float dx = 0; float dy = 0; mShaderMatrix.set(null); if (mBitmapWidth * mDrawableRect.height() > mDrawableRect.width() * mBitmapHeight) { scale = mDrawableRect.height() / (float) mBitmapHeight; dx = (mDrawableRect.width() - mBitmapWidth * scale) * 0.5f; } else { scale = mDrawableRect.width() / (float) mBitmapWidth; dy = (mDrawableRect.height() - mBitmapHeight * scale) * 0.5f; } mShaderMatrix.setScale(scale, scale); mShaderMatrix.postTranslate((int) (dx + 0.5f) + mDrawableRect.left, (int) (dy + 0.5f) + mDrawableRect.top); mBitmapShader.setLocalMatrix(mShaderMatrix); }}
布局代码如下:
//(layout)activity_main.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" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".activity.MainActivity"> <com.test.circleimageview.view.CircleImageView android:id="@+id/imageView" android:layout_width="200dp" android:layout_height="200dp"/></RelativeLayout>-----------------------------------------------------------//(values)attrs.xml<resources> <declare-styleable name="CircleImageView"> <attr name="civ_border_width" format="dimension" /> <attr name="civ_border_color" format="color" /> <attr name="civ_border_overlay" format="boolean" /> <attr name="civ_fill_color" format="color" /> </declare-styleable></resources>
Activity代码如下:
//(activity)MainActivityimport android.os.Bundle;import android.support.v7.app.AppCompatActivity;import com.test.circleimageview.R;import com.test.circleimageview.view.CircleImageView;public class MainActivity extends AppCompatActivity { private CircleImageView mImageView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); initData(); } private void initView() { mImageView = (CircleImageView) findViewById(R.id.imageView); } private void initData(){ mImageView.setImageResource(R.mipmap.pic); }}
注:如果要改变圆形图片的大小,修改:
<com.test.circleimageview.view.CircleImageView android:id="@+id/imageView" android:layout_width="XXXdp" android:layout_height="XXXdp"/>
Demo下载请移步:http://download.csdn.net/detail/zxc514257857/9833756
———-因本人才疏学浅,如博客或Demo中有错误的地方请大家随意指出,与大家一起讨论,共同进步,谢谢!———-
- Android中设置图片的圆形遮罩的几种方式
- 画圆形图片的几种方式
- Android中圆形图的几种实现方式
- Android中圆形图的几种实现方式
- 在android中画圆形图片的几种办法
- 在android中画圆形图片的几种办法
- 在android中画圆形图片的几种办法
- 在android中画圆形图片的几种办法
- Android中获取圆角图片和圆形图片的三种方式
- Android 实现圆形图片的几种方法
- ImageView设置图片的几种方式
- android中设置圆形图片
- Android 中获取图片资源的几种方式
- Android中设置颜色的几种方式
- Android中设置Activity全屏的几种方式
- ImageView设置图片的几种方式、图片的ScaleType
- Android绘制图片的几种方式
- Android图片压缩的几种方式
- Firebase Cloud Messaging接入文档
- 新闻案例本地版(listview实现)
- 反射小例and可变参数
- 多线程编程实例
- 设计模式之策略模式
- Android中设置图片的圆形遮罩的几种方式
- 事件处理(Handling Events)和委托(Delegate)代码示例(一)【UE4】【C++】
- php和python请求socket服务器
- PHP的用法
- gnome-calculator TLS support is not available
- MD5+DES在C#.NET与Java/Android中的加解密使用
- IO流输入输出增强
- python爬虫--scrapy 框架 之 项目外运行爬虫(用脚本运行爬虫)
- 《ACM程序设计》书中题目 Z