美文网首页
Android开发(7)——View属性和事件

Android开发(7)——View属性和事件

作者: 让时间走12138 | 来源:发表于2021-03-17 15:57 被阅读0次

    本节内容

    1.View的基本属性

    2.view实现监听事件的几种方式

    3.使用高阶函数接收回调

    4.shape资源使用

    5.触摸事件传递过程源码分析

    6.判断触摸点是否在某个视图中

    7.状态栏和标题栏的高度计算

    8.触摸点坐标转化大小

    9.onWindowsFocusChanged方法

    一、View的基本属性
    1.创建一个xml界面,添加一个View控件,点击它,右侧就会出现很多它的属性
    image.png
    底下还有很多属性,没有都截出来。简单介绍一些常用的属性。
    • 2.View的background属性,背景可以是纯粹的颜色,也可以是一张背景图片。
    • 3.alpha:透明度,0为完全透明,1为完全不透明。可以通过alpha实现渐变的动画。
    • 4.clickable:如果为true,表示可以被点击。如果为false,表示不能被点击。
    • 5.focusable:是否可以获得焦点,一般与clickable同步使用,且一般都是true或false,它们的状态值是一样的。
    • 6.id:唯一表示控件在容器中的标识符。
    • 7.tag:标签,字符串。功能:①记录数据 ②通过标签获取控件
    8.当有id时,可以直接通过id访问这个控件。当id不明确时,可以通过tag访问控件。
      val mView =   container.findViewWithTag<View>("1")
            mView.alpha=1f
            mView.background = getDrawable(R.color.colorAccent)
    
    9.可以通过onClick设置点击事件。先在xml的代码中添加一个onClick,并命名。然后在MainActivity中实现自己命名的这个方法。
     android:onClick="changeBg"
    
     fun changeBg(view: View) {
            view.background=getDrawable(R.color.colorPrimary)
            }
    
    • 但是一般不建议使用这种方式,因为很不稳定。
    二、View实现监听事件的几种方式
    1.通过实现对应的接口,实现监听事件(自己监听事件)
    mView.setOnClickListener(this)
     override fun onClick(v: View?) {
            v?.background= getDrawable(R.color.colorPrimaryDark)
            }
    
    • View有一个OnClickListener的接口,这个接口里面有一个onClick方法。一旦点击界面,系统会触发一个performClick方法,它会去view里面找有没有listener,如果有的话,那么它就会去调用listener对应的方法,就是onClick方法。
    • 比较麻烦的是,如果是的监听者设为this,那么还需要另外去实现onClickListener接口
    2.直接声明一个类,实现对应的接口和方法(别人监听)用的很少
    mView.setOnClickListener(MyListener())
    
    inner class MyListener:View.OnClickListener {
            override fun onClick(v: View?) {
            v?.background= getDrawable(R.color.colorPrimary)
            }
            }
    
    3.匿名内部类(用的比较多)
     mView.setOnClickListener(object :View.OnClickListener{
            override fun onClick(v: View?) {
            v?.background= getDrawable(R.color.colorPrimary)
            }
            })
    
    4.如果实现的接口只有一个 可以使用lambda表达式
    mView.setOnClickListener({v:View? ->
            v?.background= getDrawable(R.color.colorPrimary)
            })
    
    5.如果这个方法的最后一个参数是lambda表达式,那么这个表达式可以放在括号外边
     mView.setOnClickListener{v:View? ->
            v?.background= getDrawable(R.color.colorPrimary)
            }
    
    6.如果这个方法只有一个参数,那么这个参数可以省略(用的比较多)
     mView.setOnClickListener{
            it?.background= getDrawable(R.color.colorPrimary)
            }
    
    三、使用高阶函数接收回调
    1.它可以直接使用一个函数来作为返回值
    2.高阶函数应用举例
    • 创建一个类,在里面定义一个接收回调的函数,再定义一个触发事件。
    class MyView {
        //1.定义接收回调的函数/方法
         var callBack:((String)->Unit)?= null
    
        //2.事件触发
        fun performClick(){
            callBack?.let {
                it("user:swl")
            }
        }
    }
    
    • 在MainActivity中创建一个对象,再接收回调。因为callBack只有一个参数,所以这个参数可以省略。callBack一般只关心参数。
            //创建对象
            val myView = MyView()
            //接收回调
            myView.callBack = {
            Log.v("swl","主页接收到回调的数据了:$it")
            }
    
    • 然后触发一下这个事件
     mView.setOnClickListener{
            myView.performClick()
            }
    
    四、shape资源的使用
    1.让一个图片变成圆角。圆角的图片在生活中很常见,所以最好学会这个知识。
    • 首先在drawable资源文件下new一个DrawableResourceFile,然后取一个名字。
    • 打开之后呢,把<selector>改为<shape>,然后可以给它设置各种属性。形状设置为矩形。stroke是画笔的意思,里面设置的是画笔的颜色和宽度。solid是固定的意思,里面设置的是框框里面的颜色。
    <?xml version="1.0" encoding="utf-8"?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android"
        android:shape="rectangle">
        <corners android:radius="20dp"/>
        <stroke android:color="@color/colorAccent"
            android:width="2dp"/>
        <solid android:color="@color/colorPrimary"/>
      </shape>
    
    • <gradient>还可以设置渐变色。linear线性的,表示平铺过去的渐变。sweep,就是像扇形一样扫描过去的渐变。
    <gradient android:type="linear"  -->
             android:startColor="@color/colorAccent"
             android:centerColor="@color/colorPrimary"
             android:endColor="@color/colorPrimaryDark"/>
    
    2.前面说了,background可以是颜色,也可以是drawable里的资源文件,所以我们把xml中的背景换成我们刚刚新建的资源文件。
     android:background="@drawable/shape_corner_radius"
    
    五、触摸事件传递过程源码分析
    1.触摸事件有几种事件类型,由MotionEvent类来管理
    • ACTION_DOWN 按下
    • ACTION_UP 离开屏幕
    • ACTION_MOVE 移动
    • ACTION_CANCEL 被其他应用打断
    2.调用onTouchEvent方法来判断触摸事件的类型
    override fun onTouchEvent(event: MotionEvent?): Boolean {
    }
    
    3.当触摸事件开始时,又会回调下面这个方法
     override fun onUserInteraction() {
            super.onUserInteraction()
           Log.v("swl","触摸事件即将开启")
        }
    
    4.如果子控件需要接收触摸事件 就必须实现onTouchEvent,它的返回值类型为boolean, 当返回值为true时,表示这个事件已经被消费了,就不会继续传递。当返回值为false时,表示这个事件没有被消费,就继续传递。
    六、判断触摸点是否在某个视图中
    1.在onTouchEvent中判断是哪种点击事件,再做出相应的操作。这个方法可能被多次调用。
    override fun onTouchEvent(event: MotionEvent?): Boolean {
            when(event?.action){
                MotionEvent.ACTION_DOWN -> {
                    Log.v("swl", "手指按下 x: ${event.x},y:${event.y}")
                }
                MotionEvent.ACTION_MOVE -> {
                    Log.v("swl","手指滑动")
                }
                MotionEvent.ACTION_UP ->{
                    Log.v("swl","手指离开屏幕")
                }else -> Log.v("swl","被其他应用打断了")
            }
            return true
        }
    
    2.那么如何判断触摸点是否在某个视图中呢。有一个 Rect(l,t,r,b),其中 (rect是一个矩形区域)
         * l:x,
         * t:y,
         * r:l + width ,
         * b: t + height
    
    还有一个point(x,y),可以获取当前点的坐标。
         获取触摸点的x和y坐标
        event.x  表示触摸点和屏幕的左边间距
        event.y  表示触摸点和屏幕的上边间距
        mView.x  相对于父容器的左边间距
        mView.y  相对于父容器的顶部间距   没有bar和状态栏的高度
    
    3.有一个requestRectangleOnScreen方法可以获取触摸点相对于屏幕的位置。rect是一个矩形区域。
           val rect:Rect  = Rect()
            /获取这个控件在屏幕上的rect  相对于屏幕来说的尺寸
            mView.requestRectangleOnScreen(rect)
            rect.right = rect.left + mView.width
            rect.bottom = rect.top + mView.height
    
    4.判断某个rect是否包含某个点
    rect.contains(event.x.toInt(),event.y.toInt()).also {
                if(it){
                    mView.background= getDrawable(R.color.colorPrimary)
                }else{
                    mView.background = getDrawable(R.color.colorAccent)
                }
            }
    
    七、状态栏和标题栏的高度计算
    image.png
    • 红色框框起来的是绘制区域,绘制区域和屏幕顶部的距离为bar,也就是状态栏和标题栏。
    1.每次获取触摸点到顶部的距离时,都会把bar给加上去,如果我们把这个高度计算出来,再用获取的top减去这部分距离,那么得到的就是相对于绘制区域顶部的高度。
    将触摸点的y坐标减去顶部高度 ->获得相对于内容绘制区域的坐标
    
    2.获取屏幕的尺寸
    val display = DisplayMetrics()
            windowManager.defaultDisplay.getMetrics(display)
            Log.v("swl","屏幕尺寸 width:${display.widthPixels}, height : ${display.heightPixels}")
    
    3.获取内容绘制区域的尺寸
     val drawRect = Rect()
     window.findViewById<ViewGroup>(Window.ID_ANDROID_CONTENT).getDrawingRect(drawRect)
    
    4.计算顶部高度
    val barHeight = display.heightPixels - drawRect.height()
    
    八、触摸点坐标转化
    1.将触摸点的y坐标 - 顶部高度 = 相对于内容绘制区域的坐标
    viewRect.contains(event.x.toInt(),(event.y-barHeight).toInt()).also {
                if(it){
                    mView.background= getDrawable(R.color.colorPrimary)
                }else{
                    mView.background = getDrawable(R.color.colorAccent)
                }
            }
    
    九、onWindowFocusChanged方法
    1.前面计算状态栏和标题栏的代码,可以放在onWindowFocusChanged方法里面,因为这个方法被调用在onTouchEvent之前
    override fun onWindowFocusChanged(hasFocus: Boolean) {
            super.onWindowFocusChanged(hasFocus)
            //获取屏幕的尺寸
            val display = DisplayMetrics()
            windowManager.defaultDisplay.getMetrics(display)
            Log.v("swl","屏幕尺寸 width:${display.widthPixels}, height : ${display.heightPixels}")
    
            //获取内容绘制区域的尺寸
            val drawRect = Rect()
            //通过获取window上的content容器 ->容器的rect
            window.findViewById<ViewGroup>(Window.ID_ANDROID_CONTENT).getDrawingRect(drawRect)
    
            //顶部高度
            val barHeight = display.heightPixels - drawRect.height()
        }
    

    相关文章

      网友评论

          本文标题:Android开发(7)——View属性和事件

          本文链接:https://www.haomeiwen.com/subject/lmclcltx.html