之前記錄過(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。鏈接
效果
中心思想就是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地址更新了猾蒂,還是老地址均唉,里面有新東東!