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

2021-03-17  本文已影响0人  让时间走12138

本节内容

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()
    }
上一篇 下一篇

猜你喜欢

热点阅读