个人博客

http://www.milovetingting.cn

Android自定义View-圆形图片控件

前言

在日常开发中,圆形的图片效果还是很常见的。可以通过给Paint设置Xfermode来实现,这里简单记录如下。

实现

实现圆形效果的核心是PorterDuffXfermode,对于PorterDuffXfermode,这里不展开,可以查询相关资料。

核心代码

//绘制背景canvas.drawCircle(mSize / 2, mSize / 2, mSize / 2, mPaint);//设置模式为:显示背景层和上层的交集,且显示上层图像mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));//绘制要显示的图像canvas.drawBitmap(mSrcBitmap, 0, 0, mPaint);//重置XfermodemPaint.setXfermode(null);

自定义属性

<?xml version="1.0" encoding="utf-8"?><resources>    <declare-styleable name="CircleView">                <attr name="src" format="reference" />                <attr name="type" format="enum">                        <enum name="round" value="1" />                        <enum name="rect" value="2" />        attr>    declare-styleable>resources>

自定义控件

public class CircleView extends View {    private static final int DEFAULT_SIZE = 200;    private static final int DEFAULT_RADIUS = 20;    private static final int TYPE_ROUND = 1;    private static final int TYPE_RECT = 2;    private int mSize;    private int mResourceId;    private int mType;    private Paint mPaint;    private Bitmap mSrcBitmap;    public CircleView(Context context) {        this(context, null);    }    public CircleView(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public CircleView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CircleView);        mResourceId = ta.getResourceId(R.styleable.CircleView_src, R.mipmap.ic_launcher);        mType = ta.getInt(R.styleable.CircleView_type, TYPE_ROUND);        ta.recycle();        init();    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        int width = getMeasureSize(widthMeasureSpec);        int height = getMeasureSize(heightMeasureSpec);        mSize = Math.min(width, height);        setMeasuredDimension(mSize, mSize);    }    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        //绘制背景        if (mSrcBitmap == null) {            mSrcBitmap = getScaleBitmap();        }        if (mType == TYPE_ROUND) {            canvas.drawCircle(mSize / 2, mSize / 2, mSize / 2, mPaint);        } else if (mType == TYPE_RECT) {            canvas.drawRoundRect(0, 0, mSize, mSize, DEFAULT_RADIUS, DEFAULT_RADIUS, mPaint);        }        //设置模式为:显示背景层和上层的交集,且显示上层图像        mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));        //绘制要显示的图像        canvas.drawBitmap(mSrcBitmap, 0, 0, mPaint);        //重置Xfermode        mPaint.setXfermode(null);    }    private void init() {        //禁用硬件加速,否则可能无法绘制圆形        setLayerType(LAYER_TYPE_HARDWARE, null);        mPaint = new Paint();        mPaint.setAntiAlias(true);        mPaint.setStyle(Paint.Style.FILL);    }    private int getMeasureSize(int measureSpec) {        int mode = MeasureSpec.getMode(measureSpec);        int size = MeasureSpec.getSize(measureSpec);        return mode == MeasureSpec.EXACTLY ? size : DEFAULT_SIZE;    }    /**     * 获取缩放后的Bitmap     *     * @return     */    private Bitmap getScaleBitmap() {        BitmapFactory.Options options = new BitmapFactory.Options();        options.inJustDecodeBounds = true;        BitmapFactory.decodeResource(getResources(), mResourceId, options);        options.inSampleSize = calcSampleSize(options, mSize, mSize);        options.inJustDecodeBounds = false;        return BitmapFactory.decodeResource(getResources(), mResourceId, options);    }    /**     * 计算缩放比例     *     * @param option     * @param width     * @param height     * @return     */    private int calcSampleSize(BitmapFactory.Options option, int width, int height) {        int originWidth = option.outWidth;        int originHeight = option.outHeight;        int sampleSize = 1;        while ((originWidth = originWidth >> 1) > width && (originHeight = originHeight >> 1) > height) {            sampleSize = sampleSize << 1;        }        return sampleSize;    }}

注意:如果没有圆形的效果,那么可能需要禁用硬件加速:setLayerType(LAYER_TYPE_HARDWARE, null)

布局

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:gravity="center_horizontal"    android:orientation="vertical"    tools:context=".MainActivity">    <com.wangyz.custom.CircleView        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_margin="10dp"        app:src="@drawable/image" />    <com.wangyz.custom.CircleView        android:layout_width="100dp"        android:layout_height="100dp"        android:layout_margin="10dp"        app:src="@drawable/image" />    <com.wangyz.custom.CircleView        android:layout_width="100dp"        android:layout_height="100dp"        android:layout_margin="10dp"        app:src="@drawable/image"        app:type="rect" />LinearLayout>

效果

更多相关文章

  1. Android修改百度地图的显示范围的大小
  2. android 图片处理(截取,缩放)
  3. 通过GridView仿微信动态添加本地图片
  4. Android(安卓)显示SVG格式图片
  5. android 关于Toast重复显示解决方法
  6. Android控件之文本控件---TextView 两种效果+SpannableString
  7. Android(安卓)ApiDemos示例解析(128):Views->Layout Animation->
  8. Android(安卓)ViewRootImpl 解析
  9. Cordova各个插件使用介绍系列(七)—$cordovaStatusbar手机状态栏显

随机推荐

  1. Android性能测试工具:Emmagee
  2. 再谈Android的许可证(续)
  3. Android程序安装后图标不显示
  4. Android中分页滑动实现总结
  5. Android(安卓)启动性能优化 - kernel篇
  6. 加快Android离线文档的访问速度
  7. android离开一个页面时关闭子线程
  8. 转换 iOS 用户界面到 Android(安卓)的 5
  9. 从初学android到现在每天收入50块,收入还
  10. android平台yuv缩放相关