自定义View时,用到Paint Canvas的一些温故,讲讲平时一些效果是怎么画的(基础篇 二,图像遮盖,Canvas静态变化)

转载请注明出处:王亟亟的大牛之路

上一篇把简单的一些概念理一理,还画了个圈,那这一篇讲一下图像遮盖“Xfermode”和Canvas的旋转。平移等效果

Xfermode:

AvoidXfermode 指定了一个颜色和容差,强制Paint避免在它上面绘图(或者只在它上面绘图)。

PixelXorXfermode 当覆盖已有的颜色时,应用一个简单的像素异或操作。

PorterDuffXfermode 这是一个非常强大的转换模式,使用它,可以使用图像合成的16条Porter-Duff规则的任意一条来控制Paint如何与已有的Canvas图像进行交互。

我们今天的呈现就是在PorterDuffXfermode 这部分实现的

PorterDuff.Mode为枚举类,一共有16个枚举值分别是

1.PorterDuff.Mode.CLEAR
所绘制不会提交到画布上。
2.PorterDuff.Mode.SRC
显示上层绘制图片
3.PorterDuff.Mode.DST
显示下层绘制图片
4.PorterDuff.Mode.SRC_OVER
正常绘制显示,上下层绘制叠盖。
5.PorterDuff.Mode.DST_OVER
上下层都显示。下层居上显示。
6.PorterDuff.Mode.SRC_IN
取两层绘制交集。显示上层。
7.PorterDuff.Mode.DST_IN
取两层绘制交集。显示下层。
8.PorterDuff.Mode.SRC_OUT
取上层绘制非交集部分。
9.PorterDuff.Mode.DST_OUT
取下层绘制非交集部分。
10.PorterDuff.Mode.SRC_ATOP
取下层非交集部分与上层交集部分
11.PorterDuff.Mode.DST_ATOP
取上层非交集部分与下层交集部分
12.PorterDuff.Mode.XOR
异或:去除两图层交集部分
13.PorterDuff.Mode.DARKEN
取两图层全部区域,交集部分颜色加深
14.PorterDuff.Mode.LIGHTEN
取两图层全部,点亮交集部分颜色
15.PorterDuff.Mode.MULTIPLY
取两图层交集部分叠加后颜色
16.PorterDuff.Mode.SCREEN
取两图层全部区域,交集部分变为透明色

在将这一系列的效果之前我们先把我们昨天画圆的例子改一下

public class TestView extends View {
    Paint paint;
    Context context;
    Bitmap bitmap;

    public TestView(Context context) {
        super(context);
        this.context = context;
    }

    public TestView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }

    public TestView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public TestView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs) {
        paint = new Paint();
//        paint.setColor(getResources().getColor(R.color.SlateBlue));
        paint.setColor(getResources().getColor(R.color.Gold));
        paint.setStrokeWidth(3);                        //粗细
        paint.setAntiAlias(true);                       //设置画笔为无锯齿
        bitmap= BitmapFactory.decodeResource(getResources(),R.drawable.bg);

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Log.d("--->onDraw", "onDraw()");
//        canvas.drawCircle(0, 0, 90, paint);
        canvas.drawBitmap(bitmap,0,0,paint);
        canvas.drawCircle(100, 100, 90, paint);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        Log.d("--->onLayout", "changed = " + changed + " left = " + left + " top = " + top + " right = " + right + " bottom " + bottom);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        Log.d("--->onMeasure", "  widthMeasureSpec =" + widthMeasureSpec + "  heightMeasureSpec = " + heightMeasureSpec);
        setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
    }
}

我们在画圆之后又画了个背景图,效果如下:

在我们的圆下面有一个妹子,并且圆是会盖掉妹子那一块圆的涂抹面积的。

那我们把onDraw()方法里执行的顺序换一下呢?

   @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Log.d("--->onDraw", "onDraw()");
//        canvas.drawCircle(0, 0, 90, paint);
          canvas.drawCircle(100, 100, 90, paint);
          canvas.drawBitmap(bitmap,0,0,paint);
    }

如果改成这样,我们的圆就没了(效果不贴了)

利用PorterDuff.Mode就可以很好的解决这个问题当然,可能你得多绘制一次然后再做覆盖的操作了,所以在你决定先画什么后画什么之前一定理清谁在前谁在后

本来想写个大致的例子,但是想想16个都好麻烦,就拿了一个市面上比较多的图吧


Canvas静态变化

上面的代码不变,我们在新建一个Canvas然后把他里面话一点东西,来模拟我们想要的效果。

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Log.d("--->onDraw", "onDraw()");
//        canvas.drawCircle(0, 0, 90, paint);
        canvas.drawCircle(100, 100, 90, paint1);
        canvas.drawBitmap(bitmap, 120, 120, paint1);
        Canvas canvas1=new Canvas(bitmap);

        Paint paint2=new Paint();
        paint2.setColor(getResources().getColor(R.color.LightPink));
        paint2.setTextSize(50);
        canvas1.drawText("Ezreal", 0, 200, paint2);

        canvas1.drawText("Malzahar ",0,300,paint2);
    }

效果如下:

P1.我们用画布又画了2个字。那么我们来试下各种效果(分析和方法,会分两部分罗列)

平移:1.void translate(float dx, float dy)

平移参数:2个坐标点X正向右 Y正向下,负数反之。

旋转
1.void rotate(float degrees)
2.void rotate (float degrees, float px, float py)

旋转参数:以坐标原点(左上)为旋转中心转degrees度(正的为正转,负的为反转),px,py为以(px,py)为中心旋转degrees度.

缩放
1.public void scale (float sx, float sy)
2.public final void scale (float sx, float sy, float px, float py)

缩放参数:sx为水平缩放,1表示不便,大于1放大,小与1缩小(负的我没试过);sy则表示垂直,逻辑同水平.

斜切

1.void skew (float sx, float sy)

斜切参数:sx:将画布在x方向上倾斜相应的角度,sx倾斜角度的tan值;sy:将画布在y轴方向上倾斜相应的角度,sy为倾斜角度的tan值.



P2.实现以及解释:

1.平移:

肉眼看来我们的2个字偏移了canvas1.translate(300,300);的位置,效果类似于 2个字体本身的坐标(X坐标+300,Y坐标+300)。

但是 效果是这样吗?

为了验证确实如此我们再再右侧画一个“Akali”

//并且是在平移前执行
canvas1.drawText("Akali ",200,400,paint2);

然后我们在平移之后再画一个Katarina Du Couteau

并且跟平移前的阿卡丽是用以坐标

  canvas1.drawText("Katarina Du Couteau ", 200, 400, paint2);

效果是卡特跟着整个坐标系走了而不是之前的坐标相加的结果。

所以:

1.每次调用canvas.drawXXXX系列函数来绘图进,都会产生一个全新的Canvas画布。
2.在Canvas与屏幕合成时,超出屏幕范围的图像是不会显示出来的。

2.旋转

我们还是回到最初的蚂蚱和EZ的样子

  @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Log.d("--->onDraw", "onDraw()");
//        canvas.drawCircle(0, 0, 90, paint);
        canvas.drawCircle(100, 100, 90, paint1);
        canvas.drawBitmap(bitmap, 120, 120, paint1);
        Canvas canvas1 = new Canvas(bitmap);

        Paint paint2 = new Paint();
        paint2.setColor(getResources().getColor(R.color.LightPink));
        paint2.setTextSize(50);
//        canvas1.drawText("Akali ", 200, 400, paint2);

//        canvas1.translate(300, 300);
        canvas1.drawText("Ezreal", 0, 200, paint2);
        canvas1.rotate(30);
        canvas1.drawText("Malzahar ", 0, 300, paint2);

//        canvas1.drawText("Katarina Du Couteau ", 200, 400, paint2);
    }

然后把蚂蚱旋转30度,效果如图

EZ位置没变,蚂蚱转了,并且有一部分超出了我们的妹子Bitmap所以它不见了。

然后此时此刻,我们的阿卡丽回来了,并且在蚂蚱之后

我们的啊卡里也跟着蚂蚱转走了,说明旋转和平移是一样的整个位图转走了。

如下图向着箭头方向偏了30度然后创建了一个新的Canvas

3.缩放

缩放的图我就不画了,代码就是canvas.scale(1, 1.5f); 就是Y方向缩放1.5f

也是重绘了一个Canvas和上面都一样。

4.斜切
其实也就是可以实现我们的一个斜体的效果,这里就贴一下执行效果

还有就是int save () void restore()相对比较简单,对堆栈的概念清晰的小伙伴一看就懂,不需要过多试验,这里就不明说了。

时间: 2024-10-15 09:35:52

自定义View时,用到Paint Canvas的一些温故,讲讲平时一些效果是怎么画的(基础篇 二,图像遮盖,Canvas静态变化)的相关文章

Android自定义View研究--View中的原点坐标和XML中布局自定义View时View触摸原点问题

这里只做个汇总~.~独一无二 文章出处:http://blog.csdn.net/djy1992/article/details/9715047 Android自定义View研究--View中的原点坐标相关问题 我们自定义了View,但是有没想过一个问题,就是View中的(0,0)坐标,也就是原点坐标在哪??我们是不是有时候很困惑,接下来我们就来研究View中的原点坐标相关的问题. 一.new DuView时View的原点 我们通过从View中绘制一条从原点到右下角的线来看看这个View中的原点

Android 自定义View时使用TypedArray配置样式属性详细介绍_Android

 Android 自定义View时使用TypedArray配置样式属性详细介绍       在自定义view时为了提高复用性和扩展性,可以为自定义的view添加样式属性的配置,比如自定义图片资源.文字大小.控件属性等,就这需要用到TypedArray类,下面以一个自定义的可点击扩展和收缩的TextView为例记录下这个类的简单使用. 先上效果图: 点击以后为 再贴代码: 1.自定义view类: /** * @title ExpandTextView * @description 可扩展TextV

Android 自定义View时使用TypedArray配置样式属性详细介绍

Android 自定义View时使用TypedArray配置样式属性详细介绍 在自定义view时为了提高复用性和扩展性,可以为自定义的view添加样式属性的配置,比如自定义图片资源.文字大小.控件属性等,就这需要用到TypedArray类,下面以一个自定义的可点击扩展和收缩的TextView为例记录下这个类的简单使用. 先上效果图: 点击以后为 再贴代码: 1.自定义view类: /** * @title ExpandTextView * @description 可扩展TextView,可以通

自定义View时,用到Paint Canvas的一些温故,只有想不到没有做不到(实例 1,画一个简单的Activity并且实现他能实现的)

转载请注明出处:王亟亟的大牛之路 这两天都在写Paint Canvas 昨天前天都写的比较基础的一些只是和一些简单的Demo演示,那今天就写一个"大气磅礴的"(之前几篇没看的可以看下传送门:http://blog.csdn.net/ddwhan0123/article/details/50426935) 废话不多,先上效果 YE? 为什么贴2个一模一样的试图,你错了!不带toCopy按钮的那整个Activity都是画的,并且还有点击事件哦! 再贴一下2张图片(上面张为原图,下面一张为效

自定义View时,用到Paint Canvas的一些温故,自定义Loading控件(动画五,“六边形”的旋转跳跃)

转载请注明出处:王亟亟的大牛之路 最近的一系列文章都是些的自定义控件的绘制,动画等效果,这一片就直接做一个自定义view,上一篇的地址:http://blog.csdn.net/ddwhan0123/article/details/50477030(没看的小伙伴可以看下) 照惯例,贴下演示效果 包结构: 设计分析 黄色为整个控件的整体,绿色部分为绘画出来的六边形,蓝色为一个标准的TextView 问题,为什么不把控件做在一起? 一开始有考虑过直接paint一整个控件把六边形和文字都画出来,想想还

自定义View时,用到Paint Canvas的一些温故,简单的帧动画(动画一 ,"掏粪男孩Gif"顺便再提提onWindowFocusChanged)

转载请注明出处:王亟亟的大牛之路 之前在绘画的过程中提到了静态的旋转啊,缩放啊,平移等一些效果.那么自定义的View当然也有动态的效果也就是我们的Animation,常用的有三种 View Animation Drawable Animation Property Animation 这一篇讲一下简单的Drawable Animation. Drawable Animation实现好是什么个样子呢? 帧动画,一张一张的图片,一次播形成动画的景象. 效果就是如此,把一帧一帧的图品相机播放,形成动画

自定义View时,用到Paint Canvas的一些温故,简单的View Animation(动画二,“大大姐”的简单变动)

转载请注明出处:王亟亟的大牛之路 上一篇讲了 Drawable Animation ,这一篇说的使用简单的View Animation,下一篇将会做一些深化的东西,上一篇的地址:http://blog.csdn.net/ddwhan0123/article/details/50457161(没看的小伙伴可以看下) 运行效果: 包结构: 一般来说动画需要以下属性: 1.初始状态: 2.结束状态: 3.持续时间: 4.Interpolator(插值器) 前几项的字面意思一目了然,最后一项是干什么呢?

自定义View时,用到Paint Canvas的一些温故,PropertyAnimation中的ObjectAnimator(动画三,“大大姐”的旋转跳跃)

转载请注明出处:王亟亟的大牛之路 上一篇讲了一些比较基础的view Animation 这篇会选PropertyAnimation的部分功能来讲一下,因为它的子类还是蛮多的,希望分的篇幅多点,然后可以讲细点 先上一下跑的效果(gif吃动画,见谅,大家可以自己run下) 这篇主要会讲以下几部分 - ObjectAnimator - AnimatorSet - PropertyValuesHolder 以及与之相关的一些知识点 Property Animation相对于我们昨天的View Anima

Android零基础入门第24节:自定义View简单使用

原文:Android零基础入门第24节:自定义View简单使用 当我们开发中遇到Android原生的组件无法满足需求时,这时候就应该自定义View来满足这些特殊的组件需求.   一.概述 很多初入Android开发的程序员,对于Android自定义View可能比较恐惧,但这又是高手进阶的必经之路,这里先不做过多学习,只是简单了解.关于高阶的内容会在后续课程陆续进行学习,欢迎关注分享达人秀(ShareExpert)获取第一手教程. 如果说要按类型来划分的话,自定义View的实现方式大概可以分为三种