自定义view学习指南

自定义View主要掌握以下四块内容:
1. 绘制机制:掌握onMeasure,onLayout,onDraw及相关类的使用。
公共技术点之 View 绘制流程
Android View的绘制流程
郭霖的Android视图绘制流程完全解析,带你一步步深入了解View(二)
2. 事件传递机制:掌握dispathTouchEvent(),onInterceptEvent(),onTouchEvent()三者的相关逻辑.
3. 属性动画,因为属性动画核心是对数值的变化,使用属性动画对值View做动画操作。
4. 相关手势类。

不要在onDraw里new东西。一般paint,path要在构造方法里来new,path重置可以在ondraw里来reset。

动画

《Animation动画详解》

Android 属性动画:这是一篇很详细的 属性动画 总结&攻略

Window相关

DecorView为整个Window界面的最顶层View
DecorView只有一个子元素为LinearLayout。代表整个Window界面,包含通知栏,标题栏,内容显示栏三块区域。
LinearLayout里有两个FrameLayout子元素。
标题栏显示界面。只有一个TextView显示应用的名称。也可以自定义标题栏,载入后的自定义标题栏View将加入FrameLayout中。
内容栏显示界面。就是setContentView()方法载入的布局界面,加入其中。

DecorView(FrameLayout)-LinearLayout-FrameLayout-TextView/自定义(ActionBar):标题栏
-FrameLayout(contentView):内容栏

这里写图片描述

基础

安卓中的坐标系


MotionEvent中的getRawX()、getRawY()与getX()、getY()取得触摸点在X轴与Y轴上的距离,这四个方法都返回一个float类型的参数,单位为像素(Pixel)。getRawX()、getRawY()返回的是触摸点相对于屏幕的位置,而getX()、getY()返回的则是触摸点相对于View的位置。

这里写图片描述

getScrollX()与getScrollY()的值由调用View的scrollTo(int x, int y)或者scrollBy(int x, int y)产生,其中scrollTo是将View中的内容移动到指定的坐标x、y处,此x、y是相对于

View的左上角,而不是屏幕的左上角。scrollBy(int x, int y)则是改变View中的相对位置,参数x、y为距离上一次的相对位置。

这里写图片描述

值得注意的是,当View中的内容向右移动时,getScrollX()的值为负数,同理,向scrollTo与scrollBy的x中传入负数,view中的内容向右移动,反之向左。

当View中的内容向下移动时,getScrollY()的值为负数,同理,向scrollTo与scrollBy的y中传入负数,view中的内容向下移动,反之向上。

参考:图解MotionEvent中getRawX、getRawY与getX、getY以及View中的getScrollX、getScrollY

角度与弧度

颜色

其他
Android动画坐标系详解
android动画坐标定义

取色器
PicPick

进阶

安卓自定义View进阶-分类与流程

分类与流程

安卓自定义View进阶-Canvas之绘制图形

安卓自定义View进阶-Canvas之画布操作

安卓自定义View进阶-Canvas之图片文字

安卓自定义View进阶-Path之基本操作

安卓自定义View进阶-Path之贝塞尔曲线

安卓自定义View进阶-Path之完结篇

安卓自定义View进阶-PathMeasure

安卓自定义View进阶-Matrix原理

安卓自定义View进阶-Matrix详解

安卓自定义View进阶-Matrix Camera

安卓自定义View进阶-事件分发机制原理

安卓自定义View进阶-事件分发机制详解

安卓自定义View进阶-MotionEvent详解

安卓自定义View进阶-特殊控件的事件处理方案

其他学习资源:

自定义View有这些足够了

爱哥自定义控件其实很简单
GcsSloop安卓学习笔记
启舰 Android自定义控件三部曲文章索引

view的draw方法绘制流程:

canvas画图放置位置的影响效果:

参考:扔物线 : HenCoder Android 自定义 View 1-5: 绘制顺序

MyView

public class MyView extends View {
    public MyView(Context context) {
        super(context);
    }

    public MyView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // 绘制代码写在 super.onDraw() 的上面还是下面都无所谓,
        // 甚至,你把 super.onDraw() 这行代码删掉都没关系,效果都是一样的
        // —因为在 View 这个类里,onDraw() 本来就是空实现
    }
}

MyViewGroup

public class MyViewGroup extends ViewGroup {

    public MyViewGroup(Context context) {
        super(context);
    }

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

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

    @Override
    public void onDrawForeground(Canvas canvas) {
        super.onDrawForeground(canvas);
    }

    //一个完整的绘制过程会依次绘制以下几个内容:
//    1、背景:drawBackground() , 但这个方法是 private 的,不能重写,
//       只能用自带的 API 去设置(xml 布局文件的 android:background 属性
//       以及 Java 代码的 View.setBackgroundXxx() 方法
//    2、主体(onDraw())
//    3、子 View(dispatchDraw())
//    4、滑动边缘渐变和滑动条
//    5、前景:4、5 两步——滑动边缘渐变和滑动条以及前景,
//      这两部分被合在一起放在了 onDrawForeground() 方法里,这个方法是可以重写的。

    @Override
    protected void onDraw(Canvas canvas) {
        // 绘制写在上面:很少见,可绘制背景
        // ViewGroup覆盖绘制

        super.onDraw(canvas);

        // 绘制写在下面:为ViewGroup增加点缀性内容。
        // 绘制覆盖ViewGroup
    }

    // 在绘制过程中,每个 View 和 ViewGroup 都会先调用 onDraw() 方法来绘制主体,
    // 再调用 dispatchDraw() 方法来绘制子 View。

    // 虽然 View 和 ViewGroup 都有 dispatchDraw() 方法,不过由于 View 是没有子 View 的,
    // 所以一般来说 dispatchDraw() 这个方法只对 ViewGroup(以及它的子类)有意义。

    @Override
    protected void dispatchDraw(Canvas canvas) {

        //绘制写在super.dispatchDraw(canvas);上面 ==等价于== 绘制写在super.onDraw(canvas);下面

        super.dispatchDraw(canvas);

        //绘制写在下面:为ViewGroup增加点缀性内容。
    }
}

paint相关方法:

这里写图片描述

//着色器
Paint的setShader(Shader shader)
    private Shader shader;
    //子类
    private BitmapShader bitmapShader;
    private ComposeShader composeShader;
    private LinearGradient linearGradient;
    private RadialGradient radialGradient;
    private SweepGradient sweepGradient;

//图像混合模式
Paint的setXfermode(Xfermode xfermode)
    private Xfermode xfermode;
    //子类
    private AvoidXfermode avoidXfermode;//已废弃
    private PixelXorXfermode pixelXorXfermode;//已废弃
    private PorterDuffXfermode porterDuffXfermode;

//颜色过滤
Paint的setColorFilter(ColorFilter filter)
    private ColorFilter colorFilter;
    //子类
    private ColorMatrixColorFilter colorMatrixColorFilter;
    private LightingColorFilter lightingColorFilter;
    private PorterDuffColorFilter porterDuffColorFilter;

//遮罩滤镜
Paint的setMaskFilter(MaskFilter maskfilter)
    private MaskFilter maskFilter;
    //子类
    private BlurMaskFilter blurMaskFilter;//模糊遮罩滤镜
    private EmbossMaskFilter embossMaskFilter;//浮雕遮罩滤镜

//给path设置样式(效果)
Paint的setPathEffect(PathEffect effect)
    private PathEffect pathEffect;
    //子类
    private CornerPathEffect cornerPathEffect;
    private DiscretePathEffect discretePathEffect;
    private DashPathEffect dashPathEffect;
    private PathDashPathEffect pathDashPathEffect;
    private ComposePathEffect composePathEffect;
    private SumPathEffect sumPathEffect;

混合模式

PorterDuff.Mode表示混合模式,枚举值有18个,表示各种图形混合模式,有:
目标图DST: 矩形,源图SRC:圆形

canvas相关方法:

这里写图片描述

这里写图片描述

这里写图片描述

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值