【5年Android从零复盘系列之六】Android自定义View(1):基础详解(图文)
发布日期:2021-06-29 18:17:35
浏览次数:2
分类:技术文章
本文共 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 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
网站不错 人气很旺了 加油
[***.192.178.218]2024年04月20日 13时25分37秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
基于SSM的仿小米商城源码
2019-04-29
基于SSM的医院人事管理系统的设计与实现
2019-04-29
基于SSM的网上购物系统的设计与开发
2019-04-29
基于SSM框架的BS微博系统的设计与实现
2019-04-29
超市订单管理系统
2019-04-29
基于ssm的民宿网站
2019-04-29
基于JavaWeb的物流管理系统的设计与实现
2019-04-29
基于Java的飞机大战游戏的设计与实现论文
2019-04-29
基于java实现的超级马里奥游戏
2019-04-29
linux不删除文件:替换rm命令
2019-04-29
linux: shell脚本日常功夫
2019-04-29
scala集合类型,函数
2019-04-29
spark: rdd的应用(scala api)
2019-04-29
yarn: 资源调度机制
2019-04-29
spark的shell脚本分析
2019-04-29
推荐算法: 基于用户的协同过滤算法
2019-04-29
推荐算法:基于物品的协同过滤算法
2019-04-29
docker系列3:docker搭建CDH集群[单机单节点]
2019-04-29
ubuntu 16:使用系统自带的中文输入法
2019-04-29
k8s单机版[ microk8s ]
2019-04-29