Android 自定义view之 Xfermode 制作动态文字加载动画

对于Xfermode 可能很多人看了一些就放弃了,今天我就个人理解,举简单的我们生活中的例子,让大家更容易理解这是个什么东西。其实并不是你们想象的那么难,你只要懂三步就够了。先来看一看这次的效果图,这个gif大家凑合看。

                                         

不要把Xfermode 想的这么难,我把Xfermode 理解成中学时 学的“集合” ,我们知道“集合”是处理 数据的。例如:

集合 A={1,2,3,4},集合B={3,4,5,6}。这两个集合 有三个属性,交集并集补集

那么 Xfermode 我个人理解就是图形集合,就是图形A,图形B 之间可以取,交集并集补集。当然这个 A和 B 之间取那种类型,形成什么样的 效果,其实就是我们选取的 Xformode 的 属性类型。

这个就引出了我们今天 的 第一步,虽然是三步,但是前提是你要对自定义view 有一定的了解比如你要知道 ondraw(),onmesure(),Paint 画笔,canvars画布这些内容你要了解,对自定义不是很清楚的朋友可以去 看我的同类文章,文章从入门一步一步带大家进入自定义view:

第一步:我们要熟悉一下这个图

                                           

16个图形结果,其实现在有18中。这个图 我们也不用记,只要在用的时候选择对应得 我们的目标图形就行了。具体怎么使用 我们要引出我们今天主要的类 PorterDuffXfermode这个类就是我们的Xformode 的类了,他还有另外被废弃的两兄弟,被废弃了就不谈了。既然是各类我们要使用就要创建对象,如下:

PorterDuffXfermode xfermode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);

一定不要忘了有些手机会出问题需要硬件加速:view.setLayerType(View.LAYER_TYPE_SOFTWARE, null);

这里就是我们的 对象,在这里他的构造参数中就是我们上图 选择的类型,最终图形是两个图形的交集部分。当然你可以根据你的目标图形 的效果自己选择,两个图片的混排类型。

这就是 第一步,我们只要了解一下图片的意义,和 PorterDuffXfermode这个类的用法就够了。我这里提到的 所有图不只是图片,还有我们绘制出来的 圆,矩形等绘制的图。

第二步:

我们了解了 图形 混排的模式,所以第二步我们要有两个图,不然怎么混排,从图中我们可以看出这两个图,分别是 Src ,Dst。接下来我会介绍这两个名字对应我们手机上那个图形。因为我们要画图所以 我们就要来到 ondraw()方法了,这个方法有个类叫canvas 图层,所以这就到了我们第二步的关键点:那就是设置图层,调用方法

canvas.saveLayer( left, top, right, bottom, paint, saveFlags)

首先前四个方法比较简单,就是我们要设置这个图层 的大小,第5个方法就是我们的 画笔,第6个方法我们使用:Canvas.ALL_SAVE_FLAG  ,这是一个 flag。

注意:我们在绘制图形之前必须调用上面的方法,不然没有效果。

下面是这个绘制的先后顺序:

/**
* 设置图层
*/
int layer = canvas.saveLayer(0,0,w,h,paint,Canvas.ALL_SAVE_FLAG);
//绘制背景图片
canvas.drawBitmap(bitmap,0,0,paint);
//设置 xformode 模式
paint.setXfermode(xfermode);
//绘制矩形
paint.setColor(Color.RED);
RectF rectF = new RectF(0,y,bitmap.getWidth(),bitmap.getHeight());
canvas.drawRect(rectF,paint);
//最后设置为空
paint.setXfermode(null);
canvas.restoreToCount(layer);

 

第三步:

第三步我们还是围绕着上边的代码讲,因为就这几行代码,因为很简单。设置好图层之后,就要绘制图形了,我们这里用canvas绘制了一个 bitmap 图片。大家注意了我们此时 用的 paint 只是普通的 画笔,到这个时候我们的 PorterDuffXfermode模式还没有使用呢!

再往下看 我们的画笔调用了:

paint.setXfermode(xfermode);

这个方法,所以 如果我们再绘制图形的画,再用到的 画笔 就和我们之前 绘制的图形 不一样了。这个方法可以说是一个分界点,在这个方法之前绘制的图形 和 之后绘制的图形 就分别对应了 我们 图中 Src 和 Dst 的图。这就决定我们最终的目标图形是什么样的。

最后就是 把画笔 的 xformode 模式设置为空。再调用 canvas 的这个方法

canvas.restoreToCount(layer);

 

我们的绘制就结束了。我这里使用动画动态的改变了 矩形 的高度。我把这个 图片 贴给大家,图片还是盗 别人的。哈哈。

                                                     

                                                                             大家可以下载使用。

把代码也贴出来,大家参考。以上 都是我个人的理解 ,包括给大家举的例子,如果有不妥之处请指出,谢谢。

 

public class XformodeView extends View {

    Paint paint ;
    //屏幕宽高
    int w;
    int h;
    //定义一个矩形的高度变化
    float y;
    //xformode 的 类型 选择
    PorterDuffXfermode xfermode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);
    //图片
    Bitmap bitmap;
    public XformodeView(Context context) {
        this(context,null);
    }

    public XformodeView(Context context, @Nullable AttributeSet attrs) {
        this(context,attrs,0);
    }

    public XformodeView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        //画笔
        paint = new Paint();
        paint.setAntiAlias(true);
        paint.setDither(true);
        init(context);
    }

    /**
     * 初始化
     * @param context
     */
    public void init(Context context){
        //获得屏幕宽高
        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        w = wm.getDefaultDisplay().getWidth();
        h = wm.getDefaultDisplay().getHeight();
        //加载bitmap 图片
        bitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.xxx);
        //开始动画
        animator();
    }

    /**
     * 测量view
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        setMeasuredDimension(bitmap.getWidth(),bitmap.getHeight());
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        /**
         * 绘制 图片 剪切 画布 控制图片显示
         */
//        Path path = new Path();
//        path.moveTo(0,y);
//
//        path.lineTo(bitmap.getWidth(),y);
//        path.lineTo(bitmap.getWidth(),bitmap.getHeight());
//        path.lineTo(0,bitmap.getHeight());
//        canvas.clipPath(path);

        /**
         * 设置图层
         */
        int layer = canvas.saveLayer(0,0,w,h,paint,Canvas.ALL_SAVE_FLAG);
        //绘制背景图片
        canvas.drawBitmap(bitmap,0,0,paint);
        //设置 xformode 模式
        paint.setXfermode(xfermode);
        //绘制矩形
        paint.setColor(Color.RED);
        RectF rectF = new RectF(0,y,bitmap.getWidth(),bitmap.getHeight());
        canvas.drawRect(rectF,paint);
        //最后设置为空
        paint.setXfermode(null);
        canvas.restoreToCount(layer);
    }

    /**
     * 动画
     */
    public void animator(){

        ValueAnimator animator = ValueAnimator.ofFloat(bitmap.getHeight(),0);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                y = (float) animation.getAnimatedValue();
                invalidate();
            }
        });
        animator.setDuration(3000);
        animator.start();
    }
}

你也可以做一些 复杂的 效果 比如 你不用矩形,你可以用 波浪 的效果 让他 充满。发挥想象力去做吧。

纠正理解

在绘制图形剪切效果时,不生效的问题,要让我们相互影响的src ,dst生成bitmap,然后绘制,才能生效,否则,不会生效。

        int l = canvas.saveLayer(0,0,width,height,paint,Canvas.ALL_SAVE_FLAG);
        canvas.drawBitmap(drawCicle(),0,0,paint);
        paint.setXfermode(xfermode);
        canvas.drawBitmap(bitmap,0,0,paint);
        canvas.restoreToCount(l);
        paint.setXfermode(null);
    private Bitmap drawCicle(){
        Bitmap bp = Bitmap.createBitmap(width,height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bp);
        path.rewind();
        path.addCircle(sr,sr,radius, Path.Direction.CCW);
        canvas.drawPath(path,paint);
        return bp;
    }

https://github.com/WangRain1/BitmapLIneSmoothView

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WangRain1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值