您当前的位置: 首页 >  ui

命运之手

暂无认证

  • 3浏览

    0关注

    747博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

【高级UI】【017】自定义Drawable

命运之手 发布时间:2021-11-06 16:48:20 ,浏览量:3

前言

在前面我们已经讲过,Drawable并不是图片,它只是一个抽象类,对要绘制什么,怎么绘制进行了封装

这篇博客,我们以一个实际的例子来具体阐述,Drawable是如何工作的

功能

功能非常简单,主要是为了演示Drawable如何工作

我们实现的是一个ImageView,它将图片的左半侧显示为灰色,右半侧显示为彩色

这个效果非常容易实现,这里我们主要是通过它来演示Drawable的工作原理

代码


	package com.android.architecture;
	
	import android.graphics.Bitmap;
	import android.graphics.Canvas;
	import android.graphics.ColorFilter;
	import android.graphics.ColorMatrix;
	import android.graphics.ColorMatrixColorFilter;
	import android.graphics.Paint;
	import android.graphics.PixelFormat;
	import android.graphics.Rect;
	import android.graphics.drawable.Drawable;
	
	import com.easing.commons.android.manager.Bitmaps;
	
	//图像左侧变灰效果
	@SuppressWarnings("all")
	public class HalfGreyDrawable extends Drawable {
	
	    final Drawable baseDrawable;
	    final Bitmap baseBitmap;
	
	    //绘制灰色部分
	    final Paint paint1 = new Paint();
	    //绘制正常部分
	    final Paint paint2 = new Paint();
	
	    public HalfGreyDrawable(Drawable baseDrawable) {
	        this.baseDrawable = baseDrawable;
	        this.baseBitmap = Bitmaps.drawableToBitmap(baseDrawable);
	        ColorMatrix matrix = new ColorMatrix(new float[]{
	                0.333F, 0.333F, 0.333F, 0, 0,
	                0.333F, 0.333F, 0.333F, 0, 0,
	                0.333F, 0.333F, 0.333F, 0, 0,
	                0, 0, 0, 1, 0
	        });
	        ColorMatrixColorFilter filter = new ColorMatrixColorFilter(matrix);
	        paint1.setColorFilter(filter);
	        paint1.setAlpha(255);
	    }
	
	    //这里共实现了三个效果
	    //一个是图像的半侧变灰效果
	    //一个是变灰的位置带有动画效果,从左往右,再从右往左,如此反复
	    //一个是图像支持局部显示
	    @Override
	    public void draw(Canvas canvas) {
	        int level = getLevel();
	        Rect bounds = getBounds();
	        int w = bounds.right - bounds.left;
	        int h = bounds.bottom - bounds.top;
	        //绘制灰色部分
	        {
	            Rect srcRect = new Rect(bounds.left, bounds.top, bounds.left + w * level / 100, bounds.bottom);
	            Rect canvasBounds = canvas.getClipBounds();
	            int canvasW = canvasBounds.right - canvasBounds.left;
	            int canvasH = canvasBounds.bottom - canvasBounds.top;
	            Rect dstRect = new Rect(canvasBounds.left, canvasBounds.top, canvasBounds.left + canvasW * level / 100, canvasBounds.bottom);
	            canvas.drawBitmap(baseBitmap, srcRect, dstRect, paint1);
	        }
	        //绘制正常部分
	        {
	            Rect srcRect = new Rect(bounds.left + w * level / 100, bounds.top, bounds.right, bounds.bottom);
	            Rect canvasBounds = canvas.getClipBounds();
	            int canvasW = canvasBounds.right - canvasBounds.left;
	            int canvasH = canvasBounds.bottom - canvasBounds.top;
	            Rect dstRect = new Rect(canvasBounds.left + canvasW * level / 100, canvasBounds.top, canvasBounds.right, canvasBounds.bottom);
	            canvas.drawBitmap(baseBitmap, srcRect, dstRect, paint2);
	        }
	    }
	
	    @Override
	    public int getOpacity() {
	        return PixelFormat.TRANSLUCENT;
	    }
	
	    @Override
	    public void setAlpha(int alpha) {
	        paint1.setAlpha(alpha);
	    }
	
	    //不允许设置自己的ColorFilter
	    @Override
	    public void setColorFilter(ColorFilter colorFilter) {
	        throw new RuntimeException("Unsupported Operation");
	    }
	
	    @Override
	    public int getIntrinsicWidth() {
	        return baseDrawable.getIntrinsicWidth();
	    }
	
	    @Override
	    public int getIntrinsicHeight() {
	        return baseDrawable.getIntrinsicHeight();
	    }
	
	    //当我们只想绘制Drawable的部分区域时
	    //Bounds可用来指示Drawable的绘制范围
	    @Override
	    protected void onBoundsChange(Rect bounds) {
	        super.onBoundsChange(bounds);
	        baseDrawable.setBounds(bounds);
	        invalidateSelf();
	    }
	
	    //对于有状态变化效果的Drawable
	    //Level可用于指示动画进度
	    //Level的范围为0-100,具体怎么用,是由用户自己来决定的
	    @Override
	    protected boolean onLevelChange(int level) {
	        invalidateSelf();
	        return true;
	    }
	
	    @Override
	    public void setBounds(int left, int top, int right, int bottom) {
	        super.setBounds(left, top, right, bottom);
	        baseDrawable.setBounds(left, top, right, bottom);
	    }
	}




	package com.android.architecture;
	
	import android.content.Context;
	import android.graphics.Canvas;
	import android.graphics.Rect;
	import android.graphics.drawable.Drawable;
	import android.util.AttributeSet;
	import android.view.Gravity;
	import android.view.View;
	
	@SuppressWarnings("all")
	public class DrawableView extends View {
	
	    Drawable drawable;
	
	    //动画进度
	    int level = 0;
	    //动画方向
	    //先从左往右,到达最右侧,再从右往左
	    int positive = 1;
	
	    public DrawableView(Context context) {
	        this(context, null);
	    }
	
	    public DrawableView(Context context, AttributeSet attrs) {
	        super(context, attrs);
	        Drawable baseDrawable = context.getResources().getDrawable(R.drawable.gai_lun);
	        drawable = new HalfGreyDrawable(baseDrawable);
	        //只绘制整个图像中间80%的部分
	        //这里主要是为了演示Drawable.setBounds的作用
	        drawable.setBounds(
	                baseDrawable.getIntrinsicWidth() * 1 / 10,
	                baseDrawable.getIntrinsicHeight() * 1 / 10,
	                baseDrawable.getIntrinsicWidth() * 9 / 10,
	                baseDrawable.getIntrinsicHeight() * 9 / 10
	        );
	        //Drawable变化时,重新绘制View
	        //也可以不用Callback,直接invalidate
	        //这里主要是为了演示Drawable.invalidateSelf的刷新机制
	        drawable.setCallback(new Drawable.Callback() {
	
	            @Override
	            public void invalidateDrawable(Drawable d) {
	                invalidate();
	            }
	
	            @Override
	            public void scheduleDrawable(Drawable d, Runnable r, long t) {
	
	            }
	
	            @Override
	            public void unscheduleDrawable(Drawable d, Runnable r) {
	
	            }
	        });
	    }
	
	    @Override
	    protected void onDraw(Canvas canvas) {
	        //裁剪Canvas,只在右下角部分绘制
	        //这里主要是为了演示Canvas.clipRect的作用
	        Rect clipRect = new Rect();
	        Gravity.apply(
	                Gravity.RIGHT | Gravity.BOTTOM,
	                getMeasuredWidth() / 2,
	                getMeasuredHeight() / 2,
	                new Rect(0, 0, getMeasuredWidth(), getMeasuredHeight()),
	                clipRect
	        );
	        canvas.clipRect(clipRect);
	        //画HalfGreyDrawable
	        drawable.draw(canvas);
	        //增加Drawable动画效果
	        postDelayed(() -> {
	            level += positive;
	            if (level == 0)
	                positive = 1;
	            if (level == 100)
	                positive = -1;
	            drawable.setLevel(level);
	        }, 20);
	    }
	}



源码下载

自定义Drawable.zip

关注
打赏
1654938663
查看更多评论
立即登录/注册

微信扫码登录

0.0403s