今天,在网络上学习时发现了一个好东西啊--BitmapShader ,改变图片的形状,自定义控件后可以重复使用--哈哈。
这里我进行了自己的理解并且自己实现了一个,我会对每一个代码语句进行注解。
如果想自己详细的学习,请看鸿洋大大的作品-http://blog.csdn.net/lmj623565791/article/details/41967509%20mutable
在上图中有 3个图片,第一章是原始图片,由于截图需要,在xml文件中是指宽高是制定了宽高:
android:layout_width="200dp" android:layout_height="150dp"
下面介绍一下原理。
实现第一张美女图片时,啥也不用做,进行ImageView控件的正常设置即可。
第二张 图片进行自定义控件,在这里就要说明一下我们要用到的BitmapShader这个牛B家伙了,这个伙计可以对图片3中模式的操作
CLAMP | replicate the edge color if the shader draws outside of its original bounds | |
MIRROR | repeat the shader's image horizontally and vertically, alternating mirror images so that adjacent images always seam | |
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. |
![大笑](http://static.blog.csdn.net/xheditor/xheditor_emot/default/laugh.gif)
调用这个函数生成一个shapder对象,然后可以用shader对象画一个bitmap(这个bitmap是你资源文件中的图片通过代码装换出来(后面代码有如何转换),这个bitmap看构造函数就是通过构造函数传进来的,后面的参数就是对图片进行拉伸操作,白痴说话是,通过构造函数中的3中模式中的一个,对你传进来的bitmap图片进行在加工,出厂后就是你想要的东西)。
好了,言归正传Shader.TileMpde.CLAMP 是拉伸,恩,这里要注意啦,不是只要设置了它,就一定会执行,只用当图片的宽高,小于view的宽高是它参会拉神,好难理解啊,我们看图说话:
从图看,当图片层的矩形小于view层的大小才可以拉伸,拉伸的是上下左右每一个边上的1个像素点,那么是不是当他们的大小一样大(白痴的说就是重合)他们会如何?
哈哈答案就是什么也不做,不进行拉伸操作,还有一点就是他先对Y轴进行拉伸,在对x轴进行拉神,我盗用了爱神的图片,看看拉伸的图片
上图中的shader是BitmapShader(Bitmap bitmap, Shader.TileMode.CLAMP, Shader.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不需要进行更改