-
Notifications
You must be signed in to change notification settings - Fork 687
/
KPSwitchConflictUtil.java
348 lines (311 loc) · 14.4 KB
/
KPSwitchConflictUtil.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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
/*
* 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.util;
import android.app.Activity;
import android.view.MotionEvent;
import android.view.View;
import cn.dreamtobe.kpswitch.handler.KPSwitchFSPanelLayoutHandler;
import cn.dreamtobe.kpswitch.handler.KPSwitchPanelLayoutHandler;
import cn.dreamtobe.kpswitch.handler.KPSwitchRootLayoutHandler;
/**
* Created by Jacksgong on 3/30/16.
* <p/>
* This util will help you control your panel and keyboard easily and exactly with
* non-layout-conflict.
* <p/>
* This util just support the application layer encapsulation, more detail for how to resolve
* the layout-conflict please Ref {@link KPSwitchRootLayoutHandler}、
* {@link KPSwitchPanelLayoutHandler}、{@link KPSwitchFSPanelLayoutHandler}
* <p/>
* Any problems: https://github.com/Jacksgong/JKeyboardPanelSwitch
*
* @see KPSwitchRootLayoutHandler
* @see KPSwitchPanelLayoutHandler
* @see KPSwitchFSPanelLayoutHandler
*/
public class KPSwitchConflictUtil {
// whether current activity is in multi window mode
private static boolean mIsInMultiWindowMode = false;
/**
* @see #attach(View, View, View, SwitchClickListener)
*/
public static void attach(final View panelLayout,
/* Nullable **/final View switchPanelKeyboardBtn,
/* Nullable **/final View focusView) {
attach(panelLayout, switchPanelKeyboardBtn, focusView, null);
}
/**
* Attach the action of {@code switchPanelKeyboardBtn} and the {@code focusView} to
* non-layout-conflict.
* <p/>
* You do not have to use this method to attach non-layout-conflict, in other words, you can
* attach the action by yourself with invoke methods manually: {@link #showPanel(View)}、
* {@link #showKeyboard(View, View)}、{@link #hidePanelAndKeyboard(View)}, and in the case of
* don't invoke this method to attach, and if your activity with the fullscreen-theme, please
* ensure your panel layout is {@link View#INVISIBLE} before the keyboard is going to show.
*
* @param panelLayout the layout of panel.
* @param switchPanelKeyboardBtn the view will be used to trigger switching between the panel
* and the keyboard.
* @param focusView the view will be focused or lose the focus.
* @param switchClickListener the click listener is used to listening the click event for
* {@code switchPanelKeyboardBtn}.
* @see #attach(View, View, SwitchClickListener, SubPanelAndTrigger...)
*/
public static void attach(final View panelLayout,
/* Nullable **/final View switchPanelKeyboardBtn,
/* Nullable **/final View focusView,
/* Nullable **/final SwitchClickListener switchClickListener) {
final Activity activity = (Activity) panelLayout.getContext();
if (switchPanelKeyboardBtn != null) {
switchPanelKeyboardBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final boolean switchToPanel = switchPanelAndKeyboard(panelLayout, focusView);
if (switchClickListener != null) {
switchClickListener.onClickSwitch(v, switchToPanel);
}
}
});
}
if (isHandleByPlaceholder(activity)) {
focusView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
/*
* Show the fake empty keyboard-same-height panel to fix the conflict when
* keyboard going to show.
* @see KPSwitchConflictUtil#showKeyboard(View, View)
*/
panelLayout.setVisibility(View.INVISIBLE);
}
return false;
}
});
}
}
/**
* The same to {@link #attach(View, View, SwitchClickListener, SubPanelAndTrigger...)}.
*/
public static void attach(final View panelLayout,
final View focusView,
SubPanelAndTrigger... subPanelAndTriggers) {
attach(panelLayout, focusView, null, subPanelAndTriggers);
}
/**
* If you have multiple sub-panels in the {@code panelLayout}, you can use this method to simply
* attach them to non-layout-conflict. otherwise you can use {@link #attach(View, View, View)}
* or {@link #attach(View, View, View, SwitchClickListener)}.
*
* @param panelLayout the layout of panel.
* @param focusView the view will be focused or lose the focus.
* @param switchClickListener the listener is used to listening whether the panel is showing or
* keyboard is showing with toggle the panel/keyboard state.
* @param subPanelAndTriggers the array of the trigger-toggle-view and
* the sub-panel which bound trigger-toggle-view.
*/
public static void attach(final View panelLayout,
final View focusView,
/** Nullable **/final SwitchClickListener switchClickListener,
SubPanelAndTrigger... subPanelAndTriggers) {
final Activity activity = (Activity) panelLayout.getContext();
for (SubPanelAndTrigger subPanelAndTrigger : subPanelAndTriggers) {
bindSubPanel(subPanelAndTrigger, subPanelAndTriggers,
focusView, panelLayout, switchClickListener);
}
if (KPSwitchConflictUtil.isHandleByPlaceholder(activity)) {
focusView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
/**
* Show the fake empty keyboard-same-height panel to fix the conflict when
* keyboard going to show.
* @see KPSwitchConflictUtil#showKeyboard(View, View)
*/
panelLayout.setVisibility(View.INVISIBLE);
}
return false;
}
});
}
}
/**
* @see #attach(View, View, SwitchClickListener, SubPanelAndTrigger...)
*/
public static class SubPanelAndTrigger {
/**
* The sub-panel view is the child of panel-layout.
*/
final View subPanelView;
/**
* The trigger view is used for triggering the {@code subPanelView} VISIBLE state.
*/
final View triggerView;
public SubPanelAndTrigger(View subPanelView, View triggerView) {
this.subPanelView = subPanelView;
this.triggerView = triggerView;
}
}
/**
* To show the panel(hide the keyboard automatically if the keyboard is showing) with
* non-layout-conflict.
*
* @param panelLayout the layout of panel.
* @see KPSwitchPanelLayoutHandler
*/
public static void showPanel(final View panelLayout) {
final Activity activity = (Activity) panelLayout.getContext();
panelLayout.setVisibility(View.VISIBLE);
if (activity.getCurrentFocus() != null) {
KeyboardUtil.hideKeyboard(activity.getCurrentFocus());
}
}
/**
* To show the keyboard(hide the panel automatically if the panel is showing) with
* non-layout-conflict.
*
* @param panelLayout the layout of panel.
* @param focusView the view will be focused.
*/
public static void showKeyboard(final View panelLayout, final View focusView) {
final Activity activity = (Activity) panelLayout.getContext();
KeyboardUtil.showKeyboard(focusView);
if (isHandleByPlaceholder(activity)) {
panelLayout.setVisibility(View.INVISIBLE);
} else if (mIsInMultiWindowMode) {
panelLayout.setVisibility(View.GONE);
}
}
/**
* If the keyboard is showing, then going to show the {@code panelLayout},
* and hide the keyboard with non-layout-conflict.
* <p/>
* If the panel is showing, then going to show the keyboard,
* and hide the {@code panelLayout} with non-layout-conflict.
* <p/>
* If the panel and the keyboard are both hiding. then going to show the {@code panelLayout}
* with non-layout-conflict.
*
* @param panelLayout the layout of panel.
* @param focusView the view will be focused or lose the focus.
* @return If true, switch to showing {@code panelLayout}; If false, switch to showing Keyboard.
*/
public static boolean switchPanelAndKeyboard(final View panelLayout, final View focusView) {
boolean switchToPanel = panelLayout.getVisibility() != View.VISIBLE;
if (!switchToPanel) {
showKeyboard(panelLayout, focusView);
} else {
showPanel(panelLayout);
}
return switchToPanel;
}
/**
* Hide the panel and the keyboard.
*
* @param panelLayout the layout of panel.
*/
public static void hidePanelAndKeyboard(final View panelLayout) {
final Activity activity = (Activity) panelLayout.getContext();
final View focusView = activity.getCurrentFocus();
if (focusView != null) {
KeyboardUtil.hideKeyboard(activity.getCurrentFocus());
focusView.clearFocus();
}
panelLayout.setVisibility(View.GONE);
}
/**
* This listener is used to listening the click event for a view which is received the click
* event to switch between Panel and Keyboard.
*
* @see #attach(View, View, View, SwitchClickListener)
*/
public interface SwitchClickListener {
/**
* @param v The view that was clicked.
* @param switchToPanel If true, switch to showing Panel; If false, switch to showing
* Keyboard.
*/
void onClickSwitch(View v, boolean switchToPanel);
}
/**
* @param isFullScreen Whether in fullscreen theme.
* @param isTranslucentStatus Whether in translucent status theme.
* @param isFitsSystem Whether the root view(the child of the content view) is in
* {@code getFitSystemWindow()} equal true.
* @return Whether handle the conflict by show panel placeholder, otherwise, handle by delay the
* visible or gone of panel.
*/
public static boolean isHandleByPlaceholder(boolean isFullScreen, boolean isTranslucentStatus,
boolean isFitsSystem) {
return isFullScreen || (isTranslucentStatus && !isFitsSystem);
}
static boolean isHandleByPlaceholder(final Activity activity) {
return isHandleByPlaceholder(ViewUtil.isFullScreen(activity),
ViewUtil.isTranslucentStatus(activity), ViewUtil.isFitsSystemWindows(activity));
}
private static void bindSubPanel(final SubPanelAndTrigger subPanelAndTrigger,
final SubPanelAndTrigger[] subPanelAndTriggers,
final View focusView, final View panelLayout,
/* Nullable */final SwitchClickListener switchClickListener) {
final View triggerView = subPanelAndTrigger.triggerView;
final View boundTriggerSubPanelView = subPanelAndTrigger.subPanelView;
triggerView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Boolean switchToPanel = null;
if (panelLayout.getVisibility() == View.VISIBLE) {
// panel is visible.
if (boundTriggerSubPanelView.getVisibility() == View.VISIBLE) {
// bound-trigger panel is visible.
// to show keyboard.
KPSwitchConflictUtil.showKeyboard(panelLayout, focusView);
switchToPanel = false;
} else {
// bound-trigger panel is invisible.
// to show bound-trigger panel.
showBoundTriggerSubPanel(boundTriggerSubPanelView, subPanelAndTriggers);
}
} else {
// panel is gone.
// to show panel.
KPSwitchConflictUtil.showPanel(panelLayout);
switchToPanel = true;
// to show bound-trigger panel.
showBoundTriggerSubPanel(boundTriggerSubPanelView, subPanelAndTriggers);
}
if (switchClickListener != null && switchToPanel != null) {
switchClickListener.onClickSwitch(v, switchToPanel);
}
}
});
}
private static void showBoundTriggerSubPanel(final View boundTriggerSubPanelView,
final SubPanelAndTrigger[] subPanelAndTriggers) {
// to show bound-trigger panel.
for (SubPanelAndTrigger panelAndTrigger : subPanelAndTriggers) {
if (panelAndTrigger.subPanelView != boundTriggerSubPanelView) {
// other sub panel.
panelAndTrigger.subPanelView.setVisibility(View.GONE);
}
}
boundTriggerSubPanelView.setVisibility(View.VISIBLE);
}
public static void onMultiWindowModeChanged(boolean isInMultiWindowMode) {
mIsInMultiWindowMode = isInMultiWindowMode;
}
}