五种方式显示圆形图片

推荐阅读:

鸿洋:Android BitmapShader 实战 实现圆形、圆角图片

鸿洋:Android Xfermode 实战 实现圆形、圆角图片

依赖

这里写图片描述

自定义CircleImageView

> /**  * 圆图片View  */ 
> 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 = 1;
> 
>     private static final int DEFAULT_BORDER_WIDTH = 0;
>     private static final int DEFAULT_BORDER_COLOR = Color.BLACK;
> 
>     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 int mBorderColor = DEFAULT_BORDER_COLOR;
>     private int mBorderWidth = DEFAULT_BORDER_WIDTH;
> 
>     private Bitmap mBitmap;
>     private BitmapShader mBitmapShader;
>     private int mBitmapWidth;
>     private int mBitmapHeight;
> 
>     private float mDrawableRadius;
>     private float mBorderRadius;
> 
>     private boolean mReady;
>     private boolean mSetupPending;
> 
>     public CircleImageView(Context context) {
>         super(context);
>     }
> 
>     public CircleImageView(Context context, AttributeSet attrs) {
>         this(context, attrs, 0);
>     }
> 
>     public CircleImageView(Context context, AttributeSet attrs, int defStyle) {
>         super(context, attrs, defStyle);
>         super.setScaleType(SCALE_TYPE);
> 
>         TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView, defStyle, 0);
> 
>         mBorderWidth = a.getDimensionPixelSize(R.styleable.CircleImageView_border_width,
> DEFAULT_BORDER_WIDTH);
>         mBorderColor = a.getColor(R.styleable.CircleImageView_border_color,
> DEFAULT_BORDER_COLOR);
> 
>         a.recycle();
> 
>         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
>     protected void onDraw(Canvas canvas) {
>         if (getDrawable() == null) {
>             return;
>         }
> 
>         canvas.drawCircle(getWidth() / 2, getHeight() / 2, mDrawableRadius, mBitmapPaint);
>         canvas.drawCircle(getWidth() / 2, getHeight() / 2, 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 void setBorderColor(int borderColor) {
>         if (borderColor == mBorderColor) {
>             return;
>         }
> 
>         mBorderColor = borderColor;
>         mBorderPaint.setColor(mBorderColor);
>         invalidate();
>     }
> 
>     public int getBorderWidth() {
>         return mBorderWidth;
>     }
> 
>     public void setBorderWidth(int borderWidth) {
>         if (borderWidth == mBorderWidth) {
>             return;
>         }
> 
>         mBorderWidth = borderWidth;
>         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(int resId) {
>         super.setImageResource(resId);
>         mBitmap = getBitmapFromDrawable(getDrawable());
>         setup();
>     }
> 
>     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 (OutOfMemoryError e) {
>             return null;
>         }
>     }
> 
>     private void setup() {
>         if (!mReady) {
>             mSetupPending = true;
>             return;
>         }
> 
>         if (mBitmap == null) {
>             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);
> 
>         mBitmapHeight = mBitmap.getHeight();
>         mBitmapWidth = mBitmap.getWidth();
> 
>         mBorderRect.set(0, 0, getWidth(), getHeight());
>         mBorderRadius = Math.min((mBorderRect.height() - mBorderWidth) / 2, (mBorderRect.width() - mBorderWidth) / 2);
> 
>         mDrawableRect.set(mBorderWidth, mBorderWidth, mBorderRect.width() - mBorderWidth, mBorderRect.height() -
> mBorderWidth);
>         mDrawableRadius = Math.min(mDrawableRect.height() / 2, mDrawableRect.width() / 2);
> 
>         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) + mBorderWidth, (int) (dy + 0.5f) + mBorderWidth);
> 
>         mBitmapShader.setLocalMatrix(mShaderMatrix);
>     }
> 
> }
  • MyApp中初始化fresco和UIL:
public class MyApp extends Application {

    @Override
    public void onCreate() {
        super.onCreate();

        Fresco.initialize(this);
        initUIL();
    }

    private void initUIL() {
        File cacheFile = StorageUtils.getCacheDirectory(this);  //缓存文件夹路径
        Log.e("MyApplication", "initImageLoader:cacheDir===" + cacheFile);
        //cacheFile为:/storage/emulated/0/Android/data/com.example.administrator.myglide/cache

        ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(this)
                .memoryCacheExtraOptions(480, 800) // default = device screen dimensions 内存缓存文件的最大长宽
                .diskCacheExtraOptions(480, 800, null)  // 本地缓存的详细信息(缓存的最大长宽),最好不要设置这个
                .threadPoolSize(3) // default  线程池内加载的数量
                .threadPriority(Thread.NORM_PRIORITY - 2) // default 设置当前线程的优先级
                .tasksProcessingOrder(QueueProcessingType.FIFO) // default
                .denyCacheImageMultipleSizesInMemory()
                .memoryCache(new LruMemoryCache(2 * 1024 * 1024)) //可以通过自己的内存缓存实现
                .memoryCacheSize(2 * 1024 * 1024)  // 内存缓存的最大值
                .memoryCacheSizePercentage(13) // default
                .diskCache(new UnlimitedDiskCache(cacheFile)) // default 可以自定义缓存路径
                .diskCacheSize(50 * 1024 * 1024) // 50 Mb sd卡(本地)缓存的最大值
                .diskCacheFileCount(100)  // 可以缓存的文件数量
                // default为使用HASHCODE对UIL进行加密命名, 还可以用MD5(new Md5FileNameGenerator())加密
                .diskCacheFileNameGenerator(new HashCodeFileNameGenerator())
                .imageDownloader(new BaseImageDownloader(this)) // default
                .imageDecoder(new BaseImageDecoder(true)) // default
                // default,可以自定义defaultOptions来设置是否缓存:cacheInMemory(true)缓存内存和cacheOnDisc(true)缓存硬盘
                .defaultDisplayImageOptions(DisplayImageOptions.createSimple())
                .discCache(new LimitedAgeDiskCache(cacheFile, 7 * 24 * 60 * 60))// 自定义缓存路径,7天后自动清除缓存
                .writeDebugLogs() // 打印debug log
                .build(); //开始构建

        ImageLoader.getInstance().init(config); // 初始化
    }
}
  • 在Manifest中添加权限和注册app:
 
  <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

    <application
        ***android:name=".MyApp"***
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
  • 布局文件:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:fresco="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:background="#99eace31"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.administrator.myglide.MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <Button
            android:id="@+id/btn_diy_iv"
            android:onClick="clickbutton"
            android:text="下载图片并加载到自定义的圆形图片"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

        <com.example.administrator.myglide.views.CircleImageView
            android:id="@+id/diy_iv"
            android:src="@mipmap/ic_launcher"
            android:layout_width="match_parent"
            android:layout_height="300dp" />

        <!-->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>-->

        <TextView
            android:id="@+id/uil_tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="#ffffffff"
            android:text="UIL加载网络图片" />

        <ImageView
            android:id="@+id/uil_iv"
            android:layout_width="match_parent"
            android:layout_height="300dp "
            android:scaleType="centerInside"
            android:src="@mipmap/ic_launcher" />

        <!-->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>-->


        <TextView
            android:id="@+id/glide_tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="#ffffffff"
            android:text="glide加载网络图片" />

        <ImageView
            android:id="@+id/glide_iv"
            android:layout_width="match_parent"
            android:layout_height="300dp"
            android:scaleType="centerInside"
            android:src="@mipmap/ic_launcher" />

        <!-->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>-->


        <TextView
            android:id="@+id/picasso_tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="#ffffffff"
            android:text="Picasso加载网络图片" />

        <ImageView
            android:id="@+id/picasso_iv"
            android:layout_width="match_parent"
            android:layout_height="300dp"
            android:scaleType="centerInside"
            android:src="@mipmap/ic_launcher" />

        <!-->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>-->


        <TextView
            android:id="@+id/fresco_tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="#ffffffff"
            android:text="fresco加载网络图片" />

        <!--
                // com.facebook.drawee.view.SimpleDraweeView的宽度和高度
                不支持wrap_content, 如果要设置宽高比, 需要在Java代码中指定setAspectRatio(float ratio);
        -->
        <com.facebook.drawee.view.SimpleDraweeView
            android:id="@+id/fresco_iv"
            android:layout_width="match_parent"
            android:layout_height="300dp"
            android:scaleType="centerInside"
            android:src="@mipmap/ic_launcher"

            fresco:backgroundImage="@color/blue"
            fresco:failureImage="@drawable/first_icon25"
            fresco:failureImageScaleType="centerInside"

            fresco:placeholderImage="@color/wait_color"
            fresco:placeholderImageScaleType="fitCenter"
            fresco:pressedStateOverlayImage="@color/red"

            fresco:progressBarAutoRotateInterval="1000"
            fresco:progressBarImage="@drawable/first_icon11"
            fresco:progressBarImageScaleType="centerInside"
            fresco:retryImage="@drawable/first_icon19"
            fresco:retryImageScaleType="centerCrop"

            fresco:roundAsCircle="true"
            fresco:roundBottomLeft="true"
            fresco:roundBottomRight="true"
            fresco:roundTopLeft="true"
            fresco:roundTopRight="true"
            fresco:roundedCornerRadius="1dp"
            fresco:roundingBorderColor="@color/border_color"
            fresco:roundingBorderWidth="2dp" />

    </LinearLayout>

</ScrollView>
  • MainActivity:
public class MainActivity extends AppCompatActivity {

    String url = "http://image.codes51.com/Article/image/20150730/20150730121119_3945.gif";
    String net_url = "http://img2.3lian.com/2014/f6/173/d/51.jpg";
    String gif_url = " http://img15.3lian.com/2015/gif/1/78/1.gif";

    private ImageView glide_iv;
    private ImageView picasso_iv;
    private SimpleDraweeView fresco_iv;
    private ImageView uil_iv;
    private DisplayImageOptions options;
    private CircleImageView diy_iv;
    private ImageView iv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initViews();
//      加载圆角图片
        useUIL();
        usePicasso();
        useFresco();
        useGlide();

    }

    //自定义的圆形图片
    public void clickbutton(View view) {
         Bitmap bitmap = FileUtils.readImage(net_url);
        if (bitmap != null) {//读取sd图片
            Toast.makeText(this, "sd卡的路径:" + Environment
                            .getExternalStorageDirectory() + "/xq_caches/images" + url.substring(url.lastIndexOf("/") + 1)
                    , Toast.LENGTH_LONG).show();    //路径为:/storage/emulated/0   /qf_caches/images/  51.jpg
            diy_iv.setImageBitmap(bitmap);
        } else {
            // 发送异步请求
            new MyAsyncTask(this).execute(net_url);
        }
    }

    private void useGlide() {
        Glide.with(this)
                .load("http://img2.3lian.com/2014/f6/173/d/51.jpg")// 加载图片资源
                .skipMemoryCache(false)//是否将图片放到内存中
                .diskCacheStrategy(DiskCacheStrategy.ALL)//磁盘图片缓存策略
                .dontAnimate()//不执行淡入淡出动画
                .crossFade(100)// 默认淡入淡出动画300ms
                .placeholder(R.mipmap.ic_launcher)// 占位图片
                .error(R.mipmap.ic_launcher)//图片加载错误显示
                .centerCrop()//  或者  fitCenter()
                .transform(new GlideCircleTransform(this))//圆角图片
                .into(glide_iv);    //更新ui
    }

    private void useFresco() {
        DraweeController controller = Fresco.newDraweeControllerBuilder()
                .setUri(Uri.parse(net_url))
                .setAutoPlayAnimations(true)        自动播放动画,比如:gif
                .build();
        fresco_iv.setController(controller);
    }

    private void usePicasso() {
        Picasso.with(this)
                .load("http://img2.3lian.com/2014/f6/173/d/51.jpg")
                .transform(new PicassoCircleTransform())//圆角
                .placeholder(R.drawable.first_icon26)
                .error(R.drawable.first_icon25)
                .into(picasso_iv);
    }

    /**
     * UIL
     */
    private void useUIL() {
        options = new DisplayImageOptions.Builder()//构造者模式,option可以放在Application中
                .showStubImage(R.mipmap.ic_launcher)//缓冲过程中图片
                .showImageForEmptyUri(R.mipmap.ic_launcher)// 设置图片Uri为空或是错误的时候显示的图片
                .showImageOnFail(R.drawable.first_icon11)// 设置图片加载或解码过程中发生错误显示的图片
                .cacheInMemory(true)//缓存到内存
                .cacheOnDisc(true)//缓存到硬盘
                .bitmapConfig(Bitmap.Config.ARGB_8888)   //设置图片的解码类型
                .displayer(new UILCircleBitmapDisplayer())//自定义圆形图片,与默认区别在于圆心坐标移到了ImageView的中心
//                .displayer(new RoundedBitmapDisplayer(60))//默认圆角图片,弧度
//                .displayer(new CircleBitmapDisplayer(R.color.corner_color))//默认圆形图片,颜色
//                .displayer(new FadeInBitmapDisplayer(2000))//默认渐明效果,时间
                .build();
        ImageLoader.getInstance().displayImage("http://img2.3lian.com/2014/f6/173/d/51.jpg", uil_iv, options);
   /*     ImageLoader.getInstance()
                .loadImage("http://img2.3lian.com/2014/f6/173/d/51.jpg", options, new ImageLoadingListener() {
                    @Override
                    public void onLoadingStarted(String imageUri, View view) {

                    }

                    @Override
                    public void onLoadingFailed(String imageUri, View view, FailReason failReason) {

                    }

                    @Override
                    public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {

                    }

                    @Override
                    public void onLoadingCancelled(String imageUri, View view) {

                    }
                });*/
    }

    private void initViews() {
        diy_iv = ((CircleImageView) findViewById(R.id.diy_iv));
        glide_iv = ((ImageView) findViewById(R.id.glide_iv));
        picasso_iv = ((ImageView) findViewById(R.id.picasso_iv));
        fresco_iv = ((SimpleDraweeView) findViewById(R.id.fresco_iv));
        uil_iv = (ImageView) findViewById(R.id.uil_iv);
    }

    class MyAsyncTask extends AsyncTask<String, Void, byte[]> {
        private ProgressDialog pDialog;
        public MyAsyncTask(Context context) {
            pDialog = new ProgressDialog(context);
            pDialog.setIcon(R.mipmap.ic_launcher);
            pDialog.setTitle("提示");
            pDialog.setMessage("The data is loading...");
// 如果没有图标,可以像下面这样构建ProgressDialog:参数为:上下文,title,content
//            ProgressDialog pDialog = ProgressDialog.show(context, null, "加载中...");
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            pDialog.show();
        }

        @Override
        protected byte[] doInBackground(String... params) {

            URL url;
            Bitmap bitmap = null;
            try {
                url = new URL(params[0]);
                //获得连接
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                //设置超时时间为6000毫秒,conn.setConnectionTiem(0);表示没有时间限制
                conn.setConnectTimeout(6000);
                //连接设置获得数据流
                conn.setDoInput(true);
                //不使用缓存
                conn.setUseCaches(false);
                //这句可有可无,没有影响
                conn.connect();
                //得到数据流
                InputStream is = conn.getInputStream();
                //解析得到图片
                bitmap = BitmapFactory.decodeStream(is);
                //关闭数据流
                is.close();

                if (conn.getResponseCode() == 200) {
                    // 缓存工具类:保存图片
                    Utilsfile.saveImage(params[0], bitmap);// url:params[0]

                    //返回字符数组
                    ByteArrayOutputStream stream = new ByteArrayOutputStream();
                    bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
                    byte[] byteArray = stream.toByteArray();

                    return byteArray;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onPostExecute(byte[] result) {
            super.onPostExecute(result);
            if (result != null) {
                Bitmap bitmap = BitmapFactory.decodeByteArray(result, 0,
                        result.length);
                diy_iv.setImageBitmap(bitmap);
            }
            pDialog.dismiss();
        }
    }
}
  • 自定义GlideCircleTransform:
public class GlideCircleTransform extends BitmapTransformation {

    public GlideCircleTransform(Context context) {
        super(context);
    }

    @Override
    protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
        return circleCrop(pool,toTransform);
    }
    private  Bitmap circleCrop(BitmapPool pool, Bitmap source) {

        int size = Math.min(source.getWidth(), source.getHeight());

        int width = (source.getWidth() - size) / 2;
        int height = (source.getHeight() - size) / 2;

        Bitmap bitmap = pool.get(size, size, Bitmap.Config.ARGB_8888);
        if (bitmap == null) {
            bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
        }

        Canvas canvas = new Canvas(bitmap);
        Paint paint = new Paint();
        BitmapShader shader =
                new BitmapShader(source, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP);
        if (width != 0 || height != 0) {
            // source isn't square, move viewport to center
            Matrix matrix = new Matrix();
            matrix.setTranslate(-width, -height);
            shader.setLocalMatrix(matrix);
        }
        paint.setShader(shader);
        paint.setAntiAlias(true);

        float r = size / 2f;
        canvas.drawCircle(r, r, r, paint);

        return bitmap;
    }

    @Override
    public String getId() {
        return getClass().getName();
    }
}
  • 自定义PicassoCircleTransform:
public class PicassoCircleTransform implements Transformation {
    @Override
    public Bitmap transform(Bitmap source) {
        /**
         * 求出宽和高的哪个小
         */
        int  size = Math.min(source.getWidth(), source.getHeight());

        /**
         * 求中心点
         */
        int x = (source.getWidth() - size) / 2;
        int y = (source.getHeight() - size) / 2;

        /**
         * 生成BitMap
         */
        Bitmap squaredBitmap = Bitmap.createBitmap(source, x, y, size, size);
        if (squaredBitmap != source) {
            //释放
            source.recycle();
        }

        /**
         * 建立新的Bitmap
         */
        Bitmap bitmap = Bitmap.createBitmap(size, size, source.getConfig());

        /**
         * 画布画笔
         */
        Canvas canvas = new Canvas(bitmap);
        Paint paint  = new Paint();

        BitmapShader shader = new BitmapShader(squaredBitmap,
                BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP);
        paint.setShader(shader);
        paint.setAntiAlias(true);

        float r = size / 2f;
        /**
         * 画圆
         */
        canvas.drawCircle(r, r, r, paint);

        squaredBitmap.recycle();
        return bitmap;
    }

    @Override
    public String key() {
        return "circle";
    }
}
  • 自定义UILCircleBitmapDisplayer:
/**
 * 自定义圆形图片,与默认圆形图片区别在于圆心坐标移到了ImageView的中心
 */
public class UILCircleBitmapDisplayer implements BitmapDisplayer {

    protected final Integer strokeColor;
    protected final float strokeWidth;

    public UILCircleBitmapDisplayer() {
        this(null);
    }

    public UILCircleBitmapDisplayer(Integer strokeColor) {
        this(strokeColor, 0);
    }

    public UILCircleBitmapDisplayer(Integer strokeColor, float strokeWidth) {
        this.strokeColor = strokeColor;
        this.strokeWidth = strokeWidth;
    }

    @Override
    public void display(Bitmap bitmap, ImageAware imageAware, LoadedFrom loadedFrom) {
        if (!(imageAware instanceof ImageViewAware)) {
            throw new IllegalArgumentException("ImageAware should wrap ImageView. ImageViewAware is expected.");
        }

        imageAware.setImageDrawable(new CircleDrawable(bitmap, strokeColor, strokeWidth));
    }

    public static class CircleDrawable extends Drawable {

        protected float radius;

        protected final RectF mRect = new RectF();
        protected final RectF mBitmapRect;
        protected final BitmapShader bitmapShader;
        protected final Paint paint;
        protected final Paint strokePaint;//描边的画笔
        protected final float strokeWidth;//描边的宽度
        protected float strokeRadius;//描边的半径

        public CircleDrawable(Bitmap bitmap, Integer strokeColor, float strokeWidth) {
            radius = Math.min(bitmap.getWidth(), bitmap.getHeight()) / 2;//宽高中较小值的一半为半径

            bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
            mBitmapRect = new RectF(0, 0, bitmap.getWidth(), bitmap.getHeight());//imageview的框架为矩形

            paint = new Paint();
            paint.setAntiAlias(true);
            paint.setShader(bitmapShader);
            paint.setFilterBitmap(true);
            paint.setDither(true);

            if (strokeColor == null) {
                strokePaint = null;
            } else {
                strokePaint = new Paint();
                strokePaint.setStyle(Paint.Style.STROKE);   //设置paint的风格为“空心”
//                设置画笔的样式,为FILL,FILL_OR_STROKE,或STROKE
                strokePaint.setColor(strokeColor);
                strokePaint.setStrokeWidth(strokeWidth);    // 设置“空心”的外框的宽度
//                当画笔样式为STROKE或FILL_OR_STROKE时,设置笔刷的粗细度
                strokePaint.setAntiAlias(true);
            }
            this.strokeWidth = strokeWidth;
            strokeRadius = radius - strokeWidth / 2;
        }

        @Override
        protected void onBoundsChange(Rect bounds) {
            super.onBoundsChange(bounds);
            mRect.set(0, 0, bounds.width(), bounds.height());
            radius = Math.min(bounds.width(), bounds.height()) / 2;
            strokeRadius = radius - strokeWidth / 2;

            // Resize the original bitmap to fit the new bound
            Matrix shaderMatrix = new Matrix();
            shaderMatrix.setRectToRect(mBitmapRect, mRect, Matrix.ScaleToFit.FILL);
            bitmapShader.setLocalMatrix(shaderMatrix);
        }

        @Override
        public void draw(Canvas canvas) {
            //自定义圆形图片,与默认区别在于圆心坐标移到了ImageView的中心
            Rect bounds = getBounds();//画一个圆圈
            //getBounds() 方法与 getRect() 方法类似,返回一个矩形,
            //getBounds() 方法返回的矩形包括形状的所有笔触,然而 getRect() 方法返回的矩形则不包括
            //getRect() 方法返回的值等于或小于由 getBounds() 方法返回的值。
            canvas.drawCircle(bounds.width() / 2F, bounds.height() / 2F, radius, paint);
            if (strokePaint != null) {
                canvas.drawCircle(bounds.width() / 2F, bounds.height() / 2F, strokeRadius, strokePaint);
            }
        }

        @Override
        public int getOpacity() {
            return PixelFormat.TRANSLUCENT;
        }

        @Override
        public void setAlpha(int alpha) {
            paint.setAlpha(alpha);
        }

        @Override
        public void setColorFilter(ColorFilter cf) {
            paint.setColorFilter(cf);
        }
    }
}
  • 利用到的文件工具类:
public class FileUtils {

    private static final String CACHE_DIR = Environment
            .getExternalStorageDirectory() + "/qf_caches/images";// 缓存文件夹

    /**
     * 判断sdcard是否挂载
     *
     * @return
     */
    public static boolean isMounted() {
        String state = Environment.getExternalStorageState();
        return state.equals(Environment.MEDIA_MOUNTED);
    }

    /**
     * 获取sdcard的根目录
     *
     * @return
     */
    public static String getSDCARDDir() {
        return Environment.getExternalStorageDirectory().getAbsolutePath();
    }

    /**
     * 存储图片一
     *
     * @param url
     *            : 图片的http网络地址
     * @param data
     * @throws IOException
     */
    public static void saveImage(String url, byte[] data) throws IOException {
        // 1. 判断是否有sdcard
        if (!isMounted()) {
            return;
        }
        // 2. 判断是否有缓存的文件夹
        File dir = new File(CACHE_DIR);
        if (!dir.exists()) {
            dir.mkdirs();// 多层文件夹
        }
        // 3. 存储图片到sdcard
        File file = new File(dir, getFilename(url));
        FileOutputStream fos = new FileOutputStream(file);

        fos.write(data);
        fos.close();
    }

    /**
     * 保存图片二
     *
     * @param url
     *            : 图片的http网络地址
     * @param bitmap
     * @throws IOException
     */
    public static void saveImage(String url, Bitmap bitmap) throws IOException {
        // 1. 判断是否有sdcard
        if (!isMounted()) {
            return;
        }
        // 2. 判断是否有缓存的文件夹
        File dir = new File(CACHE_DIR);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        // 3. 存储图片到sdcard
        File file = new File(dir, getFilename(url));
        FileOutputStream fos = new FileOutputStream(file);

        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
    }

    /**
     * 获取图片名
     *
     * @param url
     * @return
     */
    public static String getFilename(String url) {
        return url.substring(url.lastIndexOf("/") + 1);
    }

    /**
     * 读图片
     *
     * @param url
     * @return
     */
    public static Bitmap readImage(String url) {
        // 判断是否有sdcard
        if (!isMounted()) {
            return null;
        }
        File file = new File(CACHE_DIR, getFilename(url));
        if (file.exists()) {
            // file->bitmap
            return BitmapFactory.decodeFile(file.getAbsolutePath());
        }
        return null;
    }

    /**
     * 清空缓存目录
     */
    public void clearCaches() {
        File dir = new File(CACHE_DIR);
        File[] allfiles = dir.listFiles();
        for (File file : allfiles) {
            file.delete();
        }
    }
}

欢迎交流。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值