-
Notifications
You must be signed in to change notification settings - Fork 687
/
KPSwitchRootLayoutHandler.java
145 lines (122 loc) · 5.52 KB
/
KPSwitchRootLayoutHandler.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/*
* Copyright (C) 2015-2017 Jacksgong(blog.dreamtobe.cn)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.dreamtobe.kpswitch.handler;
import android.annotation.TargetApi;
import android.app.Activity;
import android.graphics.Rect;
import android.os.Build;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import cn.dreamtobe.kpswitch.IPanelConflictLayout;
import cn.dreamtobe.kpswitch.util.KeyboardUtil;
import cn.dreamtobe.kpswitch.util.StatusBarHeightUtil;
import cn.dreamtobe.kpswitch.util.ViewUtil;
/**
* Created by Jacksgong on 3/30/16.
*
* @see cn.dreamtobe.kpswitch.widget.KPSwitchRootFrameLayout
* @see cn.dreamtobe.kpswitch.widget.KPSwitchRootLinearLayout
* @see cn.dreamtobe.kpswitch.widget.KPSwitchRootRelativeLayout
*/
public class KPSwitchRootLayoutHandler {
private static final String TAG = "KPSRootLayoutHandler";
private int mOldHeight = -1;
private final View mTargetRootView;
private final int mStatusBarHeight;
private final boolean mIsTranslucentStatus;
public KPSwitchRootLayoutHandler(final View rootView) {
this.mTargetRootView = rootView;
this.mStatusBarHeight = StatusBarHeightUtil.getStatusBarHeight(rootView.getContext());
final Activity activity = (Activity) rootView.getContext();
this.mIsTranslucentStatus = ViewUtil.isTranslucentStatus(activity);
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public void handleBeforeMeasure(final int width, int height) {
// 由当前布局被键盘挤压,获知,由于键盘的活动,导致布局将要发生变化。
if (mIsTranslucentStatus && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN
&& mTargetRootView.getFitsSystemWindows()) {
// In this case, the height is always the same one, so, we have to calculate below.
final Rect rect = new Rect();
mTargetRootView.getWindowVisibleDisplayFrame(rect);
height = rect.bottom - rect.top;
}
Log.d(TAG, "onMeasure, width: " + width + " height: " + height);
if (height < 0) {
return;
}
if (mOldHeight < 0) {
mOldHeight = height;
return;
}
final int offset = mOldHeight - height;
if (offset == 0) {
Log.d(TAG, "" + offset + " == 0 break;");
return;
}
if (Math.abs(offset) == mStatusBarHeight) {
Log.w(TAG, String.format("offset just equal statusBar height %d", offset));
// 极有可能是 相对本页面的二级页面的主题是全屏&是透明,但是本页面不是全屏,因此会有status bar的布局变化差异,进行调过
// 极有可能是 该布局采用了透明的背景(windowIsTranslucent=true),而背后的布局`full screen`为false,
// 因此有可能第一次绘制时没有attach上status bar,而第二次status bar attach上去,导致了这个变化。
return;
}
mOldHeight = height;
final IPanelConflictLayout panel = getPanelLayout(mTargetRootView);
if (panel == null) {
Log.w(TAG, "can't find the valid panel conflict layout, give up!");
return;
}
// 检测到布局变化非键盘引起
if (Math.abs(offset) < KeyboardUtil.getMinKeyboardHeight(mTargetRootView.getContext())) {
Log.w(TAG, "system bottom-menu-bar(such as HuaWei Mate7) causes layout changed");
return;
}
if (offset > 0) {
//键盘弹起 (offset > 0,高度变小)
panel.handleHide();
} else if (panel.isKeyboardShowing() && panel.isVisible()) {
// 1. 总得来说,在监听到键盘已经显示的前提下,键盘收回才是有效有意义的。
// 2. 修复在Android L下使用V7.Theme.AppCompat主题,进入Activity,默认弹起面板bug,
// 第2点的bug出现原因:在Android L下使用V7.Theme.AppCompat主题,并且
// 不使用系统的ActionBar/ToolBar,V7.Theme.AppCompat主题,还是会先默认绘制一帧默认ActionBar,
// 然后再将他去掉(略无语)
//键盘收回 (offset < 0,高度变大)
// the panel is showing/will showing
panel.handleShow();
}
}
private IPanelConflictLayout mPanelLayout;
private IPanelConflictLayout getPanelLayout(final View view) {
if (mPanelLayout != null) {
return mPanelLayout;
}
if (view instanceof IPanelConflictLayout) {
mPanelLayout = (IPanelConflictLayout) view;
return mPanelLayout;
}
if (view instanceof ViewGroup) {
for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
IPanelConflictLayout v = getPanelLayout(((ViewGroup) view).getChildAt(i));
if (v != null) {
mPanelLayout = v;
return mPanelLayout;
}
}
}
return null;
}
}