3.Android群英传读书笔记-控件架构与自定义控件

Android控件架构

ViewGroup:作为父控件可以包含多个View并进行管理。形成控件树。

这里写图片描述

setContentView做了哪些事?

1.Activity都包含一个Windows对象(通常为PhoneWindows)。
2.PhoneWindows讲一个DecorView设置为整个应用窗口的根View。
3.DecorView作为窗口界面的顶层视图,封装一些窗口的通用方法。
4.WindowManagerService所有View监听事件,并通过Activity回调相应事件。

这里写图片描述

DecorView树

若是调用requestWindowsFeature(Windows.FEATURE_NO_TITLE)设置全屏。则不包含左侧。
当onCreate()方法中调用setContentView()方法后,ActivityManagerService会回调onResume()。

View的测量

onMeasure()方法告诉系统该画一个多大的View。

MeasureSpec类测量模式:

1.EXACTLY:精确模式,控件的长宽指定具体数值或者match_parent。
2.AT_MOST:wrap_content.随着子控件内容变化,不超过父控件。
3.UNSPECIFIED:不指定大小测量模式,自定义View时才用到

View默认EXACTLY模式。若想让自定义View支持wrap_content就必须重写onMeasure()来指定其大小。

protected void onMeasure(int widthMeasureSpec ,int heightMeasureSpec)
{
    super.onMeasure(widthMeasureSpec,heightMeasureSpec) ;
    //调用setMeasuredDimension(int width , int Height)设置宽高。
}

对onMeasure()进行重写

protected void onMeasure(int widthMeasureSpec ,int heightMeasureSpec)
{
setMeasuredDimension(measureWidth(widthMeasureSpec),mesureHeight(heightMeasureSpec));
}

private int measureWidth(int measureSpec)
{
    int result = 0 ;
    int specMode = MeasureSpec.getMode(measureSpec) ; //获取测量模式
    int specSize = MeasureSpec.getSize(measureSpec) ; //获取大小
    //判断测量模式
    if(specMode == MeasureSpec.EXACLTY){
        result = specSize ;
    }else{
        result = 200 ; //自设
        if(specMode == MeasureSpec.AT_MOST)
        {
            result = Math.min(result , specSize) ;
        }
    }
    return result ;
}

View的绘制

重写View类中的onDraw()方法进行绘图:在其他地方需要创建一个Canvas对象(Canvas canvas = new Canvas(bitmap)) ;
bitmap的作用:装载画布,存储绘制信息,

ViewGroup的测量

管理子View的体现:当ViewGroup的大小为wrap_content时,便需要对子View遍历决定自己的大小。
调用子View的Measure方法来获取每个View的测量结果。
测量子View完毕后需要放置合适的位置,就是Layout过程。同样为遍历子View的Layout方法,指定具体显示位置。
自定义ViewGroup时通常重写onLayout()方法控制子View显示位置逻辑。

ViewGroup的绘制

通常自身不需要绘制。但是会使用dispatchDraw()绘制子View 。同上,遍历子View绘制方法完成。

自定义View

重要的回调方法

1.onFinishInflate():从XML加载组件后回调。
2.onSizeChanged():组件大小改变时回调。
3.onMeasure():回调该方法进行测量。
4.onLayout():回调该方法确定显示位置。
5.onTouchEvent():监听触摸事件时回调。

1.对现有控件进行扩展

一般步骤
这里写图片描述

//在构造器中初始化画笔
mPaint = new Paint() ;
mPaint.setColor(getResources().getColor(android.R.color.holo_blue_bright));
mPaint.setStyle(Paint.Style.FILL);
mPaint1 = new Paint();
mPaint1.setColor(Color.YELLOW);
mPaint1.setStyle(Paint.Style.FILL);

//onDraw()中重绘画布
protected void onDraw(Canvas canvas)
{
    canvas.drawRect(0,0,getMeasuredWidth() ,getMeasuredHeight() ,mPaint) ;
    canvas.drawRect(0,0,getMeasuredWidth() ,getMeasuredHeight() ,mPaint1) ;
    canvas.save() ;
    canvas.translate(10,0) ;
    //在回调父类方法前,实现自己的逻辑,对TextView来是就是绘制文本前
    super.onDraw(canvas) ;
    //在回调父类方法后,实现自己的逻辑,对TextView来说就是绘制文本后
    canvas.restore();
}

例2:Chapter3 -My_Text2.java //字体浮动


2.通过组合实现新的控件

通常步骤:
1.继承一个合适的ViewGroup
2.添加指定功能的控件
例子:通用Bar

//自定义属性,res/values下创建attrs.xml
<?xml version ="1.0" encoding = "utf-8"?>
<resources>
    //该标签声明自定义属性名
    <declare-styleable name = "xxxx">
        //自定义标题
        <attr name="mtitle" format ="string"/>
        //其他如颜色,背景等类似
    </declare-styleable>
</resources>

3.在自定义控件类的构造方法中,TypedArray对象的getString等方法

TypedArray ta = context.obtainStyleAttributes(attrs , R.styleable.XXX) ;
String title = ta.getString(R.styleable.XXX_title) ;
//颜色 背景等类似
ta.recycle() ;//最后TypedArray回收

Button btn = new Button(context) ;//创建控件
btn.setText(xxx) .setColor(xxx) //将前面获取的属性赋给控件。

LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT ,LayoutParams.MATCH_PARENT) ;
lp.addRule(RelativeLayout.ALIGN_PARENT_LEFT , TRUE) ; //设置布局
addView(btn , lp) //添加控件到布局 

//点击事件的接口创建
public interface topbarClickListener
{
    void xxClick(View view) ;
    void xxClick(View view) ;
}

//构造方法中暴露接口给调用者
topbarClickListener mListener ;
btn.setOnClickListener(new OnClickListener()
{
    public void onClick(View view)
    {
        mListener.xxClick(view) ;
    }
});

//暴露方法给调用者来注册接口回调。
public void setOnMyClickListener(topbarClickListener mListener)
{
    this.mListener = mListener ;
}
//可以添加更多方法提高空间的可制定性。

4.添加模板:记得引用控件空间名:xmlns:app=”http://schemas.android.com/apk/res-auto”


3.重新View来实现全新控件

4.自定义ViewGroup

1.重写onMeasure()对子View进行测量。
2.重写onLayout() 确定子View的位置。
3.重写onTouchEvent() 添加事件处理。

5.事件拦截机制

1.MotionEvent ,一般重写触摸相关方法都含有该参数。

.getX(); //
.getAction() ; //MotionEvent.ACTION_DOWN等事件。

2.事件拦截
ViewGroup拦截和处理的几个方法:

//事件拦截
public boolean dispatchTouchEvent(MotioEvent event)
{
    return super.dispatchTouchEvent(event) ;
}
//拦截的核心方法
public boolean onInterceptTouchEvent(MotionEvent ev)
{
    return super.onInterceptTouchEvent(ev) ;
}
//处理方法
public boolean onTouchEvent(MotionEvent ev)
{
    return super.onTouchEvent(ev) ;
}

对于View

public boolean dispatchTouchEvent(MotionEvent ev)
{
    return super.dispatchTouchEvent(ev) ; 
}
public boolean onTouchEvent(MotionEvent ev)
{
    return super.onTouchEvent(ev) ;
}

事件传递方向:外层ViewGroup->内层ViewGroup->View ->
->事件处理相反 ->View->内层ViewGroup->外层ViewGroup

传递返回值:true 拦截不再传递 ,false继续(默认)。
处理返回值:true 事件已处理,不再上交,false 继续交由上级处理。
一般不需要重写 dispatchTouchEvent() ;

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。、资源 5来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。、资 5源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值