ConstraintLayout 2,android 双击事件响应
class CircularRevealHelper @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : ConstraintHelper(context, attrs, defStyleAttr) {
override fun updatePostLayout(container: ConstraintLayout) {super.updatePostLayout(container)if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {val views = getViews(container)for (view in views) {val anim = ViewAnimationUtils.createCircularReveal(view, view.width / 2,view.height / 2, 0f,Math.hypot((view.height / 2).toDouble(), (view.width / 2).toDouble()).toFloat())anim.duration = 3000anim.start()}}}}
updatePostLayout 会在 onLayout 之后调用,在这里做动画就可以。
有了 CircularRevealHelper 之后可以直接在 xml 里面使用,在 CircularRevealHelper 的 constraint_referenced_ids 里面指定需要做动画 view。
<?xml version="1.0" encoding="utf-8"?><android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent">
<ImageViewandroid:id="@+id/img_mario"android:layout_width="wrap_content"android:layout_height="wrap_content"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent"app:srcCompat="@drawable/mario" />
<cn.feng.constraintLayout2.helps.CircularRevealHelperandroid:id="@+id/helper"android:layout_width="wrap_content"android:layout_height="wrap_content"app:constraint_referenced_ids="img_mario"tools:ignore="MissingConstraints" />
</android.support.constraint.ConstraintLayout>
后面如果要对 view 做 CircularReveal 直接在 xml 里面指定就可以了,做到了很好的复用。
FlyinHelper
再来看看这个 Flyin 的飞入效果,view 从四周飞入到各自的位置。
这个动画的关键在于计算出每个 view 该从什么方向飞入。
红色边框的位置可以借助前面介绍的的 Layer 找到(当然也可以不借助Layer,自己算,稍显复杂),从而计算出红色框框部分的中间点位置, 再和图中每个 view 的中间点比较(图中每个白点的位置)从而得出每个 view 该从哪个方向飞入。
计算每个 view 的初始位置代码如下,借助上面的图形应该很好理解。
for (view in views) {
val viewCenterX = (view.left + view.right) / 2val viewCenterY = (view.top + view.bottom) / 2
val startTranslationX = if (viewCenterX < centerPoint.x) -2000f else 2000fval startTranslationY = if (viewCenterY < centerPoint.y) -2000f else 2000f
view.translationX = (1 - animatedFraction) * startTranslationXview.translationY = (1 - animatedFraction) * startTranslationY}
FlyinHelper 的完整代码参考这里
ComposeMultipleHelper
每个 view 不但可以接受一个 ConstraintHelper,还可以同时接受多个 ConstraintHelper。
左边的四个 ImageView 和右下的 FloatingActionButton 都有 Flyin 的效果,同时左边的四个 ImageView 还在绕 Y 轴做 3D 旋转。上方的 Seekbar 的背景在做 CircularReveal 的效果。有了前面编写的 CircularRevealHelper 以及 FlyInHelper 我们可以很方便做到这样的效果。
Flow (VirtualLayout)
Flow 是 VirtualLayout,Flow 可以像 Chain 那样帮助快速横向/纵向布局 constraint_referenced_ids 里面的元素。 通过 flow_wrapMode 可以指定具体的排列方式,有三种模式
wrap none : 简单地把 constraint_referenced_ids 里面的元素组成 chain,即使空间不够
wrap chain : 根据空间的大小和元素的大小组成一条或者多条 chain
wrap aligned : wrap chain 类似,但是会对齐
![](https://user
-gold-cdn.xitu.io/2019/6/20/16b7364b6c30dca9?imageView2/0/w/1280/h/960/ignore-error/1)
下面看下如何实现这个计算器布局:
<?xml version="1.0" encoding="utf-8"?><android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".activity.MainActivity">
<android.support.constraint.helper.Flowandroid:id="@+id/flow"android:layout_width="match_parent"android:layout_height="wrap_content"android:background="#FFC107"android:padding="20dp"app:constraint_referenced_ids="tv_num_7,tv_num_8,tv_num_9,tv_num_4,tv_num_5,tv_num_6,tv_num_1,tv_num_2,tv_num_3,tv_num_0,tv_operator_div,tv_dot,tv_operator_times"app:flow_horizontalGap="10dp"app:flow_maxElementsWrap="3"app:flow_verticalGap="10dp"app:flow_wrapMode="aligned"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent" />
<TextViewandroid:id="@+id/tv_num_7"style="@style/text_view_style"android:text="7" />
<TextViewandroid:id="@+id/tv_num_8"style="@style/text_view_style"android:text="8" />
<TextViewandroid:id="@+id/tv_num_9"style="@style/text_view_style"android:text="9" />
<TextViewandroid:id="@+id/tv_num_4"style="@style/text_view_style"android:text="4" />
<TextViewandroid:id="@+id/tv_num_5"style="@style/text_view_style"android:text="5" />
<TextViewandroid:id="@+id/tv_num_6"style="@style/text_view_style"android:text="6" />
<TextViewandroid:id="@+id/tv_num_1"style="@style/text_view_style"android:text="1" />
<TextViewandroid:id="@+id/tv_num_2"style="@style/text_view_style"android:text="2" />
<TextViewandroid:id="@+id/tv_num_3"style="@style/text_view_style"android:text="3" />
<TextViewandroid:id="@+id/tv_num_0"style="@style/text_view_style"android:text="0" />
<TextViewandroid:id="@+id/tv_operator_div"style="@style/text_view_style"android:text="/"tools:layout_editor_absoluteX="156dp"tools:layout_editor_absoluteY="501dp" />
<TextViewandroid:id="@+id/tv_operator_times"style="@style/text_view_style"android:text="*" />
<TextViewandroid:id="@+id/tv_dot"style="@style/text_view_style"android:text="."tools:layout_editor_absoluteX="278dp"tools:layout_editor_absoluteY="501dp" />
<TextViewandroid:id="@+id/KE"android:layout_width="0dp"android:layout_height="0dp"android:background="#00BCD4"android:gravity="center"android:text="Compute"android:textColor="@android:color/white"android:textSize="24sp"app:layout_constraintBottom_toBottomOf="@+id/tv_operator_times"app:layout_constraintEnd_toEndOf="@+id/tv_dot"app:layout_constraintHorizontal_bias="1.0"app:layout_constraintStart_toStartOf="@+id/tv_operator_div"app:layout_constraintTop_toTopOf="@+id/tv_operator_times" />
<TextViewandroid:id="@+id/KR"android:layout_width="0dp"android:layout_height="0dp"android:background="#03A9F4"android:gravity="right|center_vertical"android:paddingEnd="16dp"android:text="0"android:textColor="@android:color/white"android:textSize="58sp"app:layout_constraintBottom_toTopOf="@+id/flow"app:layout_constraintEnd_toEndOf="@+id/flow"app:layout_constraintStart_toStartOf="@+id/flow"app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
借助 flow 很快可以布局出来,这里 flow_wrapMode 使用的是 aligned,id 为 KE 的 TextView 可以对齐到 Flow 里面的 view,id 为 KR 的 TextView 可以对齐到 Flow,另外 Flow 也是 ConstraintHelper,所以 Flow 也是个 View,可以设置背景,padding 等元素。 那么这样布局有什么优势? 这样的布局 view 都在一个层级,不使用 ViewGroup,减少层级。
评论