Android—登陆页面仿拉钩平滑动画过度动效(二)

之前记录过一篇实现仿拉钩特效的文章,那个实现的还是存在一些问题的,根据一些网友的反馈的情况,所以今天有时间又看了一下这个效果。今天带来相对完美一点的demo,关于键盘事件参考了Stack Overflow上以为大神的做法,在此基础上稍微修改了一些bug。链接

效果

《Android—登陆页面仿拉钩平滑动画过度动效(二)》 失真动态效果图

中心思想就是activity根布局监听布局变化,实现ViewTreeObserver.OnGlobalLayoutListener接口,根据根布局高度变化超过高度的1/4就是认为键盘弹起来了。链接上的人是默认高度变化超过100就认为键盘弹起,并且此处获取的键盘的高度没有减去状态栏的高度,我改进了一下,当非全屏的时候获取的键盘高度减去状态栏的高度。

修改后的代码如下:

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) {
            //根据资源ID获取响应的尺寸值
            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();
            }
        }
    }
}

下面开始写登陆页面的布局,也没啥难的,就我这个方案注意几点就行:
1.把需要往上移动的布局放在一个容器里面;
2.容器的高度计算好,给出定值;
3.登录页面设置键盘模式为:android:windowSoftInputMode=”adjustResize”
4.在KeyboardWatcher.SoftKeyboardStateListener的回调接口里面处理要处理的事,也就是平移动画之类的,看着玩耍吧!

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

回顾

这个跟上次相比还有一个点就是关于显示和隐藏密码的问题:
1.发现之前项目的显示和隐藏密码是动态设置EditText的inputType来实现的,效果不太好,有点键盘抖动的赶脚。所以用了EditText的setTransformationMethod方法来实现,想过看了就知道,棒棒的~

2.封装了TextView的上下左右Drawable,可以实现动态在布局文件设置大小及资源,省的在Act or Frg去设置了:

<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属性照样使用,只是设置上下左右图片的属性用自定义的吧,代码很简单,不在贴了。

此种方案较之前有很大改进,用这个版本的比较好,有问题希望反馈,谢谢~

github地址更新了,还是老地址,里面有新东东!

    原文作者:wenzhihao123
    原文地址: https://www.jianshu.com/p/afa9b37f4d24
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞