自定义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 属性动画:这是一篇很详细的 属性动画 总结&攻略
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自定义控件三部曲文章索引
参考:扔物线 : HenCoder Android 自定义 View 1-5: 绘制顺序
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() 本来就是空实现
}
}
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的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:圆形