【5年Android从零复盘系列之六】Android自定义View(1):基础详解(图文)
发布日期:2021-06-29 18:17:35
浏览次数:3
分类:技术文章
本文共 6567 字,大约阅读时间需要 21 分钟。
1.基础一:坐标计算
1.1 Android窗口坐标系计算以屏幕左上角为原点,
向右为X轴正向,向下为Y轴正向
1.2 View坐标系
【注意获取的坐标是像素值,不是dp值】
【注意获取的坐标是像素值,不是dp值】 【注意获取的坐标是像素值,不是dp值】//获取View内部相对的坐标值(距离)getX()、getY()//获取View相对父View的相对坐标值(距离)getLeft()、getTop()、getRight()、getBottom()//获取的是屏幕中的实际坐标值(距离)getRawX()、getRawY()
图中activity指全屏窗口,严格的讲应该是屏幕
1.3 实际开发使用场景
1.获取View的宽高【应在View绘制完成后调用】
width = getRight() - getLeft();height = getBottom() - getTop();
2.获取View在父view中的左上角坐标【应在View绘制完成后调用】
Point point = new Point();point.set(ivState.getLeft() ,ivState.getTop());
3.获取View在父view中心点坐标【应在View绘制完成后调用】
Point point = new Point();point.set(ivState.getRight() - ivState.getLeft() ,ivState.getBottom() - ivState.getTop());
2. 自定义属性
2.1 构造函数&初始化属性
public class MDButton extends Button { //java动态创建view时调用 public MDButton(Context context) { super(context); initInnerView(context); } //xml布局初始化时调用 public MDButton(Context context, AttributeSet attrs) { super(context, attrs);// initInnerView(context);//组合式自定义View(即ViewGroup)时,需初始化内部子view; 扩展式自定义View不需要调用 initAttrs(context, attrs); } //有默认style时,在MDButton(Context context, AttributeSet attrs)中调用MDButton(context,attrs,defStyleAttr); public MDButton(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr);// initInnerView(context);//组合式自定义View(即ViewGroup)时,需初始化内部子view; 扩展式自定义View不需要调用 initAttrs(context, attrs); } //只有在API版本>21时才会用到 //有默认style时,在MDButton(Context context, AttributeSet attrs)中调用MDButton(context,attrs,defStyleAttr); @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) public MDButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes);// initInnerView(context);//组合式自定义View(即ViewGroup)时,需初始化内部子view; 扩展式自定义View不需要调用 initAttrs(context, attrs); } //组合式自定义View(即ViewGroup)时,需初始化内部子view; 扩展式自定义View不需要调用 private void initInnerView(Context context) { //... } private void initAttrs(Context context, AttributeSet attrs) { //... }}
2.2 自定义属性
1.在module中的/res/values/attrs.xml编写属性&类型;
2.自定义View类中获取属性值,并使用
public class MDButton extends Button { //组合式自定义View(即ViewGroup)时,需初始化内部子view; 扩展式自定义View不需要调用 private void initInnerView(Context context) { //... } private void initAttrs(Context context, AttributeSet attrs) { //1.获取属性数组 TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MDButton); //2.获取属性值 Drawable bgDrawable = typedArray.getDrawable(R.styleable.MDButton_mdb_bg); int txtColor = typedArray.getInteger(R.styleable.MDButton_mdb_txt_color,Color.parseColor("#808080")); String txt = typedArray.getString(R.styleable.MDButton_mdb_txt); boolean isAutoAnim = typedArray.getBoolean(R.styleable.MDButton_mdb_auto_anim, false); float fraction = typedArray.getFraction(R.styleable.MDButton_mdb_anim_pivotX, 1, 1, 1.0f); float alpha = typedArray.getFloat(R.styleable.MDButton_mdb_auto_anim_alpha , 1.0f); float minWidth = typedArray.getDimension(R.styleable.MDButton_mdb_min_width, 32.0f); int sizeType = typedArray.getInt(R.styleable.MDButton_mdb_size, 1);//0=small 1=normal 2=big int radiusCorner = typedArray.getInt(R.styleable.MDButton_mdb_radius_corner ,0); int delay = typedArray.getInt(R.styleable.MDButton_mdb_auto_anim_delay ,0); Log.e("bgDrawable",""+bgDrawable); Log.e("txtColor",""+txtColor); Log.e("txt",""+txt); Log.e("isAutoAnim",""+isAutoAnim); Log.e("fraction",""+fraction); Log.e("alpha",""+alpha); Log.e("minWidth",""+minWidth); Log.e("sizeType",""+sizeType); Log.e("radiusCorner",""+radiusCorner); Log.e("delay",""+delay); Log.e("==============","========================================="); //3.属性值 设置到 对应属性 setText(txt); //tv.setDelay(delay); //... //4.释放 typedArray.recycle(); } //java动态创建view时调用 public MDButton(Context context) { super(context); initInnerView(context); } //xml布局初始化时调用 public MDButton(Context context, AttributeSet attrs) { super(context, attrs);// initInnerView(context);//组合式自定义View(即ViewGroup)时,需初始化内部子view; 扩展式自定义View不需要调用 initAttrs(context, attrs); } //有默认style时,在MDButton(Context context, AttributeSet attrs)中调用MDButton(context,attrs,defStyleAttr); public MDButton(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr);// initInnerView(context);//组合式自定义View(即ViewGroup)时,需初始化内部子view; 扩展式自定义View不需要调用 initAttrs(context, attrs); } //只有在API版本>21时才会用到 //有默认style时,在MDButton(Context context, AttributeSet attrs)中调用 @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) public MDButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes);// initInnerView(context);//组合式自定义View(即ViewGroup)时,需初始化内部子view; 扩展式自定义View不需要调用 initAttrs(context, attrs); }}
3.在布局文件.xml中使用控件,【注意变量组设置的数据&单位】
** 附 :属性值获取正确性验证**
3.自定义View分类
3.1 组合式
顾名思义,即xml文件中根布局使用RelativeLayout(同理其他布局控件),
内部使用其他View控件,布局摆放,组合成XxxView的原始布局。 然后,Java类继承根布局标签对应的容器类,覆写构造函数,并初始化各子View的变量。 是最常用、最稳妥、不易产生过度绘制、内存泄漏等问题。3.2 继承覆写、衍生/扩展
简而言之,即 如继承Button,修改默认background、state_press状态时按钮elevation值、取消默认最小高度56dp等。
也是最常用的、直接扩展/修改原生View功能3.3 自绘式
强烈建议:熟悉View的绘制、Android事件传递、手势处理再入手自绘式。
方式:直接继承View ,重写绘制流程三步骤
- measure() 测量
- layout() 布局计算摆放坐标
- draw() 绘制
4.View的生命周期
View的生命周期,关联Activity联动时的函数调用顺序
- 【View】构造方法
- 【View】onFinishInflate()
- 【Activity】 onCreate()
- 【Activity】onStart()
- 【Activity】onResume()
- 【View】onAttachedToWindow()
- 【View】onMeasure() (可能调用n次)
- 【View】onSizeChanged() (可能调用n次)
- 【View】onLayout() (可能调用n次)
- 【View】onDraw() (可能调用n次)
- 【View】onWindowFocusChanged() (调用Activity.onPause()前,被调用,hasWindowFocus==false)
- 【Activity】onPause()
- 【Activity】onStop()
- 【Activity】onDestroy()
- 【View】onDetachedFromWindow
转载地址:https://cupster.blog.csdn.net/article/details/112055331 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
表示我来过!
[***.240.166.169]2024年04月14日 19时13分33秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
开发团队里是否需要测试人员?
2019-04-30
深入理解java虚拟机 精华总结(面试)
2019-04-30
Java中String类的方法及说明
2019-04-30
IntelliJ IDEA - 热部署插件JRebel 安装使用教程
2019-04-30
插件GsonFormat快速实现JavaBean
2019-04-30
Java面试题全集(上)
2019-04-30
Java面试题全集(中)
2019-04-30
Java面试题全集(下)
2019-04-30
《代码整洁之道》读书笔记
2019-04-30
Java程序员从笨鸟到菜鸟之(六十七)细谈Spring(一)spring简介
2019-04-30
Java程序员从笨鸟到菜鸟之(六十八)细谈Spring(二)自己动手模拟spring
2019-04-30
Java程序员从笨鸟到菜鸟全部博客目录
2019-04-30
java程序员从笨鸟到菜鸟之(七)一—java数据库操作
2019-04-30
Java程序员从笨鸟到菜鸟之(八)反射和代理机制
2019-04-30
面试心得与总结—BAT、网易、蘑菇街
2019-04-30
Java对象初始化顺序
2019-04-30
Java开发的几个注意点
2019-04-30
我的Java后端书架 (2016年暖冬4.0版)
2019-04-30
每个程序员都必读的10篇文章
2019-04-30