實現一個帶浮動標籤的輸入框

現在帶浮動標籤的輸入框也是一個很常見的東西了,在材料設計裏面有一個TextInputLayout的控件,我們可以用它實現這個效果。但是材料設計控件的樣式比較固定,並不能滿足我們產品設計的腦洞。這裏提供一個用屬性動畫實現的方法。

還是先看看效果吧:


大概的思路是這樣的:

  • 控件有兩層,一層是浮動的標籤,一層是輸入框。
  • 當點擊控件後,標籤同時執行一個橫向和縱向的縮放動畫,還有一個向上移動的動畫,讓輸入框獲取到焦點並彈出鍵盤。
  • 當輸入框失去焦點時,判斷是否有內容,如果沒有則讓標籤執行一個復原的動畫。

下面看看控件的佈局:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/fl_content"
    android:layout_width="match_parent"
    android:layout_height="55dp"
    android:background="@color/white"
    android:orientation="vertical"
    android:paddingLeft="20dp">

    <EditText
        android:id="@+id/et_content_name"
        android:layout_width="match_parent"
        android:layout_height="30dp"
        android:layout_gravity="center_vertical"
        android:background="@color/white"
        android:textColor="@color/black"
        android:textCursorDrawable="@null"
        android:textSize="14sp"
        android:visibility="gone" />

    <TextView
        android:id="@+id/tv_content_hint"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:text="標題"
        android:textColor="@color/text_gray"
        android:textSize="14sp"
        android:transformPivotX="0dp"
        android:transformPivotY="-30dp" />

</FrameLayout>

由於EditText會默認獲取到焦點,所以我先把它隱藏了。這裏面值得注意的是transformPivotXY這個參數,等下會講到。

然後我們創建標籤向上縮放的方法,代碼如下:

public void animationUp() {
    ObjectAnimator scaleX = ObjectAnimator.ofFloat(tvHint, "scaleX", 0.6f);
    ObjectAnimator scaleY = ObjectAnimator.ofFloat(tvHint, "scaleY", 0.6f);

    AnimatorSet animatorSet = new AnimatorSet();
    animatorSet.setDuration(100);
    animatorSet.setInterpolator(new DecelerateInterpolator());
    animatorSet.play(scaleX).with(scaleY); //兩個動畫同時開始
    animatorSet.start();

    animatorSet.addListener(new Animator.AnimatorListener() {
        @Override
        public void onAnimationStart(Animator animation) {
        }

        @Override
        public void onAnimationEnd(Animator animation) {
            etContent.setVisibility(View.VISIBLE);
            etContent.requestFocus();
            //彈出鍵盤
            InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
            imm.showSoftInput(etContent, 0);
        }

        @Override
        public void onAnimationCancel(Animator animation) {

        }

        @Override
        public void onAnimationRepeat(Animator animation) {

        }
    });
}

代碼不難理解,就是同時執行了橫向和縱向的縮放動畫,讓標籤縮小到60%。動畫執行完後顯示EditText,讓它獲取到焦點並彈出鍵盤。如果animatorSet.setInterpolator(new DecelerateInterpolator());這句不懂的話,看看下面這張圖就明白了:


Interpolator.png

到這裏,你可能還有的一個疑問就是,向上移動的動畫呢?
縮放動畫是根據控件的基準座標來進行縮放的。也就是說,當我們把基準座標設在控件上方時,縮放的時候也會有一個移動的效果。所以在佈局裏面用

android:transformPivotX="0dp"
android:transformPivotY="-30dp"

將標籤的基準點設爲(0dp, -30dp),這樣我們就省去了移動動畫。

至於復原的動畫,就更簡單了:

public void animationDown() {
    etContent.setVisibility(View.GONE);

    ObjectAnimator scaleX = ObjectAnimator.ofFloat(tvHint, "scaleX", 1);
    ObjectAnimator scaleY = ObjectAnimator.ofFloat(tvHint, "scaleY", 1);

    AnimatorSet animatorSet = new AnimatorSet();
    animatorSet.setDuration(100);
    animatorSet.setInterpolator(new DecelerateInterpolator());
    animatorSet.play(scaleX).with(scaleY); //兩個動畫同時開始
    animatorSet.start();
}

爲了實現失去焦點,標籤復原,我們需要監聽輸入框是否有焦點:

etContent.setOnFocusChangeListener(new OnFocusChangeListener() {
    @Override
    public void onFocusChange(View view, boolean b) {
        if (!b && TextUtils.isEmpty(etContent.getText())) {
            animationDown();
        }
    }
});

這樣就已經完成了一個帶浮動標籤的輸入框,妥妥的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章