文章目录
一. 约束布局
1. 常用属性及工具
- 官方不推荐在ConstraintLayout中使用match_parent,可以设置 0dp (MATCH_CONSTRAINT) 配合约束代替match_parent
- 链 Chain
例子:
### 权重链
<TextView
android:id="@+id/TextView1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="@color/pink"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/TextView2"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/TextView2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="@color/green"
app:layout_constraintLeft_toRightOf="@+id/TextView1"
app:layout_constraintRight_toLeftOf="@+id/TextView3"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/TextView3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="@color/red"
app:layout_constraintLeft_toRightOf="@+id/TextView2"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintTop_toTopOf="parent" />
### 样式链
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/TextView1"
android:layout_width="50dp"
android:layout_height="wrap_content"
android:background="@color/pink"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/TextView2"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/TextView2"
android:layout_width="50dp"
android:layout_height="wrap_content"
android:background="@color/green"
app:layout_constraintLeft_toRightOf="@+id/TextView1"
app:layout_constraintRight_toLeftOf="@+id/TextView3"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/TextView3"
android:layout_width="50dp"
android:layout_height="wrap_content"
android:background="@color/red"
app:layout_constraintLeft_toRightOf="@+id/TextView2"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
- 角度定位
- 相对定位(最常用的)
- 偏移 bias
假如现在要实现水平偏移,给TextView1的layout_constraintHorizontal_bias赋一个范围为 0-1 的值,假如赋值为0,则TextView1在布局的最左侧,假如赋值为1,则TextView1在布局的最右侧,假如假如赋值为0.5,则水平居中,假如假如赋值为0.3,则更倾向于左侧,垂直偏移同理。 - 宽高比
app:layout_constraintDimensionRatio="1:1"
- Group
Group可以把多个控件归为一组,方便隐藏或显示一组控件,举个例子:
<TextView
android:id="@+id/TextView1"
android:background="@color/pink"
android:layout_width="100dp"
android:layout_height="70dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:background="@color/yellow"
android:id="@+id/TextView2"
android:layout_width="100dp"
android:layout_height="70dp"
app:layout_constraintLeft_toRightOf="@+id/TextView1"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:background="@color/green"
android:id="@+id/TextView3"
android:layout_width="100dp"
android:layout_height="70dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toRightOf="@id/TextView2" />
# 把控件1和3合并成一组
<androidx.constraintlayout.widget.Group
android:id="@+id/group"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="invisible"
app:constraint_referenced_ids="TextView1,TextView3" />
- Placeholder
Placeholder指的是占位符。在Placeholder中可使用setContent()设置另一个控件的id,使这个控件移动到占位符的位置 - Guideline
2. 实际操作
- 引导线如何设置百分比大小切换百分比
- 设置控件百分比大小
比如图片,但是会发生变形?
android:scaleType="fitXY"
app:layout_constraintHeight_percent="0.1"
app:layout_constraintWidth_percent="1.0
- 设置控件的层级
android:elevation="4dp" //值越大越在最上层,反正负值越低越在最底层
二. View的事件体系
1. View的基础概念
定义
- View是所有UI组件的父类,它负责绘制自己的内容,并处理与其相关的用户事件。每个View对象都会在屏幕上显示为一个矩形区域,并且可以响应用户的触摸、点击等交互操作。
- ViewGroup:ViewGroup是View的子类,它除了具备View的所有特性外,还负责管理子View的布局。ViewGroup可以包含多个子View,并负责测量、布局这些子View,以及处理事件的分发。简而言之,ViewGroup是一个用于存放其他View(和ViewGroup)对象的布局容器。
位置参数
可以通过getX()方法获取
Android3.0增加了新坐标x、y、translationX和translationY
x和y是view的左上角坐标
translation是view相对于父布局容器的偏移量
- MotionEvent和TouchSlop
MotionEvent对象可以获得x和y坐标。getX() getRawX()
- VelocityTracker
- GestureDetector
监听手势 - Scroller
全面解析的文章,较长
实现view的弹性滑动。与scollerBy和scollerTo相比,Scroller能够实现有过渡性的滑动,而不是瞬间滑动。
2. View的滑动
- scrollTo和scrollBy对比
当你想要滚动到具体的内容起始点 (如顶部或某个固定位置) 时,使用 scrollTo。
当你希望基于当前滚动位置进行调整 (如继续向下或向上滚动一定距离) 时,使用 scrollBy。
源码里的mScrollX 和 mScrollY 是 View 类中用于记录滚动状态的两个私有字段,分别表示视图的水平滚动偏移量和垂直滚动偏移量
- 动画实现
ObjectAnimator.ofFloat(mCustomView,"translationX",0,300).setDuration(1000).start();
- 改变布局参数
改变LayoutParams参数
- 三种方式对比
3. 弹性滑动
将一次大的滑动分成若干次小滑动并在一个时间段内完成
-
使用Scroller
结合View的ComputeScroll方法实现。不断的让View重绘,而每一次重绘距滑动起始时间会有一个时间间隔,通过这个这个间隔得知view当前的位置,再通过ScrooTo方法完成view的滑动。view的每一次滑动都会导致view的小幅度滑动,多次的滑动最终组成弹性滑动 -
通过动画
-
使用延时策略
Handler或者view的postDelay方法;线程的sleep方法
4. 事件分发机制
4.1 核心概念
核心对象:MotionEvent
三个核心方法:dispatchTouchEvent(入口 ) onInterceptTouchEvent(是否拦截) onTouchEvent(处理逻辑)
- 三个方法的逻辑关系
- 处理事件时的优先级
onTouchListner > onTouchEvent
- 点击事件传递过程
activity -> window -> view。当view拿到事件后,开始进行分发事件,直到onTouchEvent执行。若不执行,该事件最终丢给Activity处理
4.2 常用结论(参考android开发艺术)
4.3 小结
在 Android 中,View 点击事件的传递过程可以简单概括为以下几个步骤:
-
事件产生:当用户在 View 上进行点击操作时,系统会产生一个
MotionEvent
事件。 -
事件分发:系统会将该
MotionEvent
事件传递给当前 Activity 的dispatchTouchEvent()
方法进行分发。 -
事件拦截:在分发过程中,
ViewGroup
类型的 View 可以通过重写onInterceptTouchEvent()
方法来拦截事件的传递。如果onInterceptTouchEvent()
返回true
,则事件会停止向下传递,由当前ViewGroup
自己处理事件。 -
事件传递:如果事件没有被拦截,则会继续向下传递到子 View 的
dispatchTouchEvent()
方法。子 View 可以通过重写dispatchTouchEvent()
方法来决定是否要处理该事件。 -
事件处理:如果某个 View 想要处理该事件,可以重写
onTouchEvent()
方法并返回true
。否则,事件会继续向上传递到父 View 的onTouchEvent()
方法。 -
事件回溯:如果事件一直没有被处理,最终会回溯到 Activity 的
dispatchTouchEvent()
方法,由 Activity 来处理事件。
整个事件传递的过程可以通过 dispatchTouchEvent()
、onInterceptTouchEvent()
和 onTouchEvent()
三个方法来控制。
需要注意的是,在事件传递的过程中,可以通过调用 requestDisallowInterceptTouchEvent()
方法来禁止父 View 拦截事件,从而确保事件能够正确地传递到目标 View。
总的来说,Android 的事件传递机制是一个比较复杂的过程,但掌握这些基本原理对于理解和处理 View 的点击事件非常重要。
安卓手势事件action_down,action_move,action_up单次点击事件的探究