Android

Android ObjectAnimator(屬性動畫)

1.先算出手機的比例 讓每一隻手機的移動距離都是一樣的

val metric = DisplayMetrics()
fragment.activity!!.windowManager.defaultDisplay.getMetrics(metric)

//縮放比
val scale = 1080f / metric.widthPixels
editMoveLeft = -190f / scale
titleMoveTop = -70f / scale
titleMoveRight = 5f / scale

2.Layout布局

<?xml version="1.0" encoding="utf-8"?>
<layout 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">


    <data>
        <variable
            name="viewCtrl"
            type="com.doughpack.RegisterStepOneCtrl" />
    </data>

    <android.support.constraint.ConstraintLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/register_container_shape">


        <TextView
            android:id="@+id/account"
            style="@style/register_text_style"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp"
            android:layout_marginTop="8dp"
            android:text="@string/account"
            app:layout_constraintBottom_toTopOf="@+id/guideline50"
            app:layout_constraintStart_toStartOf="@+id/guideline40"
            app:layout_constraintTop_toTopOf="@+id/guideline43" />

        <TextView
            android:id="@+id/captcha"
            style="@style/register_text_style"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp"
            android:layout_marginTop="8dp"
            android:text="@string/captcha"
            app:layout_constraintBottom_toTopOf="@+id/guideline51"
            app:layout_constraintStart_toStartOf="@+id/guideline40"
            app:layout_constraintTop_toTopOf="@+id/guideline50" />

        <TextView
            android:id="@+id/password"
            style="@style/register_text_style"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp"
            android:layout_marginTop="8dp"
            android:text="@string/password"
            app:layout_constraintBottom_toTopOf="@+id/guideline52"
            app:layout_constraintStart_toStartOf="@+id/guideline40"
            app:layout_constraintTop_toTopOf="@+id/guideline51" />

        <TextView
            android:id="@+id/confirm_password"
            style="@style/register_text_style"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp"
            android:layout_marginTop="8dp"
            android:text="@string/confirm_password"
            app:layout_constraintBottom_toTopOf="@+id/guideline53"
            app:layout_constraintStart_toStartOf="@+id/guideline40"
            app:layout_constraintTop_toTopOf="@+id/guideline52" />

        <TextView
            android:id="@+id/invite_code"
            style="@style/register_text_style"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp"
            android:layout_marginTop="8dp"
            android:text="@string/invite_code"
            app:layout_constraintBottom_toTopOf="@+id/guideline49"
            app:layout_constraintStart_toStartOf="@+id/guideline40"
            app:layout_constraintTop_toTopOf="@+id/guideline53" />

        <EditText
            android:id="@+id/edit_account"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="16dp"
            android:layout_marginEnd="16dp"
            android:background="@null"
            android:ems="10"
            android:hint="@string/input_phoneNumber"
            android:inputType="phone"
            android:maxLength="10"
            android:textSize="14sp"
            app:layout_constraintBottom_toBottomOf="@+id/account"
            app:layout_constraintEnd_toStartOf="@+id/isCaptcha"
            app:layout_constraintStart_toStartOf="@+id/guideline39"
            app:layout_constraintTop_toTopOf="@+id/account"
            tools:ignore="Autofill" />

        <EditText
            android:maxLength="4"
            android:id="@+id/edit_captcha"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="16dp"
            android:layout_marginEnd="50dp"
            android:background="@null"
            android:ems="10"
            android:hint="@string/input_captcha"
            android:inputType="numberDecimal"
            android:textSize="14sp"
            app:layout_constraintBottom_toBottomOf="@+id/captcha"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="@+id/guideline39"
            app:layout_constraintTop_toTopOf="@+id/captcha"
            tools:ignore="Autofill" />

        <EditText
            android:maxLength="15"
            android:id="@+id/edit_password"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="16dp"
            android:layout_marginEnd="50dp"
            android:background="@null"
            android:ems="10"
            android:hint="@string/input_password"
            android:inputType="textPassword"
            android:textSize="14sp"
            app:layout_constraintBottom_toBottomOf="@+id/password"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="@+id/guideline39"
            app:layout_constraintTop_toTopOf="@+id/password"
            tools:ignore="Autofill" />

        <EditText
            android:maxLength="15"
            android:id="@+id/edit_confrim_password"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="16dp"
            android:layout_marginEnd="50dp"
            android:background="@null"
            android:ems="10"
            android:hint="@string/input_again_password"
            android:inputType="textPassword"
            android:textSize="14sp"
            app:layout_constraintBottom_toBottomOf="@+id/confirm_password"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="@+id/guideline39"
            app:layout_constraintTop_toTopOf="@+id/confirm_password"
            tools:ignore="Autofill" />

        <EditText
            android:id="@+id/edit_invite_code"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="16dp"
            android:layout_marginEnd="50dp"
            android:background="@null"
            android:ems="10"
            android:hint="@string/choice"
            android:inputType="textPersonName"
            android:textSize="14sp"
            app:layout_constraintBottom_toBottomOf="@+id/invite_code"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="@+id/guideline39"
            app:layout_constraintTop_toTopOf="@+id/invite_code"
            tools:ignore="Autofill" />

        <View
            android:id="@+id/view"
            android:layout_width="0dp"
            android:layout_height="2dp"
            android:layout_marginEnd="32dp"
            android:layout_marginBottom="6dp"
            android:background="#D1D1D1"
            app:layout_constraintBottom_toTopOf="@+id/guideline50"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="@+id/account"
            app:layout_constraintTop_toBottomOf="@+id/edit_account" />

        <View
            android:id="@+id/view16"
            android:layout_width="0dp"
            android:layout_height="2dp"
            android:layout_marginEnd="32dp"
            android:layout_marginBottom="6dp"
            android:background="#D1D1D1"
            app:layout_constraintBottom_toTopOf="@+id/guideline51"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="@+id/captcha"
            app:layout_constraintTop_toBottomOf="@+id/edit_captcha" />

        <View
            android:id="@+id/view17"
            android:layout_width="0dp"
            android:layout_height="2dp"
            android:layout_marginEnd="32dp"
            android:layout_marginBottom="6dp"
            android:background="#D1D1D1"
            app:layout_constraintBottom_toTopOf="@+id/guideline52"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="@+id/password"
            app:layout_constraintTop_toBottomOf="@+id/edit_password" />

        <View
            android:id="@+id/view18"
            android:layout_width="0dp"
            android:layout_height="2dp"
            android:layout_marginEnd="32dp"
            android:layout_marginBottom="6dp"
            android:background="#D1D1D1"
            app:layout_constraintBottom_toTopOf="@+id/guideline53"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="@+id/confirm_password"
            app:layout_constraintTop_toBottomOf="@+id/edit_confrim_password" />

        <View
            android:id="@+id/view19"
            android:layout_width="0dp"
            android:layout_height="2dp"
            android:layout_marginEnd="32dp"
            android:layout_marginBottom="6dp"
            android:background="#D1D1D1"
            app:layout_constraintBottom_toTopOf="@+id/guideline49"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="@+id/invite_code"
            app:layout_constraintTop_toBottomOf="@+id/edit_invite_code" />

        <android.support.constraint.Guideline
            android:id="@+id/guideline39"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            app:layout_constraintGuide_percent="0.25" />

        <android.support.constraint.Guideline
            android:id="@+id/guideline40"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            app:layout_constraintGuide_percent="0.06" />

        <android.support.constraint.Guideline
            android:id="@+id/guideline43"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            app:layout_constraintGuide_begin="37dp" />

        <ImageView
            android:id="@+id/imageView13"
            android:layout_width="15dp"
            android:layout_height="15dp"
            app:layout_constraintBottom_toTopOf="@+id/guideline45"
            app:layout_constraintEnd_toStartOf="@+id/guideline39"
            app:layout_constraintStart_toStartOf="@+id/guideline40"
            app:layout_constraintTop_toTopOf="@+id/guideline49"
            app:srcCompat="@drawable/note"
            tools:ignore="ContentDescription" />

        <TextView
            android:id="@+id/textView12"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="16dp"
            android:text="@string/register_member_rule"
            android:textColor="#585858"
            android:textSize="14sp"
            app:layout_constraintBottom_toTopOf="@+id/guideline45"
            app:layout_constraintStart_toEndOf="@+id/imageView13"
            app:layout_constraintTop_toTopOf="@+id/guideline49" />

        <android.support.constraint.Guideline
            android:id="@+id/guideline45"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            app:layout_constraintGuide_percent="0.77" />

        <CheckBox
            android:id="@+id/agree"
            android:layout_width="26dp"
            android:layout_height="26dp"
            android:background="@drawable/selector_cb_check"
            android:button="@null"
            android:gravity="center"
            app:layout_constraintBottom_toTopOf="@+id/guideline46"
            app:layout_constraintEnd_toStartOf="@+id/guideline39"
            app:layout_constraintStart_toStartOf="@+id/guideline40"
            app:layout_constraintTop_toTopOf="@+id/guideline45" />

        <CheckBox
            android:id="@+id/agree2"
            android:layout_width="26dp"
            android:layout_height="26dp"
            android:background="@drawable/selector_cb_check"
            android:button="@null"
            android:gravity="center"
            app:layout_constraintBottom_toTopOf="@+id/guideline47"
            app:layout_constraintEnd_toStartOf="@+id/guideline39"
            app:layout_constraintStart_toStartOf="@+id/guideline40"
            app:layout_constraintTop_toTopOf="@+id/guideline46" />

        <TextView
            android:id="@+id/textView20"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/agree"
            android:textColor="#000000"
            app:layout_constraintBottom_toTopOf="@+id/guideline46"
            app:layout_constraintStart_toStartOf="@+id/guideline48"
            app:layout_constraintTop_toTopOf="@+id/guideline45" />

        <android.support.constraint.Guideline
            android:id="@+id/guideline46"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            app:layout_constraintGuide_percent="0.86" />

        <android.support.constraint.Guideline
            android:id="@+id/guideline47"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            app:layout_constraintGuide_percent="0.95" />

        <TextView
            android:id="@+id/textView85"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/agree"
            android:textColor="#000000"
            app:layout_constraintBottom_toTopOf="@+id/guideline47"
            app:layout_constraintStart_toStartOf="@+id/guideline48"
            app:layout_constraintTop_toTopOf="@+id/guideline46" />

        <android.support.constraint.Guideline
            android:id="@+id/guideline48"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            app:layout_constraintGuide_percent="0.22" />

        <android.support.constraint.Guideline
            android:id="@+id/guideline49"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            app:layout_constraintGuide_percent="0.65" />

        <android.support.constraint.Guideline
            android:id="@+id/guideline50"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            app:layout_constraintGuide_percent="0.17" />

        <android.support.constraint.Guideline
            android:id="@+id/guideline51"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            app:layout_constraintGuide_percent="0.29" />

        <android.support.constraint.Guideline
            android:id="@+id/guideline52"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            app:layout_constraintGuide_percent="0.41" />

        <android.support.constraint.Guideline
            android:id="@+id/guideline53"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            app:layout_constraintGuide_percent="0.53" />

        <Button
            android:onClick="@{viewCtrl::getCodeClick}"
            android:id="@+id/isCaptcha"
            android:layout_width="wrap_content"
            android:layout_height="0dp"
            android:layout_marginBottom="8dp"
            android:background="@drawable/register_button"
            android:text="@string/getCode"
            android:textColor="#ffffff"
            android:textSize="12sp"
            android:visibility="gone"
            app:layout_constraintBottom_toTopOf="@+id/view"
            app:layout_constraintEnd_toEndOf="@+id/view"
            app:layout_constraintTop_toTopOf="@+id/guideline43" />

        <TextView
            android:id="@+id/textView86"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp"
            android:text="會員權益條款"
            android:textColor="#46A79C"
            app:layout_constraintBottom_toBottomOf="@+id/textView20"
            app:layout_constraintStart_toEndOf="@+id/textView20"
            app:layout_constraintTop_toTopOf="@+id/textView20" />

        <TextView
            android:id="@+id/textView88"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp"
            android:text="隱私權條款"
            android:textColor="#46A79C"
            app:layout_constraintBottom_toBottomOf="@+id/textView85"
            app:layout_constraintStart_toEndOf="@+id/textView85"
            app:layout_constraintTop_toTopOf="@+id/textView85" />

        <View
            android:background="#46A79C"
            android:id="@+id/view15"
            android:layout_width="0dp"
            android:layout_height="1dp"
            app:layout_constraintEnd_toEndOf="@+id/textView86"
            app:layout_constraintStart_toStartOf="@+id/textView86"
            app:layout_constraintTop_toBottomOf="@+id/textView86" />

        <View
            android:id="@+id/view20"
            android:layout_width="0dp"
            android:layout_height="1dp"
            android:background="#46A79C"
            app:layout_constraintEnd_toEndOf="@+id/textView88"
            app:layout_constraintStart_toStartOf="@+id/textView88"
            app:layout_constraintTop_toBottomOf="@+id/textView88" />


    </android.support.constraint.ConstraintLayout>
</layout>

3.設定開始動畫

private fun beginAnimation(v: View?, text: TextView) {           
    ObjectAnimator.ofFloat(v, "translationX", 0f, editMoveLeft).setDuration(500).start()
    ObjectAnimator.ofFloat(text, "translationY", 0f, titleMoveTop).setDuration(500).start()
    ObjectAnimator.ofFloat(text, "translationX", 0f, titleMoveRight).setDuration(500).start()
    ObjectAnimator.ofFloat(text, "scaleX", 1f, 0.9f).setDuration(500).start()
    ObjectAnimator.ofFloat(text, "scaleY", 1f, 0.9f).setDuration(500).start()
    val circle = fragment.resources.getDrawable(R.drawable.register_circle)
    view.compoundDrawablePadding = 20
    view.setCompoundDrawablesWithIntrinsicBounds(circle, null, null, null)
}

4.設定結束動畫

private fun endAnimation(v: View?, text: TextView) {
    ObjectAnimator.ofFloat(v, "translationX", editMoveLeft, 0f).setDuration(1000).start()
    ObjectAnimator.ofFloat(text, "translationY", titleMoveTop, 0f).setDuration(1000).start()
    ObjectAnimator.ofFloat(text, "translationX", titleMoveRight, 0f).setDuration(1000).start()
    ObjectAnimator.ofFloat(text, "scaleX", 0.9f, 1f).setDuration(1000).start()
    ObjectAnimator.ofFloat(text, "scaleY", 0.9f, 1f).setDuration(1000).start()
    text.compoundDrawablePadding = 0
    text.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null)
 }

5.監聽是否會取焦點(有開始動畫,沒有結束動畫)

binding.editAccount.onFocusChangeListener = this
binding.editPassword.onFocusChangeListener = this
binding.editCaptcha.onFocusChangeListener = this
binding.editConfrimPassword.onFocusChangeListener = this
binding.editInviteCode.onFocusChangeListener = this
 override fun onFocusChange(v: View?, hasFocus: Boolean) {
        when (v?.id) {
            R.id.edit_account -> {
                if (hasFocus) {
                    beginAnimation(v, binding.account)
                } else {
                    endAnimation(v, binding.account)
                }
            }
            R.id.edit_captcha -> {
                if (hasFocus) {
                    beginAnimation(v, binding.captcha)
                } else {
                    endAnimation(v, binding.captcha)
                }
            }
            R.id.edit_password -> {
                if (hasFocus) {
                    beginAnimation(v, binding.password)
                } else {
                    endAnimation(v, binding.password)
                }
            }
            R.id.edit_confrim_password -> {
                if (hasFocus) {
                    beginAnimation(v, binding.confirmPassword)
                } else {
                    endAnimation(v, binding.confirmPassword)
                }
            }
            R.id.edit_invite_code -> {
                if (hasFocus) {
                    beginAnimation(v, binding.inviteCode)
                } else {
                    endAnimation(v, binding.inviteCode)
                }
            }
        }
    }

6.展示結果

發表迴響