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
- Android Drawable 进阶篇
- Android进阶2之Bitmap、Drawable、byte[]转换
- Android进阶2之Bitmap、Drawable、byte[]转换
- android.graphics.drawable.Drawable
- android drawable Transition Drawable
- Android Drawable资源总结篇
- Android drawable
- Android Drawable
- android drawable
- Android Drawable
- Android Drawable
- Android Drawable
- android drawable
- Android Drawable
- android drawable
- Android Drawable
- android-Drawable
- Android drawable
- 应用:Python实现简单聊天程序
- 队列在Http请求中的一点理解
- 1452: 旅行(SPFA)
- (转)EL表达式(Expression Language)
- android下面通过ndk建立一个虚拟触摸屏设备可以被sendevent调用
- Android Drawable 进阶篇
- js string()常用方法总结
- 算法优解(10)-合并两个有序的单链表
- android listview 异步加载图片并防止错位
- 记android学习之路----Activity(4)----Activity之间的跳转与数据传递
- PIC单片机精通_A/D转换&异步串口通讯实例与详解
- web分布式方案
- codeforces 738D Sea Battle 思维+构造
- Java——>IO