view知识点终篇:自定义view

自定义view一直便是中高级工程师必备知识点,对于初学者来说也是一座山,翻过这座山知识储备便会有所提高。
本文不会详细总结各种自定义view的写法,在这里主要总结下自定义view的相关概念、自定义view注意要点。提供view事件体系参考文章、view的工作流程参考文章,自定义view系列文章练习,相信吧view的事件体系、工作流程弄个大概,自定义view书写便会容易多了。

一、自定义view的分类

分类标准不一(这里参考书上总结)

1、继承view重写onDraw方法

这种方式主要用于实现一些不规则的效果,即这种效果不便通过布局组合的方式来达到。往往需要动态或者静态显示一些不规则图形,很显然需要通过绘制方式实现。
注意:采用这种方式往往需要自己处理wrap_content,而且padding也要自己处理。

2、继承ViewGroup打造特殊的Layout

这种实现主要用于实除了于我们系统提供的布局以外的效果。采用这种方式复杂些需要合理处理viewGroup的测量、布局这两个过程。并同时处理子元素的测量、布局过程。

3、继承特定的view(比如:Textview)

这种方式一般是在已有的view上扩展功能(参看Button实现)
注意:比如继承Textview,我们不需要自己支持wrap_content 、padding 他已经处理

4、继承特定viewGroup(比如:LinearLayout)

这种方法也比较常见:自定义view实战之市场上app设置界面的通用SettingView
注意:这种方式也不需要自己处理测量、布局过程方便多了。与2方式区别是2更接近底层方式。

二、自定义view注意事项

自定义view讲究的是灵活性,一种效果可能有多种方式实现,这里我们要考虑代价最小、最高效这两个因素。接下来总结下注意事项。

1、让view支持wrap_content

直接继承view或者viewGroup的控件如果不在onMeasure中对onMeasure处理那么wrap_content就会是match_parent的效果。
问题由来参考这篇文章结尾处:View的工作原理(一)初认识ViewRoot、DecorView,理解MeasureSpec
解决参考:View的工作原理(二)Measure过程

2、如果有必要让你的view支持padding

1、如果直接继承view的控件如果不在onDraw(或者onMeasure)中处理padding,那么padding是无法生效的。
2、如果直接继承viewGroup的控件,需要在onMeasure、onLayout中考虑padding和子元素margain对其造成影响,不然导致padding 和子元素padding失效。
3、自定义view中可以考虑padding,自定义viewGroup可以考虑padding、margain(View不需要考虑margain这个是viewGroup才考虑的,使用已有的viewGroup时margain是生效的)

(1) view 的onMeasure中处理padding的栗子

 @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
         // 写死一个paddingStart值,实际中开发者可以根据getPaddingXXX来设置,用户没传递时,使用设置默认值
         setPadding(10,0,0,0);// 写死一个paddingStart值 控件的宽高减去这个值


        // view的宽高以及侧来那个模式
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heighthMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);

        // 用户宽高都设置为 wrap_content时
        if (widthMode == MeasureSpec.AT_MOST && heighthMode == MeasureSpec.AT_MOST) {
            setMeasuredDimension(DEFAULT_VIEW_SIZE-getPaddingStart(), DEFAULT_VIEW_SIZE-getPaddingStart());//告知系统测量,我们随便写的,这个值由自己决定。
        }
        // 当宽设置了wrap_content时  (处理宽,高使用计算值即可。)
        else if (widthMode == MeasureSpec.AT_MOST) {
            setMeasuredDimension(DEFAULT_VIEW_SIZE-getPaddingStart(), heightSize-getPaddingStart());
        }
        // 当高设置了wrap_content时  (处理高,宽使用计算值即可。)
        else  (heighthMode == MeasureSpec.AT_MOST) {
            setMeasuredDimension(widthSize-getPaddingStart(), DEFAULT_VIEW_SIZE-getPaddingStart());
        }  
        }

    }

(2)view 的onDraw中处理padding的栗子

@Override
public void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    //获取padding,然后根据实际情况处理就好
    mPaddingLeft = getPaddingLeft();
    mPaddingRight = getPaddingRight();
    mPaddingTop = getPaddingTop();
    mPaddingBottom = getPaddingBottom();
    mWidth = getWidth() - mPaddingLeft - mPaddingRight;
    mHeight = getHeight() - mPaddingTop - mPaddingBottom;
    canvas.drawXXX();
}

这种方式在官方的demo(例如TextView等控件)中使用较多

3、尽量不要在view中使用Handler

因为没必要。view提供了一系列post方法完全可以替代Handler功能。

4、view中如果有线程或者动画应及时停止

很好理解,线程或者动画需要停止时,要及时停止。
1、如果包含view的activity退出时,或者view被remove时,那么view的onDetachedFromWindow方法便会回调,我们结束相应操作即可。
2、当包含此view的activity启动时,view的onAttachedToWindow方法便会回调。
当view变得不可见时我们也要处理线程和动画,否则处理不及时也会造成内存泄漏

5、view带有滑动嵌套要处理滑动冲突

也就是滑动冲突的处理
参考:View的事件体系(四)view滑动冲突

三、文章推荐

如果我们想要简单的实现下自定义view那么我们直接采取自定义组合view或者继承已有的view,比如TextView即可。
1、自定义组合view很简单:参考文章自定义view实战之市场上app设置界面的通用SettingView
2、继承已有的view比如button的源码参考
如果我们想要实现复杂的自定义view那么最好先熟悉view的事件体系,view的工作流程。参考文章如下:

先看文章:
1、View的事件体系(一)view基础和view的几种滑动方式
2、View的事件体系(二)view的弹性滑动
3、View的事件体系(三)view的事件分发机制
4、View的事件体系(四)view滑动冲突
5、View的工作原理(一)初认识ViewRoot、DecorView,理解MeasureSpec
6、View的工作原理(二)Measure过程
7、View的工作原理(三)layout和draw过程
8、view知识点终篇:自定义view

这些文章本人总结于《按住开发艺术探索》,读此书所总结的笔记

在做练习:
1、闹钟练习实战栗子
2、自定义view系列文章集合这个可以当字典用里面好多栗子可以选一些练习实战下

ps:这两篇文章可是刚哥知识星球自定义view学习推荐的哦,里面学习路线初级、高级、专家都有,跟着路线走方向不错哈哈(真心感受)。。。

四、小结

view的事件系列就此总结完毕,中间有些东西还是不很理解(ViewGroup的事件分发源码,及其ViewGroup的Measure过程比较复杂),就此先记下吧,有了印象,以后有了新的理解,或者之前总结有误再回来修改吧。总体来说感觉自己入门了,稍作练习必定会更加熟练吧。。。。。溜了溜了还有更多的知识点等待学习,任重而道远啊。

The end

本文参考<安卓开发艺术探索>

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值