Android登陸頁面仿拉鉤動(dòng)效,你總會(huì)需要它!
哈哈,看到這個(gè)標(biāo)題是不是JH一緊,你可能會(huì)說我就沒遇到過,但是現(xiàn)在沒遇到不代表就遇不到,畢竟設(shè)計(jì)也是變幻莫測,只有你想不到的,沒有你不能實(shí)現(xiàn)的,說的這么吊,到底是啥效果?沒錯(cuò)就是一個(gè)小小的登錄頁面,大家都有拉勾app吧,看拉勾的登錄頁做的很是平滑動(dòng)畫,而且?guī)?dòng)畫效果,所以就有了類似拉勾登錄效果,如圖:
雖然是個(gè)簡單的頁面,但是涵蓋的東西不算少啊,很納悶為何谷歌一直不提供簡單,方便,準(zhǔn)確的鍵盤監(jiān)聽事件?惆悵啊,所以我們只能自己從側(cè)面監(jiān)聽鍵盤事件了,我們可以監(jiān)聽最外層布局的變化來判斷鍵盤是不是彈起了。閑話不多說,上車吧。
布局文件,大家都能看懂吧。
我們要想監(jiān)聽鍵盤事件,首先我們想得到的是鍵盤彈起的時(shí)候我們可以去搞點(diǎn)事情,鍵盤搜起的時(shí)候我們?cè)偃ジ泓c(diǎn)事情,知道這些還不夠,我們還要知道鍵盤彈起了多少,以及需要平移多少的距離。我們都知道我們的一個(gè)頁面彈起鍵盤的時(shí)候這個(gè)頁面的根布局會(huì)回調(diào)他的監(jiān)聽方法:addOnLayoutChangeListener( );當(dāng)鍵盤彈起的時(shí)候,我們的布局是變化了,因此會(huì)執(zhí)行這個(gè)回調(diào)方法,但是前提是必須設(shè)置我們的Activity的windowSoftInputMode屬性為adjustResize。
我們想讓布局整體平移的距離也就是彈起時(shí)候處于***部的view距離頂部的高度減去我們鍵盤的高度?,F(xiàn)在認(rèn)為只要控件將Activity向上推的高度超過了1/3屏幕高,就認(rèn)為軟鍵盤彈起
- scrollView.addOnLayoutChangeListener(new ViewGroup.OnLayoutChangeListener() {
- @Override
- public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
- /* old是改變前的左上右下坐標(biāo)點(diǎn)值,沒有old的是改變后的左上右下坐標(biāo)點(diǎn)值
- 現(xiàn)在認(rèn)為只要控件將Activity向上推的高度超過了1/3屏幕高,就認(rèn)為軟鍵盤彈起*/
- if (oldBottom != 0 && bottom != 0 && (oldBottom - bottom > keyHeight)) {
- Log.e("wenzhihao", "up------>"+(oldBottom - bottom));
- int dist = btn_login.getBottom() - bottom;
- if (dist>0){
- ObjectAnimator mAnimatorTranslateY = ObjectAnimator.ofFloat(content, "translationY", 0.0f, -dist);
- mAnimatorTranslateY.setDuration(300);
- mAnimatorTranslateY.setInterpolator(new LinearInterpolator());
- mAnimatorTranslateY.start();
- zoomIn(logo, dist);
- }
- service.setVisibility(View.INVISIBLE);
- } else if (oldBottom != 0 && bottom != 0 && (bottom - oldBottom > keyHeight)) {
- Log.e("wenzhihao", "down------>"+(bottom - oldBottom));
- if ((btn_login.getBottom() - oldBottom)>0){
- ObjectAnimator mAnimatorTranslateY = ObjectAnimator.ofFloat(content, "translationY", content.getTranslationY(), 0);
- mAnimatorTranslateY.setDuration(300);
- mAnimatorTranslateY.setInterpolator(new LinearInterpolator());
- mAnimatorTranslateY.start();
- //鍵盤收回后,logo恢復(fù)原來大小,位置同樣回到初始位置
- zoomOut(logo);
- }
- service.setVisibility(View.VISIBLE);
- }
- }
- });
- /n_login是登錄按鈕
這樣我們發(fā)現(xiàn)是可以實(shí)現(xiàn)效果了,但是我想全屏顯示,懵比了,發(fā)現(xiàn)全屏的時(shí)候不回調(diào)這個(gè)方法了,怎么辦?又是查資料一看原來這個(gè)也是一個(gè)bug,但是有解決方案,AndroidBug5497Workaround。也是谷歌提供的?直接拷貝過來,會(huì)發(fā)現(xiàn)其實(shí)他的作用就是讓Activity最外層的根布局,當(dāng)有布局變化時(shí)去響應(yīng)這個(gè)變化mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener();
- package com.wzh.study.login;
- import android.app.Activity;
- import android.graphics.Rect;
- import android.view.View;
- import android.view.ViewTreeObserver;
- import android.widget.FrameLayout;
- public class AndroidBug5497Workaround {
- // For more information, see https://code.google.com/p/android/issues/detail?id=5497
- // To use this class, simply invoke assistActivity() on an Activity that already has its content view set.
- public static void assistActivity (Activity activity) {
- new AndroidBug5497Workaround(activity);
- }
- private View mChildOfContent;
- private int usableHeightPrevious;
- private FrameLayout.LayoutParams frameLayoutParams;
- private AndroidBug5497Workaround(Activity activity) {
- FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content);
- mChildOfContent = content.getChildAt(0);
- mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
- public void onGlobalLayout() {
- possiblyResizeChildOfContent();
- }
- });
- frameLayoutParams = (FrameLayout.LayoutParams) mChildOfContent.getLayoutParams();
- }
- private void possiblyResizeChildOfContent() {
- int usableHeightNow = computeUsableHeight();
- if (usableHeightNow != usableHeightPrevious) {
- int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight();
- int heightDifference = usableHeightSansKeyboard - usableHeightNow;
- if (heightDifference > (usableHeightSansKeyboard/4)) {
- // keyboard probably just became visible
- frameLayoutParams.height = usableHeightSansKeyboard - heightDifference;
- } else {
- // keyboard probably just became hidden
- frameLayoutParams.height = usableHeightSansKeyboard;
- }
- mChildOfContent.requestLayout();
- usableHeightPrevious = usableHeightNow;
- }
- }
- private int computeUsableHeight() {
- Rect r = new Rect();
- mChildOfContent.getWindowVisibleDisplayFrame(r);
- return (r.bottom - r.top);
- }
- }
使用方式,如果我們?cè)O(shè)置了全屏,就去加載它,不設(shè)置不管:
- if(isFullScreen(this)){
- AndroidBug5497Workaround.assistActivity(this);
- }
- ...
- public boolean isFullScreen(Activity activity) {
- return (activity.getWindow().getAttributes().flags &
- WindowManager.LayoutParams.FLAG_FULLSCREEN)==WindowManager.LayoutParams.FLAG_FULLSCREEN;
- }
接下來就看具體動(dòng)畫事件了,鍵盤彈起來的時(shí)候整體向上平移,LOGO縮小,鍵盤收起的時(shí)候整體下移,并且LOGO恢復(fù)原來大小。這里用到的都是屬性動(dòng)畫,只有屬性動(dòng)畫我們才可以實(shí)現(xiàn)真正平移效果。
我看網(wǎng)上很多人使用addOnLayoutChangeListener()去監(jiān)聽鍵盤事件,但是這個(gè)方法回調(diào)的太頻繁,比如本例特效,輸入框后面有文字時(shí)候顯示清除的圖標(biāo),如果用這個(gè)方法那么也會(huì)執(zhí)行一次,可能會(huì)影響你的動(dòng)畫,當(dāng)然你也可以去記錄***次的高度讓他不會(huì)走邏輯,但是我覺得也不是很靠譜,雖然我這個(gè)方法也不是很棒 ๑乛◡乛๑~。
***貼上源碼:
如果有什么問題歡迎指出,我將給出例子地址,包含另一種實(shí)現(xiàn)方式就是用scrollview滑動(dòng)到***部的方式來實(shí)現(xiàn)平移效果~