自定义圆角矩形---BitmapShader

今天,在网络上学习时发现了一个好东西啊--BitmapShader ,改变图片的形状,自定义控件后可以重复使用--哈哈。

这里我进行了自己的理解并且自己实现了一个,我会对每一个代码语句进行注解。

如果想自己详细的学习,请看鸿洋大大的作品-http://blog.csdn.net/lmj623565791/article/details/41967509%20mutable


在上图中有 3个图片,第一章是原始图片,由于截图需要,在xml文件中是指宽高是制定了宽高:

android:layout_width="200dp"
android:layout_height="150dp"

下面介绍一下原理。

实现第一张美女图片时,啥也不用做,进行ImageView控件的正常设置即可。

第二张 图片进行自定义控件,在这里就要说明一下我们要用到的BitmapShader这个牛B家伙了,这个伙计可以对图片3中模式的操作

Shader.TileMode 

CLAMP 

replicate the edge color if the shader draws outside of its original bounds  

Shader.TileMode 

MIRROR 

repeat the shader's image horizontally and vertically, alternating mirror images so that adjacent images always seam  

Shader.TileMode 

REPEAT 

repeat the shader's image horizontally and vertically  


哎,英文我是不行了,看了头大啊,

Shader.TileMpde.CLAMP 这个是说,这里就不得不说他的构造函数了,不然不好解释,小伙们我们一起看他的创造者,

BitmapShader(Bitmap bitmap, Shader.TileMode tileX, Shader.TileMode tileY)

Call this to create a new shader that will draw with a bitmap.

英文解释好像是(我自己的理解,如果有错,表明你英文牛哄哄的 大笑),

调用这个函数生成一个shapder对象,然后可以用shader对象画一个bitmap(这个bitmap是你资源文件中的图片通过代码装换出来(后面代码有如何转换),这个bitmap看构造函数就是通过构造函数传进来的,后面的参数就是对图片进行拉伸操作,白痴说话是,通过构造函数中的3中模式中的一个,对你传进来的bitmap图片进行在加工,出厂后就是你想要的东西)。

好了,言归正传Shader.TileMpde.CLAMP 是拉伸,恩,这里要注意啦,不是只要设置了它,就一定会执行,只用当图片的宽高,小于view的宽高是它参会拉神,好难理解啊,我们看图说话:


从图看,当图片层的矩形小于view层的大小才可以拉伸,拉伸的是上下左右每一个边上的1个像素点,那么是不是当他们的大小一样大(白痴的说就是重合)他们会如何?

哈哈答案就是什么也不做,不进行拉伸操作,还有一点就是他先对Y轴进行拉伸,在对x轴进行拉神,我盗用了爱神的图片,看看拉伸的图片


上图中的shader是BitmapShader(Bitmap bitmap, Shader.TileMode.CLAMPShader.TileMode.CLAMP)长生的,对X轴和Y周方向进行拉伸,先对Y后拉伸在对X轴拉伸。

原图片仅仅占据了左上角的一小部分,但是view占据了整个手机屏幕,所以对图片进行了拉伸来满足view的大小。

具体实现:

自定义属性:

<attr name="borderRadius" format="dimension"/>

<attr name="type">
    <enum name="circle" value="0"/>
    <enum name="round" value="1"/>
</attr>

<declare-styleable name="RoundImageView">
    <attr name="borderRadius"/>
    <attr name="type"/>
</declare-styleable>

自定义控件

package com.luo.cutomimageview.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
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.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.widget.ImageView;

import com.luo.cutomimageview.R;


/**
 * Created by luolawn on 15/7/8.
 * 自定义圆角图片
 */
public class RoundImageView extends ImageView {

    public static final int BORDER_RADIUS_DEFAULT = 10;
    private static final int TYPE_CIRCLE = 0;
    private static final int TYPE_ROUND = 1;
    private final Matrix matrix;
    private final Paint mPaint;
    private int mBorderRadius;
    private int type;
    private int mRaduis;
    private BitmapShader mBitmapShader;
    private int mWidth;
    private RectF mRoundRect;

    public RoundImageView(Context context, AttributeSet attrs) {
        super(context, attrs);


        matrix = new Matrix();

        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        getAttrsFromXML(context,attrs);
    }


    /**
     * 取得自定义的属性值
     */
    private void getAttrsFromXML(Context context,AttributeSet attrs){

        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RoundImageView);

        mBorderRadius = a.getDimensionPixelSize(R.styleable.RoundImageView_borderRadius,
                (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,BORDER_RADIUS_DEFAULT
                        ,getResources().getDisplayMetrics()));

        type = a.getInt(R.styleable.RoundImageView_type,TYPE_CIRCLE); // 默认原型

        a.recycle();   //在把所有的属性取出后,把TypeArray清空

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        if (TYPE_CIRCLE == type) {
            /**
             * 如果我们目标是画出圆形,那么我们要画出一个正方形的矩形,以测量的高和宽中的最小值为正方形的边长
             * 当我们进行填充图片时,在对图片进行适当的matrix
             */
             mWidth = Math.min(getMeasuredHeight(), getMeasuredWidth());

            mRaduis = mWidth / 2;

            setMeasuredDimension(mWidth, mWidth);

        }
    }


        /**
         * 设置bitmapShader
         */

        private void setupBitmapShader(){


            //取得用户设置的图片
            Drawable drawable = getDrawable();
            if (drawable == null){
                return;
            }
            Bitmap bitmap = drawableToBitmap(drawable);

            mBitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);

            float scal = 1.0f;


            if (type == TYPE_CIRCLE){

                int bSize = Math.min(bitmap.getWidth(),bitmap.getHeight());

                scal = mWidth * 1.0f / bSize;

            }else if (type == TYPE_ROUND){

                scal = Math.max(getHeight() * 1.0f / bitmap.getHeight(),getWidth() * 1.0f / bitmap.getWidth());
            }
            scal = 0.2f;

            matrix.setScale(scal,scal);


          //  mBitmapShader.setLocalMatrix(matrix);

            setImageMatrix(matrix);

            mPaint.setShader(mBitmapShader);

        }


    /**
     * 把drawable转化成bitmap
     * @param drawable
     * @return
     */
    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 b = Bitmap.createBitmap(w,h, Bitmap.Config.ARGB_8888);

        Canvas canvas = new Canvas(b);

        drawable.setBounds(0,0,w,h);

        drawable.draw(canvas); //把图片画到canva中去

        return b;
    }


    @Override
    protected void onDraw(Canvas canvas) {

        if(getDrawable() == null){
            return;
        }

        setupBitmapShader();

        if (type == TYPE_CIRCLE){
            canvas.drawCircle(mRaduis,mRaduis,mRaduis,mPaint);
        }else if (type == TYPE_ROUND){

            canvas.drawRoundRect(mRoundRect,mBorderRadius,mBorderRadius,mPaint);
        }


    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);

        if (type == TYPE_ROUND){
            mRoundRect = new RectF(0,0,getWidth(),getHeight());
        }
    }






}


布局文件
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:zhy="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
   >
    <ImageView
        android:layout_width="200dp"
        android:layout_height="150dp"
        android:src="@drawable/gril"/>

    <com.luo.cutomimageview.view.RoundImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/gril"/>

    <com.luo.cutomimageview.view.RoundImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/gril"
        zhy:type="round"
        zhy:borderRadius="60dp"/>



</LinearLayout>
</ScrollView


mainActivity.java不需要进行更改


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值