分享一个超好用的圆形imageview自定义组件

近来无聊,写了一个圆形imageview组件

这组件的优点在于可以自动屏幕适配压缩图片,极大节省占用内存,并且可以在xml中动态设置图片模糊程度,要让图片以多高清晰度显示由你决定

效果如下:

这里写图片描述

从上到下分别设置了清晰度1, 4, 8,可以看出他们直接清晰度有很大区别

而从内存上来说:

直接显示原图内存是:

这里写图片描述

而用我的imageview压缩处理之后,内存是:

这里写图片描述

好啦,吹了这么多,话不多说,下面贴上源代码

首先,现在你的工程的res目录下的values创建一个attrs文件,内容如下:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="circleImageView">
        <attr name="imageSrc" format="reference"/>
        <attr name="inSampleSize" format="integer"/>
    </declare-styleable>
</resources>

上面那些是xml的属性,一个是获取图片id,相当于imageview的src,一个是设置图片清晰度,1是不变,越大只是清晰度越小

下面是自定义组件的源码:

package com.example.administrator.testmyidea.myTextView;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.*;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import com.example.administrator.testmyidea.R;

public class circleImageView extends View{
    private Paint mPaint;
    private Bitmap imageBitmap;
    private float circleRadio;
    private int imageResourceId;
    private int mInSampleSize=1;
    private int mWidth;
    public circleImageView(Context context,int width) {
        super(context);
        mPaint=new Paint();
        mWidth=width;
    }

    public circleImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        System.out.println("圆的历程"+"circleImageView");
        mPaint=new Paint();
        TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.circleImageView, 0, 0);
        System.out.println("imageResourceId="+imageResourceId);
        int n = a.getIndexCount();
        for (int i = 0; i < n; i++)
        {
            int attr = a.getIndex(i);
            switch (attr)
            {
                //获取图片id
                case R.styleable.circleImageView_imageSrc:
                    imageResourceId=a.getResourceId(attr,R.drawable.moren);
                    break;
                //获取图片清晰度设置
                case R.styleable.circleImageView_inSampleSize:
                    mInSampleSize=a.getInteger(attr,1);
                    break;
            }
        }
        a.recycle();
        if(imageResourceId==0)imageResourceId=R.drawable.moren;
    }
    @Override
    protected void onDraw(Canvas canvas) {
        System.out.println("圆的历程"+"onDraw");
        canvas.drawBitmap(imageBitmap,0,0,mPaint);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        mWidth=widthSize;
        if(imageBitmap==null||imageBitmap.isRecycled()){
            System.out.println("圆的历程"+"imageBitmap");
            imageBitmap=getCircle(getSampleBitmap2(imageResourceId,widthSize));
        }
        setMeasuredDimension(widthSize, heightSize);
        System.out.println("圆的历程"+"onMeasure");
    }

    //动态设置图片
    public void setImageid(int imageid){
        System.out.println("圆的历程"+"setImageid");
        if(mWidth==0)imageResourceId=imageid;
        else{
            imageResourceId=imageid;
            if(!imageBitmap.isRecycled()){
                imageBitmap.recycle();
                imageBitmap=null;
            }
            imageBitmap=getCircle(getSampleBitmap2(imageResourceId,mWidth));
            postInvalidate();
        }
    }

    //动态设置图片清晰度
    public void setSimpleSize(int size){
        System.out.println("圆的历程"+"setSimpleSize");
        if(mWidth==0)mInSampleSize=size;
        else{
            mInSampleSize=size;
            if(!imageBitmap.isRecycled()){
                imageBitmap.recycle();
                imageBitmap=null;
            }
            imageBitmap=getCircle(getSampleBitmap2(imageResourceId,mWidth));
            postInvalidate();
        }
    }

    public Bitmap getCircle(Bitmap bitmap){
        //circleRadio圆形图片的半径
        float circleRadio;
        //bitmapSize图片的尺寸,也就是圆的直径,正方形图片的边长
        int bitmapSize;
        if(bitmap.getHeight()>bitmap.getWidth()){
            circleRadio=bitmap.getWidth()/2;
            bitmapSize=bitmap.getWidth();
        }else{
            circleRadio=bitmap.getHeight()/2;
            bitmapSize=bitmap.getHeight();
        }
        //创建一张新的bitmap,跟传入图片一样宽的正方形bitmap,
        Bitmap b=Bitmap.createBitmap(bitmapSize,bitmapSize, Bitmap.Config.ARGB_8888);
        //将图片密度修改为上面那张的图片密度
        b.setDensity(bitmap.getDensity());
        //初始化画布,并将刚才创建的bitmap给这画布,让画布画在这bitmap上面
        Canvas canvas=new Canvas(b);
        //初始化画笔
        Paint p=new Paint();
        //在画布中画一个等宽的圆
        canvas.drawCircle(circleRadio,circleRadio,circleRadio,p);
        //设置画笔属性,让画笔只在哪圆圈中画画,关于画笔属性,可以百度一下,很多,但是非常有用
        p.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(bitmap,0,0,p);
        return  b;
    }

    /**
     * 获取特定大小缩略图
     * @param imageid 图片资源id
     * @param size 你想要获取的图片大小尺寸
     * @return
     */
    public Bitmap getSampleBitmap2(int imageid,int size){
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds=true;
        BitmapFactory.decodeResource(getResources(),imageid,options);
        options.inPreferredConfig = Bitmap.Config.ARGB_8888;
        options.inSampleSize= calculateInSampleSize(options,size)*mInSampleSize;
        //设置图片可以缩小
        options.inScaled = true;
        int calsize=options.outHeight>options.outWidth?options.outWidth:options.outHeight;
        /**
         * 计算图片缩小的目标密度,在这里说一下,有一条公式:
         * 输出图片的宽高= (原图片的宽高 * (inTargetDensity / inDensity)) / inSampleSize
         * 一般来说,图片的options.inDensity默认为160
         * 所以inTargetDensity计算公式为:(希望输出的宽高*options.inDensity)/(原来图片的宽高/options.inSampleSize)
         */
        options.inTargetDensity =(size*options.inDensity)/(calsize/options.inSampleSize);
        options.inJustDecodeBounds = false;
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(),imageid,options);
        circleRadio=bitmap.getWidth()/2;
        return bitmap;
    }

    //谷歌源码里面的计算simplesize方法,
    public int calculateInSampleSize(BitmapFactory.Options options,
                                     int size) {
        int reqWidth,reqHeight;
        // Raw height and width of image
        final int height = options.outHeight;
        final int width = options.outWidth;
        if(options.outHeight>options.outWidth){
            reqWidth=size;
            reqHeight=size*options.outHeight/options.outWidth;
        }else{
            reqWidth=size*options.outWidth/options.outHeight;
            reqHeight=size;
        }
        int inSampleSize = 1;

        if (height > reqHeight || width > reqWidth) {

            final int halfHeight = height / 2;
            final int halfWidth = width / 2;

            // Calculate the largest inSampleSize value that is a power of 2 and
            // keeps both
            // height and width larger than the requested height and width.
            while ((halfHeight / inSampleSize) > reqHeight
                    && (halfWidth / inSampleSize) > reqWidth) {
                inSampleSize *= 2;
            }
        }

        return inSampleSize;
    }
}

然后你用的时候直接这样用就好了:

<?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:luo="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="com.example.administrator.testmyidea.MainActivity">

    <com.example.administrator.testmyidea.myTextView.circleImageView
            luo:imageSrc="@drawable/timg"
            luo:inSampleSize="1"
            android:layout_width="150dp"
            android:layout_height="150dp"/>
</RelativeLayout>

对了,记得在你的xml里面加上自定义组件的命名空间,如果你用的开发工具是androidStudo,那么要加

xmlns:luo="http://schemas.android.com/apk/res-auto"

如同我上面一样

eclipse的话,那就比较恶心了,得动态加载到包名,格式如同下面

//其中com.xxx是你的包名
xmlns:luo="http://schemas.android.com/apk/res/com.xxx"

好啦,然后就可以使用这个组件啦~~~

public class MainActivity extends Activity {
    circleImageView circle;
    int size=1;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.go).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                circle.setSimpleSize(size++);
            }
        });
        circle=(circleImageView)findViewById(ll);
        circle.setImageid(R.drawable.touxiang);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值