Android Drawable 进阶篇

来源:互联网 发布:莎莎源码的解压密码 编辑:程序博客网 时间:2024/05/29 14:24

1、前言

在前一篇博客当中提到关于Drawable的一些常用的用法,和使用系统自身的提供Drawable子类,来实现一定的具有功能性的Drawable,那么在今天的博客当中,我们就去自己定义Drawable的子类去实现我们自己功能的Drawable,

2、正文

首先我们去自己考虑一下,自定义Drawable是什么,先不着急,我们思考一下Android系统为我们提供的Drawable的子类实现,我们明确是对我们原有的图片进行一定的封装,然后进行一定的处理,让它和原来的最根本的res资源Drawable有某一种小功能,比如我们的ClipDrawable,ScaleDrawable,RotateDrawable,第一个是对原有的res资源Drawable有裁剪的功能,第二ScaleDrawable,是对原有的的res下的根本Drawable有一定的缩放功能,而第三个RotateDrawable就是对原来最原始的Drawable有一定的旋转功能。我们自定义Drawable首先我们要明确我们自定义的Drawable去实现什么功能,在这里我们去实现一个百叶窗的动画效果,


百叶窗效果:为了和原图作比较,我们把原图和百叶窗的效果一起展示出来,

首先来看我们的自定义Drawable,我们起名为ShuttersDrawable

import android.graphics.Bitmap;import android.graphics.Canvas;import android.graphics.ColorFilter;import android.graphics.Paint;import android.graphics.PixelFormat;import android.graphics.drawable.Drawable;/** * 自定义百叶窗的Drawable对象 * @author liusuansuan *///TODO(suansuan):由于创建Bitmap的时候,我们的宽度不能是0,//TODO(suansuan): 所以在做动画的时候我们不能通过ValueAnimator从0开始public class ShuttersDrawable extends Drawable{    /** 在这里定义一下我们所要 */    private Bitmap mBitmap;//原图的Bitmap的对象    private Bitmap[] mBitmaps;//对原图进行分割以后百叶窗,叶片的Bitmap对象数组    private int mWidth;    //原图的宽度。    private int mHeight;//原图的高度    private int mCellWidth;//单个叶片的宽度    private int mCount;    //叶片总数    private Paint mPaint;//画笔    private float scale = 1f;//比例,当前绘制的比例,主要通过该属性去控制整个百叶窗动画    /** 初始化操作 */    public ShuttersDrawable(Bitmap bitmap, int count){        this.mBitmap = bitmap;        this.mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);        this.mCount = count;        initBitmap();    }    /** 初始化Bitmap */    private void initBitmap() {        this.mHeight = mBitmap.getHeight();        this.mWidth = mBitmap.getWidth();        mCellWidth = mWidth / mCount;        mBitmaps = new Bitmap[mCount];    }    /** 绘制方法 */    @Override    public void draw(Canvas canvas) {        canvas.save();        float width = (mCellWidth * scale) + 1;        if(width >= mCellWidth){            width = mCellWidth;        }        for(int i = 0 ; i < mBitmaps.length; i++){            mBitmaps[i] = Bitmap.createBitmap(mBitmap, i * mCellWidth, 0,(int)width, mHeight);            canvas.drawBitmap(mBitmaps[i], i * mCellWidth, 0, mPaint);        }        canvas.restore();    }    /** 设置比例 */    public void setScale(float mScale){        this.scale = mScale;        invalidateSelf();    }    /** 主要是给以后使用到该Drawable,可以得到该Drawable的宽度 */    @Override    public int getIntrinsicWidth() {        return mBitmap.getWidth();    }    /** 主要是给以后使用到该Drawable,可以得到该Drawable的高度 */    @Override    public int getIntrinsicHeight() {        return mBitmap.getHeight();    }    @Override    public int getOpacity() {        return PixelFormat.TRANSLUCENT;    }    @Override    public void setAlpha(int alpha) {        mPaint.setAlpha(alpha);    }    @Override    public void setColorFilter(ColorFilter cf) {        mPaint.setColorFilter(cf);    }}

自定义Drawable我们首先需要继承Drawable,有几个方法我们是必须所要实现的那就是

draw(Canvas canvas):就是使用参数Canvas画布对象,给该Drawable画上内容的方法。

getOpacity():

setAlpha(int alpha):设置透明度

setColorFilter(ColorFilter cf):设置颜色过滤。

其余我写的都比较简单,大家应该都能看懂是什么意思,我也就不献丑了。说一下具体的思路。

就是我们把Bitmap分成一个个的叶片对象,然后对叶片对象进行绘制,然后通过sclae比例去控制绘制叶片的宽度,

activity_main.xml  layout:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"    android:gravity="center_horizontal">         <!-- 用来放至原来的Drawable对象 -->     <ImageView        android:layout_width="wrap_content"        android:layout_height="0dip"        android:layout_weight="1"        android:background="#F00"        android:src="@drawable/pressed"/>    <!-- 用来放至现在的ShuttersDrawable对象的载体  -->    <ImageView        android:id="@+id/iv_imageView"        android:layout_width="wrap_content"        android:background="#0F0"        android:layout_height="0dip"        android:layout_weight="1"/>   <Button     android:layout_width="wrap_content"     android:layout_height="wrap_content"     android:text="click me start Animator"     android:onClick="click"/> </LinearLayout>
使用Button来控制开启动画,

再来我们就看看在Activity中的实现

/** *  * @author suansuan * */public class MainActivity extends Activity {    private ShuttersDrawable mShuttersDrawable;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        initImageView();    }      /** 初始化ImageView */  private void initImageView() {  ImageView iv = (ImageView) findViewById(R.id.iv_imageView);      Bitmap decodeResource = BitmapFactory.decodeResource(getResources(),                                                                       R.drawable.pressed);      mShuttersDrawable = new ShuttersDrawable(decodeResource, 5);      iv.setImageDrawable(mShuttersDrawable);  }  /** Button的点击事件 */  @SuppressLint("NewApi")  //TODO(suansuan):在这里,博主建议大家还是使用V7包下面的Animator,          //TODO(suansuan):博主是因为个人原因没用使用,为了更好的适配,大家请不要这样  public void click(View view){     ValueAnimator mValueAnimation = ValueAnimator.ofFloat(0f, 1f).                                                                         setDuration(10000);     mValueAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {             @SuppressLint("NewApi") @Override             public void onAnimationUpdate(ValueAnimator animation) {                 float animatedValue = (Float) animation.getAnimatedValue();                 mShuttersDrawable.setScale(animatedValue);             }         });        mValueAnimation.start();  }}

效果呢就如下所以。


上述就是如何通过自定义Drawable去实现百叶窗的效果,

接下来我们去探讨第二个问题,我们以前会去通过自定义View去实现一些关于画图的东西其实都可以通过自定义Drawable去实现,比如鸿洋大神可以通过自定义Drawable去实现圆角图片一样,这个时候我们想到的也许就是去自定义Imageview去实现,大家应该发现了,自定义Drawable就可以看做是自定义View的一种轻量级实现,下面我们看看一种效果,然后我们去自定义这种效果,这种效果叫什么呢,我也不知,总之我们看吧!


这种类似于专辑盒的Icon,在各大音乐平台多的是,相信大家也都做过,我们可以类似于这样的专辑盒去做一个自定义Drawable,好了废话少说,我们开始干活。

package vadsdk.testdrawable.drawable;import android.annotation.SuppressLint;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.ColorFilter;import android.graphics.Matrix;import android.graphics.Paint;import android.graphics.PixelFormat;import android.graphics.drawable.Drawable;import vadsdk.testdrawable.R;public class AlbumDrawable extends Drawable {/** 画笔对象 */private Paint mPaint;/** 右侧图片对象 */private Bitmap mLeftDrawable;/** 背景阴影图片 */private Bitmap mBackgoundDrawable;/** 内容图片 */private Bitmap mContentBitmap;/** 上下文环境 */private Context mContext;/** 构造方法 */public AlbumDrawable(Bitmap bitmap, Context context) {this.mContentBitmap = bitmap;this.mContext = context;init();}/** 初始化操作 */private void init() {mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);mLeftDrawable = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.album_chart_left);}@Overridepublic void draw(Canvas canvas) {onDrawLeftDrawable(canvas);onDrawLeftBitmap(canvas);onDrawDrawable(canvas);}/** 绘制小图片 */private void onDrawLeftDrawable(Canvas canvas) {canvas.save();canvas.translate(mLeftDrawable.getWidth()/2f, mLeftDrawable.getWidth() * 3f/5f);Bitmap zoomBitmap = zoomBitmap(mContentBitmap, 1/6f);canvas.drawBitmap(zoomBitmap, 0, 0, mPaint);canvas.restore();}/** 绘制海报Drawable */private void onDrawDrawable(Canvas canvas) {canvas.save();canvas.translate(mLeftDrawable.getWidth(), 0);Bitmap zoomBitmap = zoomBitmap(mContentBitmap , mLeftDrawable.getHeight()-3);canvas.drawBitmap(zoomBitmap, 0, 0, mPaint);canvas.restore();}/** 绘制左侧的图片 */private void onDrawLeftBitmap(Canvas canvas) {canvas.save();canvas.drawBitmap(mLeftDrawable, 0, 0, mPaint);canvas.restore();}/** 按照比例获取Bitmap */private Bitmap zoomBitmap(Bitmap bitmap, int h){int width = bitmap.getWidth();int height = bitmap.getHeight();float scaleHeight = ((float)h)/height;Matrix matrix = new Matrix();    // 计算缩放比例matrix.postScale(scaleHeight, scaleHeight);return Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);}/** 按照比例获取Bitmap */private Bitmap zoomBitmap(Bitmap bitmap, float scale){int width = bitmap.getWidth();int height = bitmap.getHeight();Matrix matrix = new Matrix();    // 计算缩放比例matrix.postScale(scale, scale);return Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);}@Overridepublic int getOpacity() {return PixelFormat.TRANSLUCENT;}@Overridepublic void setAlpha(int alpha) {mPaint.setAlpha(alpha);}@Overridepublic void setColorFilter(ColorFilter cf) {mPaint.setColorFilter(cf);}}
我们现在自己定义了一个Drawable,我说一下思路,大体的思路就是对Bitmap做一定的操作,然后根据宽高去摆放,使用Bitmap去缩放小的海报,然后使用左侧的图片去盖住右侧的图片,主要就是计算方面,博主写的计算方法也有偏差,可以自己明确计算规则写自己的逻辑。

下来在我们的Activity当中使用我们定义的Drawable

public class MainActivity extends AppCompatActivity {    private ImageView iv;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        iv = (ImageView) findViewById(R.id.iv_imageView);        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.album);        AlbumDrawable albumDrawable = new AlbumDrawable(bitmap, this);        iv.setImageDrawable(albumDrawable);    }}
效果如下:



以上就是自定义Drawable


1 0
原创粉丝点击