Android—登陸頁(yè)面仿拉鉤平滑動(dòng)畫過(guò)度動(dòng)效(二)

之前記錄過(guò)一篇實(shí)現(xiàn)仿拉鉤特效的文章,那個(gè)實(shí)現(xiàn)的還是存在一些問(wèn)題的,根據(jù)一些網(wǎng)友的反饋的情況冒冬,所以今天有時(shí)間又看了一下這個(gè)效果。今天帶來(lái)相對(duì)完美一點(diǎn)的demo摩渺,關(guān)于鍵盤事件參考了Stack Overflow上以為大神的做法简烤,在此基礎(chǔ)上稍微修改了一些bug。鏈接

效果

失真動(dòng)態(tài)效果圖

中心思想就是activity根布局監(jiān)聽布局變化摇幻,實(shí)現(xiàn)ViewTreeObserver.OnGlobalLayoutListener接口,根據(jù)根布局高度變化超過(guò)高度的1/4就是認(rèn)為鍵盤彈起來(lái)了横侦。鏈接上的人是默認(rèn)高度變化超過(guò)100就認(rèn)為鍵盤彈起,并且此處獲取的鍵盤的高度沒有減去狀態(tài)欄的高度绰姻,我改進(jìn)了一下枉侧,當(dāng)非全屏的時(shí)候獲取的鍵盤高度減去狀態(tài)欄的高度。

修改后的代碼如下:

import android.app.Activity;
import android.graphics.Rect;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.WindowManager;

import java.util.LinkedList;
import java.util.List;

public class KeyboardWatcher implements ViewTreeObserver.OnGlobalLayoutListener {

    public interface SoftKeyboardStateListener {
        void onSoftKeyboardOpened(int keyboardHeightInPx);
        void onSoftKeyboardClosed();
    }

    private final List<SoftKeyboardStateListener> listeners = new LinkedList<SoftKeyboardStateListener>();
    private final View activityRootView;
    private int        lastSoftKeyboardHeightInPx;
    private boolean    isSoftKeyboardOpened;
    private int statusBarHeight = -1;
    public KeyboardWatcher(View activityRootView) {
        this(activityRootView, false);
    }
    public boolean isFullScreen(Activity activity) {
        return (activity.getWindow().getAttributes().flags &
                WindowManager.LayoutParams.FLAG_FULLSCREEN)==WindowManager.LayoutParams.FLAG_FULLSCREEN;
    }
    public KeyboardWatcher(View activityRootView, boolean isSoftKeyboardOpened) {
        this.activityRootView     = activityRootView;
        this.isSoftKeyboardOpened = isSoftKeyboardOpened;
        activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(this);
        //獲取status_bar_height資源的ID
        int resourceId = activityRootView.getContext().getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            //根據(jù)資源ID獲取響應(yīng)的尺寸值
            statusBarHeight = activityRootView.getContext().getResources().getDimensionPixelSize(resourceId);
        }
    }

    @Override
    public void onGlobalLayout() {
        final Rect r = new Rect();
        //r will be populated with the coordinates of your view that area still visible.
        activityRootView.getWindowVisibleDisplayFrame(r);

        final int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top);
        if (!isSoftKeyboardOpened && heightDiff > activityRootView.getRootView().getHeight()/4) {
            isSoftKeyboardOpened = true;
            if ((activityRootView.getContext() instanceof  Activity)
                    && !isFullScreen((Activity) activityRootView.getContext())){
                notifyOnSoftKeyboardOpened(heightDiff-statusBarHeight);
            }else {
                notifyOnSoftKeyboardOpened(heightDiff);
            }

        } else if (isSoftKeyboardOpened && heightDiff < activityRootView.getRootView().getHeight()/4) {
            isSoftKeyboardOpened = false;
            notifyOnSoftKeyboardClosed();
        }
    }

    public void setIsSoftKeyboardOpened(boolean isSoftKeyboardOpened) {
        this.isSoftKeyboardOpened = isSoftKeyboardOpened;
    }

    public boolean isSoftKeyboardOpened() {
        return isSoftKeyboardOpened;
    }

    /**
     * Default value is zero {@code 0}.
     *
     * @return last saved keyboard height in px
     */
    public int getLastSoftKeyboardHeightInPx() {
        return lastSoftKeyboardHeightInPx;
    }

    public void addSoftKeyboardStateListener(SoftKeyboardStateListener listener) {
        listeners.add(listener);
    }

    public void removeSoftKeyboardStateListener(SoftKeyboardStateListener listener) {
        listeners.remove(listener);
    }

    private void notifyOnSoftKeyboardOpened(int keyboardHeightInPx) {
        this.lastSoftKeyboardHeightInPx = keyboardHeightInPx;

        for (SoftKeyboardStateListener listener : listeners) {
            if (listener != null) {
                listener.onSoftKeyboardOpened(keyboardHeightInPx);
            }
        }
    }

    private void notifyOnSoftKeyboardClosed() {
        for (SoftKeyboardStateListener listener : listeners) {
            if (listener != null) {
                listener.onSoftKeyboardClosed();
            }
        }
    }
}

下面開始寫登陸頁(yè)面的布局狂芋,也沒啥難的榨馁,就我這個(gè)方案注意幾點(diǎn)就行:
1.把需要往上移動(dòng)的布局放在一個(gè)容器里面;
2.容器的高度計(jì)算好帜矾,給出定值翼虫;
3.登錄頁(yè)面設(shè)置鍵盤模式為:android:windowSoftInputMode="adjustResize"
4.在KeyboardWatcher.SoftKeyboardStateListener的回調(diào)接口里面處理要處理的事,也就是平移動(dòng)畫之類的屡萤,看著玩耍吧珍剑!

  • void onSoftKeyboardOpened(int keyboardHeightInPx);
  • void onSoftKeyboardClosed();

回顧

這個(gè)跟上次相比還有一個(gè)點(diǎn)就是關(guān)于顯示和隱藏密碼的問(wèn)題:
1.發(fā)現(xiàn)之前項(xiàng)目的顯示和隱藏密碼是動(dòng)態(tài)設(shè)置EditText的inputType來(lái)實(shí)現(xiàn)的,效果不太好死陆,有點(diǎn)鍵盤抖動(dòng)的趕腳招拙。所以用了EditText的setTransformationMethod方法來(lái)實(shí)現(xiàn),想過(guò)看了就知道翔曲,棒棒的~

2.封裝了TextView的上下左右Drawable迫像,可以實(shí)現(xiàn)動(dòng)態(tài)在布局文件設(shè)置大小及資源,省的在Act or Frg去設(shè)置了:

<com.wzh.study.login.suggest.DrawableTextView
        android:id="@+id/logo"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_gravity="center"
        android:layout_marginTop="100dp"
        android:drawablePadding="10dp"
        android:gravity="center_vertical"
        android:text="歡迎登陸"
        android:textSize="18sp"
        android:textStyle="bold"
        app:drawableHeight="40dp"
        app:drawableWidth="120dp"
        app:leftDrawable="@drawable/google" />

drawablePadding屬性照樣使用,只是設(shè)置上下左右圖片的屬性用自定義的吧瞳遍,代碼很簡(jiǎn)單闻妓,不在貼了。

此種方案較之前有很大改進(jìn)掠械,用這個(gè)版本的比較好由缆,有問(wèn)題希望反饋,謝謝~

github地址更新了猾蒂,還是老地址均唉,里面有新東東!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末肚菠,一起剝皮案震驚了整個(gè)濱河市舔箭,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖层扶,帶你破解...
    沈念sama閱讀 206,013評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件箫章,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡镜会,警方通過(guò)查閱死者的電腦和手機(jī)檬寂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,205評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)戳表,“玉大人桶至,你說(shuō)我怎么就攤上這事∝倚瘢” “怎么了镣屹?”我有些...
    開封第一講書人閱讀 152,370評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)价涝。 經(jīng)常有香客問(wèn)我野瘦,道長(zhǎng),這世上最難降的妖魔是什么飒泻? 我笑而不...
    開封第一講書人閱讀 55,168評(píng)論 1 278
  • 正文 為了忘掉前任,我火速辦了婚禮吏廉,結(jié)果婚禮上泞遗,老公的妹妹穿的比我還像新娘。我一直安慰自己席覆,他們只是感情好史辙,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,153評(píng)論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著佩伤,像睡著了一般聊倔。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上生巡,一...
    開封第一講書人閱讀 48,954評(píng)論 1 283
  • 那天耙蔑,我揣著相機(jī)與錄音,去河邊找鬼孤荣。 笑死甸陌,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的盐股。 我是一名探鬼主播钱豁,決...
    沈念sama閱讀 38,271評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼疯汁!你這毒婦竟也來(lái)了牲尺?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,916評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤幌蚊,失蹤者是張志新(化名)和其女友劉穎谤碳,沒想到半個(gè)月后溃卡,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,382評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡估蹄,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,877評(píng)論 2 323
  • 正文 我和宋清朗相戀三年塑煎,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片臭蚁。...
    茶點(diǎn)故事閱讀 37,989評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡最铁,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出垮兑,到底是詐尸還是另有隱情冷尉,我是刑警寧澤畴蹭,帶...
    沈念sama閱讀 33,624評(píng)論 4 322
  • 正文 年R本政府宣布质涛,位于F島的核電站荤胁,受9級(jí)特大地震影響碟渺,放射性物質(zhì)發(fā)生泄漏业稼。R本人自食惡果不足惜扫尖,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,209評(píng)論 3 307
  • 文/蒙蒙 一卸夕、第九天 我趴在偏房一處隱蔽的房頂上張望逝慧。 院中可真熱鬧衬浑,春花似錦捌浩、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,199評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至助币,卻和暖如春浪听,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背眉菱。 一陣腳步聲響...
    開封第一講書人閱讀 31,418評(píng)論 1 260
  • 我被黑心中介騙來(lái)泰國(guó)打工迹栓, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人倍谜。 一個(gè)月前我還...
    沈念sama閱讀 45,401評(píng)論 2 352
  • 正文 我出身青樓迈螟,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親尔崔。 傳聞我的和親對(duì)象是個(gè)殘疾皇子答毫,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,700評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容