zoukankan      html  css  js  c++  java
  • Android圆形图片不求人,自定义View实现(BitmapShader使用)

    在很多APP当中,圆形的图片是必不可少的元素,美观大方。本文将带领读者去实现一个圆形图片自定View,力求只用一个Java类来完成这件事情。

    一、先上效果图

    二、实现思路

    • 在定义View 的onMeasure()方法里设置View的宽高相等,应该取宽高中的最小值。
    • 在自定义View的onDraw()里面使用画笔paint结合BitmapShaper画出一个圆形区域。
    • 上述两步已经可以实现一个圆形图片,但是如果图片大于View的设定的宽高,则只会绘制左上角的局域,内容显示不完全(如下图)。因此,还应该做好图片的缩放。

    三、具体实现

    1.新建一个java类 CircleImageView继承 ImageView,这个是完整的代码。

    public class CircleImageView extends ImageView {
    
        private Paint mPaint; //画笔
    
        private int mRadius; //圆形图片的半径
    
        private float mScale; //图片的缩放比例
    
        public CircleImageView(Context context) {
            super(context);
        }
    
        public CircleImageView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public CircleImageView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            //因为是圆形图片,所以应该让宽高保持一致
            int size = Math.min(getMeasuredWidth(), getMeasuredHeight());
            mRadius = size / 2;
    
            setMeasuredDimension(size, size);
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
    
            mPaint = new Paint();
            Bitmap bitmap = drawableToBitmap(getDrawable());
    
            //初始化BitmapShader,传入bitmap对象
            BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
    
            //计算缩放比例
            mScale = (mRadius * 2.0f) / Math.min(bitmap.getHeight(), bitmap.getWidth());
    
            Matrix matrix = new Matrix();
            matrix.setScale(mScale, mScale);
            bitmapShader.setLocalMatrix(matrix);
    
    
            mPaint.setShader(bitmapShader);
    
            //画圆形,指定好中心点坐标、半径、画笔
            canvas.drawCircle(mRadius, mRadius, mRadius, mPaint);
        }
    
        //写一个drawble转BitMap的方法
        private Bitmap drawableToBitmap(Drawable drawable) {
            if (drawable instanceof BitmapDrawable) {
                BitmapDrawable bd = (BitmapDrawable) drawable;
                return bd.getBitmap();
            }
            int w = drawable.getIntrinsicWidth();
            int h = drawable.getIntrinsicHeight();
            Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
            Canvas canvas = new Canvas(bitmap);
            drawable.setBounds(0, 0, w, h);
            drawable.draw(canvas);
            return bitmap;
        }
    }

    2. onMeasure()方法里面,计算好宽高

    因为是圆形图片,所以应该让宽高保持一致,取测量尺寸宽高中的最小值最为最终结果。

    @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            //因为是圆形图片,所以应该让宽高保持一致
            int size = Math.min(getMeasuredWidth(), getMeasuredHeight());
            mRadius = size / 2;
    
            setMeasuredDimension(size, size);
        }

    3. onDraw()方法里面画出圆形图片,注意看注释,很详细。

    @Override
        protected void onDraw(Canvas canvas) {
    
            mPaint = new Paint();
            Bitmap bitmap = drawableToBitmap(getDrawable());
    
            //初始化BitmapShader,传入bitmap对象
            BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
    
            //计算缩放比例
            mScale = (mRadius * 2.0f) / Math.min(bitmap.getHeight(), bitmap.getWidth());
    
            Matrix matrix = new Matrix();
            matrix.setScale(mScale, mScale);
            bitmapShader.setLocalMatrix(matrix);
    
    
            mPaint.setShader(bitmapShader);
    
            //画圆形,指定好中心点坐标、半径、画笔
            canvas.drawCircle(mRadius, mRadius, mRadius, mPaint);
        }

    4. 上一步中的将drwable转换为bitmap的方法。

    //写一个drawble转BitMap的方法
        private Bitmap drawableToBitmap(Drawable drawable) {
            if (drawable instanceof BitmapDrawable) {
                BitmapDrawable bd = (BitmapDrawable) drawable;
                return bd.getBitmap();
            }
            int w = drawable.getIntrinsicWidth();
            int h = drawable.getIntrinsicHeight();
            Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
            Canvas canvas = new Canvas(bitmap);
            drawable.setBounds(0, 0, w, h);
            drawable.draw(canvas);
            return bitmap;
        }

    四、使用该自定义View

    1. 布局文件里面使用,此处使用了斯嘉丽的美图

    <?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="com.roundimage.MainActivity"
        >
    
        <com.roundimage.CircleImageView
            android:id="@+id/image1"
            android:layout_width="200dp"
            android:layout_height="200dp"
            android:layout_centerInParent="true"
            android:scaleType="centerCrop"
            android:src="@drawable/beauty"
            />
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@+id/image1"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="10dp"
            android:text="斯嘉丽·约翰逊"
            android:textColor="#333333"
            android:textSize="17sp"
            />
    </RelativeLayout>

    2. 各种效果图,用于验证适应性

    • 尺寸都指定为200dp
    android:layout_width="200dp"
       android:layout_height="200dp"

    • 尺寸都指定为100dp
    android:layout_width="100dp"
       android:layout_height="100dp"

    • 尺寸都指定不一样,一个150,一个400
    android:layout_width="100dp"
       android:layout_height="200dp"

    • 尺寸设定为wrap_content
    android:layout_width="wrap_content"
      android:layout_height="wrap_content"

    五、总结

    实现圆形图片有很多种方法:

    • 可以使用一些开源框架如Fresco,这个可以参考本人的另一篇博客 Fresco图片框架简介及使用

    • 笨办法,让视觉给到一张圆形图片(如果每张图都需要处理,可能她会打死你)

    • 笨办法,用一个view在上面挡住(这个我写的自己都笑了)

    • 自定义View,就如本文介绍的。

    • 自定义Drawble,这个和自定义view可以相互补充。

    总之,通过以上各个不同属性验证,可以发现本文的自定义View完美的实现了圆形图片。如果读者有需要圆形图的,可以把这个copy一下自己用,就一个类,简单精巧。

    如果觉得本文对你有帮助,请关注、留言、点赞我,谢谢!

    来自:http://www.jianshu.com/p/6b5eef0f6f3d

  • 相关阅读:
    SQL Server Audit监控触发器状态
    SQL Server 数据变更时间戳(timestamp)在复制中的运用
    SQL Server 更改跟踪(Chang Tracking)监控表数据
    SQL Server 变更数据捕获(CDC)监控表数据
    SQL Server 事件通知(Event notifications)
    SQL Server 堆表行存储大小(Record Size)
    SQL Server DDL触发器运用
    SQL Server 默认跟踪(Default Trace)
    SQL Server 创建数据库邮件
    SQL Server 跨网段(跨机房)FTP复制
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/6722720.html
Copyright © 2011-2022 走看看