Android自定义View

来源:互联网 发布:ubuntu安装nodejs 编辑:程序博客网 时间:2024/05/19 00:54

继承已知Layout(如RelativeLayout和LinearLayout)

创建构造函数:

//该构造函数一般在Java文件中创建控件使用public DefinedView( Context context ){    super( context );    LayoutInflater.from(context).inflate(R.layout.definedview, this);    ...    //或者直接调用下一个函数,即使用以下代码:    this( context, null );}
//该构造函数一般在xml文件中创建控件时候调用public DefinedView( Context context, AttributeSet attrs){    super(context, attrs);    LayoutInflater.from(context).inflate(R.layout.definedview, this);    【1】...}

对于这个构造函数,因为会在这里读取attrs文件来获得各项参数,所以还需要进行一系列复杂的操作:
1. 在res/values目录下创建一个attrs_definedview.xml文件,以resources作为最外层根标签,并定义styleable标签,如:

<?xml version="1.0" encoding="utf-8"?><resources>    <declare-styleable name="DefinedView">        <attr name="textSize"           format="dimension"/>        <attr name="text"               format="string" />        <attr name="viewColor"    format="color" />        <!--        dimension表示尺寸,一般是一些以dp,sp,px等单位的内容        string表示字符串,一般是text的内容        color表示颜色,一般是背景等的内容        -->    </declare-styleable></resources>

值得注意的是,在这里所创建的styleable name必须和控件的名称保持一致,才能够顺利的使用xml文件来指定该控件的某些属性。

2. 在构造函数(在之前的【1】处)中读取所创建的styleable内容

TypedArray array = context.obtainStyledAttributes(attrs,R.styleable.DefinedView);//解析StringString text = array.getString(R.styleable.DefinedView_text);if(text == null || text.isEmpty() )    text = "default text";//解析Dimensionfloat textSize = array.getDimension(R.styleable.DefinedView_textSize, 20sp);//解析color,后一个值表示未设置时的默认值int color = array.getColor(R.styleable.DefinedView_viewColor, Color.RED);//务必记得调用recycle()array.recycle();

创建点击响应

Android的事件分发

  • 分发函数

事件分发一般会分发给几个函数来处理:该View中用户所设定的onTouchListener的onTouch()函数,该View中系统自带的onTouchEvent()函数,该View中系统自带的dispatchTouchEvent()函数和只存在与ViewGroup和Activity中的onInterceptTouchEvent()函数

  • 分发函数返回值
    对于以上函数而言,其返回值与作用如下
函数名称 返回true 返回false dispatchTouchEvent 事件分配完成,本身不处理 事件分配失败,交由自身处理 onTouch 事件处理完成 事件处理失败(或用户未定义) onTouchEvent 事件处理完成 事件处理失败 onInterceptTouchEvent 拦截事件自己处理 不拦截,分发事件

值得注意的是,onTouchEvent()函数是系统已经定义好的函数,对于View默认返回值时true,对于ViewGroup默认返回值时false

  • Event的分发顺序:
    1. Activity获取事件以后调用dispatchTouchEvent()进行事件分发。
    2. ViewGroup获取事件以后同样调用dispatchTouchEvent()尝试分发,而在dispatchTouchEvent()中,则会分别进行如下步骤:
1、onFilterTouchEventForSecurity()//是否需要分发事件。当View上层有遮蔽且设置android:filterTouchesWhenObscured//[对应Java文件内调用函数:setFilterTouchesWhenObscured(boolean) ]为true时,不分发事件,函数返回false;否则需要分发事件,则进行目标和状态清空等操作。2、onInterceptTouchEvent()//是否需要拦截事件,返回true表示事件被拦截,不再分发给子View;默认//值是false。3、进行事件分发.//如果之前的1、2步均表示需要进行事件分发,则此时将事件分发给其子//View(ViewGroup)。4、检查子View是否处理事件。//如果子View顺利处理了该事件(即子View的onTouch或者onTouchEvent()//返回了true),则此时dispatchTouchEvent()函数返回true,分发结束。5、onTouchListener.onTouch()//如果所有子View(ViewGroup)均表示处理不了,则由该ViewGroup自己调//用其设定的onTouchListnener的onTouch函数,当返回true时表示事件处//理完成,dispatchTouchEvent函数返回true,分发结束。6、ViewGroup.onTouchEvent()在这个过程中捕捉到ACTION_DOWN和ACTION_UP后会执行onClick()//如果之前onTouch()也表示处理不了,或者压根就没设置,这时则由//ViewGroup中已经定义好的onTouchEvent()函数来处理事件,当返回true//时表示事件处理完成,函数返回true,分发成功结束;而当返回false的时候//ViewGroup表示自己也未处理,则dispatchTouchEvent()函数返回false


View的点击位置及函数获取值

调用event.getX()和event.getY()获取到的X和Y的值均为相对于当前View的坐标,所以ACTION_MOVE和ACTION_UP这两个操作所得到的值均有可能超出View的范围,其值也有可能小于0。

0 0