現在帶浮動標籤的輸入框也是一個很常見的東西了,在材料設計裡面有一個 TextInputLayout 的控制元件,我們可以用它實現這個效果。但是材料設計控制元件的樣式比較固定,並不能滿足我們產品設計的腦洞。這裡提供一個用屬性動畫實現的方法。
還是先看看效果吧:
![實現一個帶浮動標籤的輸入框](https://i.iter01.com/images/083247077809338d92d3daea0d842822e3f154e67c9bc24814d51cb2834473a6.gif)
大概的思路是這樣的:
- 控制元件有兩層,一層是浮動的標籤,一層是輸入框。
- 當點選控制元件後,標籤同時執行一個橫向和縱向的縮放動畫,還有一個向上移動的動畫,讓輸入框獲取到焦點並彈出鍵盤。
- 當輸入框失去焦點時,判斷是否有內容,如果沒有則讓標籤執行一個復原的動畫。
下面看看控制元件的佈局:
<?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](https://i.iter01.com/images/fbf7df3342385dc9ee092af18dc2b13b442e5593c618f12c262832d9a046ba5e.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();
}
}
});
複製程式碼
這樣就已經完成了一個帶浮動標籤的輸入框,妥妥的。
雖然實現一個這樣的控制元件不難,但我個人還是希望可以使用原生控制元件的,希望移動端的設計能多去了解一下材料設計吧。(T_T)