iterator = mEmojiLayoutChangeListeners.iterator();
301 | while (iterator.hasNext()) {
302 | iterator.next().onEmojiLayoutChange(isEmojiShow, isKeyboardShow, height);
303 | }
304 | }
305 |
306 | public void hideSoftInput() {
307 | InputMethodManager manager = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
308 | manager.hideSoftInputFromWindow(getWindowToken(), 0);
309 | }
310 |
311 | public void showSoftInput() {
312 | InputMethodManager manager = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
313 | manager.showSoftInputFromInputMethod(getWindowToken(), 0);
314 | }
315 |
316 | /**
317 | * 当键盘显示时, 可以通过此方法返回键盘的高度
318 | */
319 | public int getKeyboardHeight() {
320 | return keyboardHeight;
321 | }
322 |
323 | public boolean isEmojiShow() {
324 | return isEmojiShow;
325 | }
326 |
327 | public boolean isKeyboardShow() {
328 | return isKeyboardShow;
329 | }
330 |
331 | /**
332 | * 当表情显示时, 可以通过此方法返回表情的高度
333 | */
334 | public int getShowEmojiHeight() {
335 | return showEmojiHeight;
336 | }
337 |
338 | /**
339 | * 返回true时, 可以退出. 否则会隐藏键盘或者表情.
340 | */
341 | public boolean requestBackPressed() {
342 | if (isKeyboardShow || isEmojiShow) {
343 | hideEmojiLayout();
344 | return false;
345 | }
346 | return true;
347 | }
348 |
349 | public interface OnEmojiLayoutChangeListener {
350 | /**
351 | * @param height EmojiLayout弹出的高度 或者 键盘弹出的高度
352 | * @param isEmojiShow 表情布局是否显示了
353 | * @param isKeyboardShow 键盘是否显示了
354 | */
355 | void onEmojiLayoutChange(boolean isEmojiShow, boolean isKeyboardShow, int height);
356 | }
357 | }
358 |
--------------------------------------------------------------------------------
/app/src/main/java/com/angcyo/exkeyboarddemo/RSoftInputLayout2.java:
--------------------------------------------------------------------------------
1 | package com.angcyo.exkeyboarddemo;
2 |
3 | import android.animation.Animator;
4 | import android.animation.ObjectAnimator;
5 | import android.animation.TimeInterpolator;
6 | import android.animation.ValueAnimator;
7 | import android.app.Activity;
8 | import android.content.Context;
9 | import android.content.res.TypedArray;
10 | import android.graphics.Rect;
11 | import android.os.Build;
12 | import android.support.annotation.NonNull;
13 | import android.support.annotation.Nullable;
14 | import android.util.AttributeSet;
15 | import android.view.Gravity;
16 | import android.view.View;
17 | import android.view.ViewGroup;
18 | import android.view.Window;
19 | import android.view.WindowInsets;
20 | import android.view.WindowManager;
21 | import android.view.animation.DecelerateInterpolator;
22 | import android.view.inputmethod.InputMethodManager;
23 | import android.widget.FrameLayout;
24 |
25 | import java.util.HashSet;
26 | import java.util.Iterator;
27 |
28 | /**
29 | * Copyright (C) 2016,深圳市红鸟网络科技股份有限公司 All rights reserved.
30 | * 项目名称:
31 | * 类的描述:支持透明状态栏, 支持Dialog, 支持动画
32 | *
33 | * 重写于2019-8-19
34 | * 原理:
35 | * API < 21
36 | * 键盘弹出, 只会回调 onSizeChanged , 相差的高度就是键盘的高度
37 | *
38 | * API >= 21
39 | * 如果未激活 View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN, 那么和 API < 21 的处理方式一样
40 | * 键盘弹出, 会回调 onApplyWindowInsets , insets.getSystemWindowInsetBottom, 就是键盘的高度
41 | * 此时onSizeChange方法不会执行, 应为系统是用 PaddingBottom的方式, 为键盘腾出空间
42 | *
43 | *
44 | * 使用方式:
45 | *
46 | * 1. android:windowSoftInputMode="adjustResize"
47 | *
48 | * 2.
49 | *
50 | *
51 | * <RSoftInputLayout2>
52 | * <第一个必须是内容布局>
53 | * <第二个会被识别为emoji布局, 非必须>
54 | * <其他子布局>
55 | * <其他子布局>
56 | * <其他子布局>
57 | * ...
58 | * </RSoftInputLayout2>
59 | *
60 | *
61 | *
62 | *
63 | * 创建人员:Robi
64 | * 创建时间:2016/12/21 9:01
65 | * 修改人员:Robi
66 | * 修改时间:2019-8-19
67 | * 修改备注:
68 | * Version: 1.0.0
69 | */
70 | public class RSoftInputLayout2 extends FrameLayout {
71 |
72 | public static final int INTENT_NONE = 0;
73 | public static final int INTENT_SHOW_KEYBOARD = 1;
74 | public static final int INTENT_HIDE_KEYBOARD = 2;
75 | public static final int INTENT_SHOW_EMOJI = 3;
76 | public static final int INTENT_HIDE_EMOJI = 4;
77 |
78 | /**
79 | * 是否激活控件
80 | */
81 | private boolean enableSoftInput = true;
82 | private boolean enableSoftInputAnim = true;
83 | /**
84 | * 隐藏和显示的动画 分开控制
85 | */
86 | private boolean enableSoftInputAnimShow = true;
87 | private boolean enableSoftInputAnimHide = true;
88 |
89 | /**
90 | * 可以关闭此开关, 当键盘弹出时, 只有事件回调, 没有界面size处理. (API>=21)
91 | */
92 | private boolean enableSoftInputInset = true;
93 |
94 | /**
95 | * 频繁切换键盘, 延迟检查时长.
96 | * 如果开启了手机的安全密码输入键盘, 可以适当的加大延迟时间. 消除抖动.
97 | */
98 | private int switchCheckDelay = 0;
99 |
100 | private long animDuration = 240;
101 |
102 | /**
103 | * 在软键盘展示的过程中, 动态改变此paddingTop, 需要开启 [enableSoftInputAnim]
104 | * 大于0, 表示激活属性
105 | */
106 | private int animPaddingTop = -1;
107 | /**
108 | * 键盘完全显示时, 依旧需要的padding大小
109 | */
110 | private int animPaddingMinTop = 0;
111 |
112 | /**
113 | * 激活表情布局恢复, (如:显示键盘之前是表情布局, 那么隐藏键盘后就会显示表情布局)
114 | */
115 | private boolean enableEmojiRestore = false;
116 |
117 | /**
118 | * 当键盘未显示过时, 默认的键盘高度
119 | */
120 | int defaultKeyboardHeight = -1;
121 |
122 | /**
123 | * 由于延迟操作带来的意图延迟, 此变量不考虑无延迟
124 | */
125 | int wantIntentAction = INTENT_NONE;
126 | /**
127 | * 当前用户操作的意图
128 | */
129 | int intentAction = INTENT_NONE;
130 | /**
131 | * 最后一次有效的操作意图
132 | */
133 | int lastIntentAction = intentAction;
134 |
135 | /**
136 | * 最后一次的意图, 用来实现表情布局状态恢复
137 | */
138 | int lastRestoreIntentAction = intentAction;
139 | //2级缓存状态
140 | int lastRestoreIntentAction2 = intentAction;
141 |
142 | public RSoftInputLayout2(@NonNull Context context) {
143 | super(context);
144 | initLayout(context, null);
145 | }
146 |
147 | public RSoftInputLayout2(@NonNull Context context, @Nullable AttributeSet attrs) {
148 | super(context, attrs);
149 | initLayout(context, attrs);
150 | }
151 |
152 | private void initLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
153 | TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.RSoftInputLayout2);
154 | defaultKeyboardHeight = array.getDimensionPixelOffset(R.styleable.RSoftInputLayout2_r_default_soft_input_height, defaultKeyboardHeight);
155 | animPaddingTop = array.getDimensionPixelOffset(R.styleable.RSoftInputLayout2_r_soft_input_anim_padding_top, animPaddingTop);
156 | animPaddingMinTop = array.getDimensionPixelOffset(R.styleable.RSoftInputLayout2_r_soft_input_anim_padding_min_top, animPaddingMinTop);
157 | enableSoftInput = array.getBoolean(R.styleable.RSoftInputLayout2_r_enable_soft_input, enableSoftInput);
158 | enableSoftInputAnim = array.getBoolean(R.styleable.RSoftInputLayout2_r_enable_soft_input_anim, enableSoftInputAnim);
159 | setEnableSoftInputAnim(enableSoftInputAnim);
160 |
161 | enableSoftInputAnimShow = array.getBoolean(R.styleable.RSoftInputLayout2_r_enable_soft_input_anim_show, enableSoftInputAnimShow);
162 | enableSoftInputAnimHide = array.getBoolean(R.styleable.RSoftInputLayout2_r_enable_soft_input_anim_hide, enableSoftInputAnimHide);
163 |
164 | enableEmojiRestore = array.getBoolean(R.styleable.RSoftInputLayout2_r_enable_emoji_restore, enableEmojiRestore);
165 | enableSoftInputInset = array.getBoolean(R.styleable.RSoftInputLayout2_r_enable_soft_input_inset, enableSoftInputInset);
166 | switchCheckDelay = array.getInt(R.styleable.RSoftInputLayout2_r_switch_check_delay, switchCheckDelay);
167 | animDuration = array.getInt(R.styleable.RSoftInputLayout2_r_anim_duration, (int) animDuration);
168 | array.recycle();
169 | }
170 |
171 | //
172 |
173 | int contentLayoutMaxHeight = 0;
174 |
175 | @Override
176 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
177 | int widthSize = MeasureSpec.getSize(widthMeasureSpec);
178 | int heightSize = MeasureSpec.getSize(heightMeasureSpec);
179 |
180 | int maxWidth = widthSize - getPaddingLeft() - getPaddingRight();
181 |
182 | int animPaddingTop = calcAnimPaddingTop();
183 | int maxHeight = heightSize - getPaddingTop() - getPaddingBottom() - animPaddingTop;
184 |
185 | boolean layoutFullScreen = isLayoutFullScreen(getContext());
186 | boolean softKeyboardShow = isSoftKeyboardShow();
187 | boolean emojiLayoutShow = isEmojiLayoutShow();
188 |
189 | int bottomHeight = bottomCurrentShowHeight;
190 |
191 | if (isInEditMode()) {
192 | if (emojiLayout == null) {
193 | defaultKeyboardHeight = 0;
194 | }
195 | bottomHeight = defaultKeyboardHeight;
196 | }
197 |
198 | if (isAnimStart()) {
199 | bottomHeight = bottomCurrentShowHeightAnim;
200 | }
201 |
202 | if (contentLayout != null) {
203 | FrameLayout.LayoutParams layoutParams = (LayoutParams) contentLayout.getLayoutParams();
204 |
205 | if (layoutFullScreen) {
206 | contentLayoutMaxHeight = maxHeight - bottomHeight - layoutParams.topMargin - layoutParams.bottomMargin;
207 | } else {
208 | if (softKeyboardShow) {
209 | //这里加动画, 体验不好.
210 | // if (isAnimStart()) {
211 | // contentLayoutMaxHeight = (int) (maxHeight - layoutParams.topMargin - layoutParams.bottomMargin
212 | // + bottomCurrentShowHeight * (1 - animProgress));
213 | // } else {
214 | // contentLayoutMaxHeight = maxHeight - layoutParams.topMargin - layoutParams.bottomMargin;
215 | // }
216 | contentLayoutMaxHeight = maxHeight - layoutParams.topMargin - layoutParams.bottomMargin;
217 | } else {
218 | contentLayoutMaxHeight = maxHeight - bottomHeight - layoutParams.topMargin - layoutParams.bottomMargin;
219 | }
220 | }
221 | int contentLayoutMaxWidth = maxWidth - layoutParams.leftMargin - layoutParams.rightMargin;
222 |
223 | if (layoutParams.height != ViewGroup.LayoutParams.MATCH_PARENT) {
224 | measureChildWithMargins(contentLayout, widthMeasureSpec, 0,
225 | heightMeasureSpec, 0);
226 | }
227 |
228 | if (contentLayout.getMeasuredHeight() > contentLayoutMaxHeight
229 | || layoutParams.height == ViewGroup.LayoutParams.MATCH_PARENT) {
230 | contentLayout.measure(MeasureSpec.makeMeasureSpec(contentLayoutMaxWidth, MeasureSpec.EXACTLY),
231 | MeasureSpec.makeMeasureSpec(contentLayoutMaxHeight, MeasureSpec.EXACTLY));
232 | }
233 |
234 | // L.i("内容高度:" + contentLayout.getMeasuredHeight() +
235 | // " max: " + maxHeight + ":" + contentLayoutMaxHeight + " anim:" + isAnimStart()
236 | // + " top:" + animPaddingTop + " wa:" + wantIntentAction + " la:" + lastIntentAction);
237 | }
238 |
239 | if (emojiLayout != null) {
240 | emojiLayout.measure(MeasureSpec.makeMeasureSpec(maxWidth, MeasureSpec.EXACTLY),
241 | MeasureSpec.makeMeasureSpec(validBottomHeight(), MeasureSpec.EXACTLY));
242 | }
243 |
244 | measureOther(widthMeasureSpec, heightMeasureSpec);
245 |
246 | setMeasuredDimension(widthSize, heightSize);
247 | }
248 |
249 | @Override
250 | protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
251 | int l = getPaddingLeft();
252 | int t = getPaddingTop() + calcAnimPaddingTop();
253 | int r = 0;
254 | int b = 0;
255 |
256 | if (contentLayout != null) {
257 | FrameLayout.LayoutParams layoutParams = (LayoutParams) contentLayout.getLayoutParams();
258 |
259 | r = l + contentLayout.getMeasuredWidth();
260 | b = t + contentLayoutMaxHeight;
261 |
262 | t = b - layoutParams.bottomMargin - contentLayout.getMeasuredHeight();
263 |
264 | contentLayout.layout(l, t, r, b);
265 |
266 | t = contentLayout.getBottom();
267 | }
268 |
269 | if (emojiLayout != null) {
270 | if (isSoftKeyboardShow()) {
271 | t = getMeasuredHeight();
272 | } else if (!isEnableSoftInputAnim() && intentAction == INTENT_HIDE_KEYBOARD) {
273 | t = getMeasuredHeight();
274 | }
275 |
276 | r = l + emojiLayout.getMeasuredWidth();
277 | b = t + emojiLayout.getMeasuredHeight();
278 | emojiLayout.layout(l, t, r, b);
279 | }
280 |
281 | layoutOther();
282 | }
283 |
284 | //键盘/emoji 当前显示的高度
285 | int bottomCurrentShowHeight = 0;
286 | //动画过程中的高度变量
287 | int bottomCurrentShowHeightAnim = 0;
288 | //动画进度
289 | float animProgress = 0f;
290 | int lastKeyboardHeight = 0;
291 |
292 | private Runnable delaySizeChanged;
293 |
294 | @Override
295 | protected void onSizeChanged(int w, int h, int oldw, int oldh) {
296 | // L.i("sizeChanged:" + oldw + "->" + w + " " + oldh + "->" + h +
297 | // " " + intentAction + " k:" + isSoftKeyboardShow() + " anim:" + isAnimStart());
298 |
299 | //低版本适配
300 | boolean layoutFullScreen = isLayoutFullScreen(getContext());
301 | if (!layoutFullScreen) {
302 | if (intentAction == INTENT_SHOW_EMOJI && checkSizeChanged == null) {
303 | return;
304 | }
305 |
306 | if (isFirstLayout(oldw, oldh)) {
307 | if (isSoftKeyboardShow()) {
308 | //软件盘默认是显示状态
309 | oldh = h + getSoftKeyboardHeight();
310 | }
311 | }
312 |
313 | if (handleSizeChange(w, h, oldw, oldh)) {
314 | //有可能是键盘弹出了
315 | int diffHeight = oldh - h;
316 |
317 | boolean softKeyboardShow = isSoftKeyboardShow();
318 |
319 | if (diffHeight > 0) {
320 | if (softKeyboardShow) {
321 | wantIntentAction = INTENT_SHOW_KEYBOARD;
322 | } else {
323 | wantIntentAction = INTENT_SHOW_EMOJI;
324 | }
325 | } else {
326 | if (lastIntentAction == INTENT_SHOW_EMOJI) {
327 | wantIntentAction = INTENT_HIDE_EMOJI;
328 | } else {
329 | wantIntentAction = INTENT_HIDE_KEYBOARD;
330 | }
331 | }
332 | }
333 | } else {
334 | //高版本, 默认显示键盘适配
335 | if (oldw == 0 && oldh == 0) {
336 | if (isSoftKeyboardShow()) {
337 | oldh = h;
338 | h = oldh - getSoftKeyboardHeight();
339 | }
340 | }
341 | }
342 |
343 | //用来解决, 快速切换 emoji布局和键盘或者普通键盘和密码键盘 时, 闪烁的不良体验.
344 | if (delaySizeChanged != null) {
345 | removeCallbacks(delaySizeChanged);
346 | }
347 | delaySizeChanged = new DelaySizeChangeRunnable(w, h, oldw, oldh, wantIntentAction);
348 | if (switchCheckDelay > 0) {
349 | postDelayed(delaySizeChanged, switchCheckDelay);
350 | } else {
351 | delaySizeChanged.run();
352 | }
353 | }
354 |
355 | //
356 |
357 | //
358 |
359 | private void initDefaultKeyboardHeight() {
360 | //恢复上一次键盘的高度
361 | if (defaultKeyboardHeight < 0) {
362 | int lastKeyboardHeight = 0;
363 | if (!isInEditMode()) {
364 | //lastKeyboardHeight = Hawk.get(KEY_KEYBOARD_HEIGHT, 0);
365 | }
366 | if (lastKeyboardHeight <= 0) {
367 | defaultKeyboardHeight = (int) (275 * getResources().getDisplayMetrics().density);
368 | } else {
369 | defaultKeyboardHeight = lastKeyboardHeight;
370 | }
371 | }
372 | }
373 |
374 | private boolean isFirstLayout(int oldw, int oldh) {
375 | return oldw == 0 && oldh == 0 && intentAction == INTENT_NONE;
376 | }
377 |
378 | private boolean handleSizeChange(int w, int h, int oldw, int oldh) {
379 | boolean result = false;
380 |
381 | boolean isFirstLayout = isFirstLayout(oldw, oldh);
382 |
383 | int diffHeight = oldh - h;
384 | if (isFirstLayout) {
385 | //布局第一次显示在界面上, 需要排除默认键盘展示的情况
386 | result = diffHeight != 0;
387 | } else {
388 | if (oldw != 0 && w != oldw) {
389 | //有可能屏幕旋转了
390 | } else {
391 | result = diffHeight != 0;
392 | }
393 | }
394 | return result;
395 | }
396 |
397 | private void setIntentAction(int action) {
398 | if (action == INTENT_NONE || intentAction != action) {
399 | if (intentAction != INTENT_NONE) {
400 | lastIntentAction = intentAction;
401 | }
402 | }
403 | intentAction = action;
404 | wantIntentAction = action;
405 | }
406 |
407 | private void clearIntentAction() {
408 | setIntentAction(INTENT_NONE);
409 | }
410 |
411 | private void measureOther(int widthMeasureSpec, int heightMeasureSpec) {
412 | for (int i = 2; i < getChildCount(); i++) {
413 | final View child = getChildAt(i);
414 | if (child.getVisibility() != GONE) {
415 | measureChildWithMargins(child, widthMeasureSpec, 0,
416 | heightMeasureSpec, 0);
417 | }
418 | }
419 | }
420 |
421 | private void layoutOther() {
422 | final int count = getChildCount();
423 |
424 | final int parentLeft = getPaddingLeft();
425 | final int parentRight = getMeasuredWidth() - getPaddingRight();
426 |
427 | final int parentTop = getPaddingTop();
428 | final int parentBottom = getMeasuredHeight() - getPaddingBottom();
429 |
430 | final boolean forceLeftGravity = false;
431 |
432 | for (int i = 2; i < count; i++) {
433 | final View child = getChildAt(i);
434 | if (child.getVisibility() != GONE) {
435 | final LayoutParams lp = (LayoutParams) child.getLayoutParams();
436 |
437 | final int width = child.getMeasuredWidth();
438 | final int height = child.getMeasuredHeight();
439 |
440 | int childLeft;
441 | int childTop;
442 |
443 | int gravity = lp.gravity;
444 | if (gravity == -1) {
445 | gravity = Gravity.TOP | Gravity.LEFT;
446 | }
447 |
448 | int layoutDirection = 1;
449 | if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) {
450 | layoutDirection = getLayoutDirection();
451 | }
452 |
453 | final int absoluteGravity = Gravity.getAbsoluteGravity(gravity, layoutDirection);
454 | final int verticalGravity = gravity & Gravity.VERTICAL_GRAVITY_MASK;
455 |
456 | switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
457 | case Gravity.CENTER_HORIZONTAL:
458 | childLeft = parentLeft + (parentRight - parentLeft - width) / 2 +
459 | lp.leftMargin - lp.rightMargin;
460 | break;
461 | case Gravity.RIGHT:
462 | if (!forceLeftGravity) {
463 | childLeft = parentRight - width - lp.rightMargin;
464 | break;
465 | }
466 | case Gravity.LEFT:
467 | default:
468 | childLeft = parentLeft + lp.leftMargin;
469 | }
470 |
471 | switch (verticalGravity) {
472 | case Gravity.TOP:
473 | childTop = parentTop + lp.topMargin;
474 | break;
475 | case Gravity.CENTER_VERTICAL:
476 | childTop = parentTop + (parentBottom - parentTop - height) / 2 +
477 | lp.topMargin - lp.bottomMargin;
478 | break;
479 | case Gravity.BOTTOM:
480 | childTop = parentBottom - height - lp.bottomMargin;
481 | break;
482 | default:
483 | childTop = parentTop + lp.topMargin;
484 | }
485 |
486 | child.layout(childLeft, childTop, childLeft + width, childTop + height);
487 | }
488 | }
489 | }
490 |
491 | View contentLayout;
492 | View emojiLayout;
493 |
494 | @Override
495 | public void addView(View child, int index, ViewGroup.LayoutParams params) {
496 | super.addView(child, index, params);
497 |
498 | int childCount = getChildCount();
499 | /*请按顺序布局*/
500 | if (childCount > 0) {
501 | contentLayout = getChildAt(0);
502 | }
503 | if (childCount > 1) {
504 | emojiLayout = getChildAt(1);
505 | }
506 |
507 | if (haveChildSoftInput(child)) {
508 | setEnableSoftInput(false);
509 | }
510 | }
511 |
512 |
513 | /**
514 | * 解决RSoftInputLayout2嵌套RSoftInputLayout2的问题
515 | */
516 | private boolean haveChildSoftInput(View child) {
517 | if (child instanceof ViewGroup) {
518 | for (int i = 0; i < ((ViewGroup) child).getChildCount(); i++) {
519 | return haveChildSoftInput(((ViewGroup) child).getChildAt(i));
520 | }
521 | }
522 | return child instanceof RSoftInputLayout2;
523 | }
524 |
525 | @Override
526 | protected void onAttachedToWindow() {
527 | super.onAttachedToWindow();
528 |
529 | initDefaultKeyboardHeight();
530 |
531 | if (!isInEditMode() && isEnabled() && enableSoftInput) {
532 | setFitsSystemWindows();
533 | //setClipToPadding(false);//未知作用
534 | }
535 |
536 | //必须放在post里面调用, 才会生效
537 | post(new Runnable() {
538 | @Override
539 | public void run() {
540 | adjustResize(getContext());
541 | }
542 | });
543 | }
544 |
545 | @Override
546 | protected boolean fitSystemWindows(Rect insets) {
547 | //此方法会触发 dispatchApplyWindowInsets
548 | insets.set(0, 0, 0, 0);
549 | super.fitSystemWindows(insets);
550 | return isEnableSoftInput();
551 | }
552 |
553 | @Override
554 | public WindowInsets onApplyWindowInsets(WindowInsets insets) {
555 |
556 | //Fragment+Fragment中使用此控件支持.
557 | if (!isEnableSoftInput()) {
558 | return super.onApplyWindowInsets(insets);
559 | }
560 |
561 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
562 | int insetBottom = insets.getSystemWindowInsetBottom();
563 |
564 | // L.i("onApplyWindowInsets:" + insetBottom + " " +
565 | // intentAction + " w:" + getMeasuredWidth() + " h:" + getMeasuredHeight());
566 |
567 | if (getMeasuredWidth() <= 0 && getMeasuredHeight() <= 0) {
568 | return super.onApplyWindowInsets(insets);
569 | }
570 |
571 | if (isSoftKeyboardShow() && insetBottom <= 0) {
572 | //软件已经显示, 此时却要隐藏键盘. ViewPager中, 使用此控件支持.
573 |
574 | //当启动一个新的Activity时, 也会触发此场景.
575 | post(new Runnable() {
576 | @Override
577 | public void run() {
578 | if (!isSoftKeyboardShow()) {
579 | insetBottom(0);
580 | }
581 | }
582 | });
583 | return super.onApplyWindowInsets(insets);
584 | }
585 |
586 | int action;
587 | if (insetBottom > 0) {
588 | action = INTENT_SHOW_KEYBOARD;
589 | } else {
590 | action = INTENT_HIDE_KEYBOARD;
591 | }
592 |
593 | if (insetRunnable != null) {
594 | if (action == wantIntentAction) {
595 | //之前已有相同操作
596 | return insets.replaceSystemWindowInsets(0, 0, 0, 0);
597 | }
598 | wantIntentAction = action;
599 | removeCallbacks(insetRunnable);
600 | }
601 |
602 | insetRunnable = new InsetRunnable(insetBottom);
603 |
604 | //键盘切换到键盘, 延迟检查. 防止是普通键盘切换到密码键盘
605 | if (lastIntentAction == INTENT_NONE || switchCheckDelay <= 0) {
606 | //第一次不检查
607 | insetRunnable.run();
608 | } else {
609 | postDelayed(insetRunnable, switchCheckDelay);
610 | }
611 |
612 | //替换掉系统的默认处理方式(setPadding)
613 | //系统会使用setPadding的方式, 为键盘留出空间
614 | return insets.replaceSystemWindowInsets(0, 0, 0, 0);
615 | }
616 | return super.onApplyWindowInsets(insets);
617 | }
618 |
619 | private Runnable insetRunnable;
620 |
621 | //底部需要腾出距离
622 | private void insetBottom(int height) {
623 | // L.i("插入:" + height + ":" + getMeasuredHeight() +
624 | // " isFirstLayout:" + isFirstLayout(getMeasuredWidth(), getMeasuredHeight()));
625 | int insetBottom = height;
626 | int measuredWidth = getMeasuredWidth();
627 | int measuredHeight = getMeasuredHeight();
628 | if (insetBottom > 0) {
629 | //键盘弹出
630 | checkSizeChanged = new KeyboardRunnable(measuredWidth, measuredHeight - insetBottom,
631 | measuredWidth, measuredHeight);
632 | } else {
633 | //键盘隐藏
634 | int hideHeight = bottomCurrentShowHeight;
635 | if (bottomCurrentShowHeight <= 0) {
636 | hideHeight = lastKeyboardHeight;
637 | }
638 | checkSizeChanged = new KeyboardRunnable(measuredWidth, measuredHeight,
639 | measuredWidth, measuredHeight - hideHeight);
640 | }
641 | checkOnSizeChanged(false);
642 | }
643 |
644 | private Runnable checkSizeChanged;
645 |
646 | private void checkOnSizeChanged(boolean delay) {
647 | if (checkSizeChanged == null) {
648 | return;
649 | }
650 | removeCallbacks(checkSizeChanged);
651 | if (delay) {
652 | post(checkSizeChanged);
653 | } else {
654 | checkSizeChanged.run();
655 | }
656 | }
657 |
658 | /**
659 | * 判断键盘是否显示
660 | */
661 | public boolean isSoftKeyboardShow() {
662 | if (isInEditMode()) {
663 | return false;
664 | }
665 | int screenHeight = getScreenHeightPixels();
666 | int keyboardHeight = getSoftKeyboardHeight();
667 | return screenHeight != keyboardHeight && keyboardHeight > 50 * getContext().getResources().getDisplayMetrics().density;
668 | }
669 |
670 | /**
671 | * 获取键盘的高度
672 | */
673 | public int getSoftKeyboardHeight() {
674 | return getSoftKeyboardHeight(this);
675 | }
676 |
677 | /**
678 | * 屏幕高度(不包含虚拟导航键盘的高度)
679 | */
680 | private int getScreenHeightPixels() {
681 | return getResources().getDisplayMetrics().heightPixels;
682 | }
683 |
684 | private ValueAnimator mValueAnimator;
685 |
686 | private void startAnim(int bottomHeightFrom, int bottomHeightTo, long duration) {
687 | // L.i("动画:from:" + bottomHeightFrom + "->" + bottomHeightTo);
688 | cancelAnim();
689 |
690 | int from = bottomHeightFrom;
691 | int to = bottomHeightTo;
692 | if (animatorCallback != null) {
693 | int[] preStart = animatorCallback.onAnimatorPreStart(wantIntentAction, bottomHeightFrom, bottomHeightTo, duration);
694 | from = preStart[0];
695 | to = preStart[1];
696 | duration = preStart[2];
697 | }
698 |
699 | mValueAnimator = ObjectAnimator.ofInt(from, to);
700 | mValueAnimator.setDuration(duration);
701 | if (animatorCallback == null) {
702 | mValueAnimator.setInterpolator(new DecelerateInterpolator());
703 | } else {
704 | mValueAnimator.setInterpolator(animatorCallback.getInterpolator(wantIntentAction));
705 | }
706 | mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
707 | @Override
708 | public void onAnimationUpdate(ValueAnimator animation) {
709 | float animatedFraction = animation.getAnimatedFraction();
710 | int animatedValue = (int) animation.getAnimatedValue();
711 | animProgress = animatedFraction;
712 | if (animatorCallback == null) {
713 | bottomCurrentShowHeightAnim = animatedValue;
714 | } else {
715 | bottomCurrentShowHeightAnim = animatorCallback.onUpdateAnimatorValue(intentAction, animatedFraction, animatedValue);
716 | }
717 | requestLayout();
718 | }
719 | });
720 | mValueAnimator.addListener(new Animator.AnimatorListener() {
721 | @Override
722 | public void onAnimationStart(Animator animation) {
723 |
724 | }
725 |
726 | @Override
727 | public void onAnimationEnd(Animator animation) {
728 | clearIntentAction();
729 | if (animatorCallback != null) {
730 | animatorCallback.onAnimatorEnd(lastIntentAction, false);
731 | }
732 | }
733 |
734 | @Override
735 | public void onAnimationCancel(Animator animation) {
736 | //clearIntentAction();
737 | if (animatorCallback != null) {
738 | animatorCallback.onAnimatorEnd(wantIntentAction, true);
739 | }
740 | }
741 |
742 | @Override
743 | public void onAnimationRepeat(Animator animation) {
744 |
745 | }
746 | });
747 | mValueAnimator.start();
748 |
749 | if (animatorCallback != null) {
750 | animatorCallback.onAnimatorStart(wantIntentAction);
751 | }
752 | }
753 |
754 | private void cancelAnim() {
755 | if (mValueAnimator != null) {
756 | mValueAnimator.cancel();
757 | mValueAnimator = null;
758 | }
759 | }
760 |
761 | //动画是否执行中
762 | private boolean isAnimStart() {
763 | return mValueAnimator != null && mValueAnimator.isRunning();
764 | }
765 |
766 | //表情布局有效的高度
767 | private int validBottomHeight() {
768 | //没显示过键盘, 默认高度
769 | int bottomHeight = defaultKeyboardHeight;
770 |
771 | if (lastKeyboardHeight > 0) {
772 | //显示过键盘, 有键盘的高度
773 | bottomHeight = lastKeyboardHeight;
774 | }
775 |
776 | return bottomHeight;
777 | }
778 |
779 | private int calcAnimPaddingTop() {
780 | if (animPaddingTop <= 0) {
781 | return 0;
782 | }
783 |
784 | if (isInEditMode()) {
785 | return animPaddingTop;
786 | }
787 |
788 | int result = animPaddingTop;
789 | boolean animStart = isAnimStart();
790 | int statusBarHeight = getStatusBarHeight(getContext());
791 |
792 | boolean layoutFullScreen = isLayoutFullScreen(getContext());
793 | if (isSoftKeyboardShow() || isEmojiLayoutShow()) {
794 | if (animStart && intentAction != lastIntentAction) {
795 | result = (int) (animPaddingTop * (1 - animProgress));
796 | result = Math.max(result, statusBarHeight + animPaddingMinTop);
797 | } else if (lastIntentAction == INTENT_NONE ||
798 | lastIntentAction == INTENT_HIDE_EMOJI ||
799 | lastIntentAction == INTENT_HIDE_KEYBOARD) {
800 |
801 | } else if (layoutFullScreen) {
802 | result = statusBarHeight + animPaddingMinTop;
803 | } else {
804 | result = animPaddingMinTop;
805 | }
806 | } else {
807 | if (wantIntentAction == INTENT_HIDE_EMOJI ||
808 | wantIntentAction == INTENT_HIDE_KEYBOARD) {
809 |
810 | if (animStart && wantIntentAction != lastIntentAction) {
811 | result = (int) (animPaddingTop * animProgress);
812 | result = Math.max(result, statusBarHeight + animPaddingMinTop);
813 | } else if (layoutFullScreen) {
814 | result = statusBarHeight + animPaddingMinTop;
815 | } else {
816 | result = animPaddingMinTop;
817 | }
818 | }
819 | }
820 | return result;
821 | }
822 |
823 | //
824 |
825 | //
826 |
827 | public void setEnableSoftInput(boolean enableSoftInput) {
828 | if (this.enableSoftInput == enableSoftInput) {
829 | return;
830 | }
831 | boolean keyboardShow = isSoftKeyboardShow();
832 |
833 | this.enableSoftInput = enableSoftInput;
834 | if (enableSoftInput) {
835 | setEnabled(true);
836 | setFitsSystemWindows(true);
837 | } else {
838 | setFitsSystemWindows(false);
839 | }
840 |
841 | if (keyboardShow && !enableSoftInput) {
842 | //已经显示了软键盘, 这个时候禁用控件, 恢复默认布局
843 | setIntentAction(INTENT_HIDE_KEYBOARD);
844 | insetBottom(0);
845 | } else {
846 | requestLayout();
847 | }
848 | }
849 |
850 | public void setFitsSystemWindows() {
851 | setFitsSystemWindows(isEnabled() && enableSoftInput);
852 | }
853 |
854 | public boolean isEnableSoftInput() {
855 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
856 | return getFitsSystemWindows() && isEnabled() && enableSoftInput;
857 | } else {
858 | return isEnabled() && enableSoftInput;
859 | }
860 | }
861 |
862 | //
863 |
864 | //
865 |
866 | public boolean isEnableSoftInputAnim() {
867 | return enableSoftInputAnimHide || enableSoftInputAnimShow;
868 | }
869 |
870 | public boolean isEmojiLayoutShow() {
871 | boolean result = false;
872 |
873 | if (isSoftKeyboardShow()) {
874 | return false;
875 | }
876 |
877 | if (emojiLayout != null) {
878 | if (isAnimStart()) {
879 | result = bottomCurrentShowHeight > 0;
880 | } else if (emojiLayout.getMeasuredHeight() > 0
881 | && emojiLayout.getTop() < getMeasuredHeight() - getPaddingBottom()
882 | && emojiLayout.getBottom() >= getMeasuredHeight() - getPaddingBottom()
883 | ) {
884 | result = true;
885 | }
886 | }
887 | return result;
888 | }
889 |
890 | /**
891 | * 返回按键处理
892 | *
893 | * @return true 表示可以关闭界面
894 | */
895 | public boolean requestBackPressed() {
896 | if (isSoftKeyboardShow()) {
897 | if (intentAction == INTENT_HIDE_KEYBOARD) {
898 | return false;
899 | }
900 | setIntentAction(INTENT_HIDE_KEYBOARD);
901 | hideSoftInput(this);
902 | return false;
903 | }
904 |
905 | if (isEmojiLayoutShow()) {
906 | hideEmojiLayout();
907 | return false;
908 | }
909 |
910 | return true;
911 | }
912 |
913 | /**
914 | * 显示表情布局
915 | */
916 | public void showEmojiLayout() {
917 | showEmojiLayout(validBottomHeight(), false);
918 | }
919 |
920 | public void showEmojiLayout(int height) {
921 | showEmojiLayout(height, true);
922 | }
923 |
924 | public void showEmojiLayout(int height, boolean force) {
925 | if (force) {
926 | lastKeyboardHeight = height;
927 | } else {
928 | if (isEmojiLayoutShow()) {
929 | return;
930 | }
931 |
932 | if (intentAction == INTENT_SHOW_EMOJI) {
933 | return;
934 | }
935 | }
936 |
937 | if (isSoftKeyboardShow()) {
938 | hideSoftInput(this);
939 | }
940 |
941 | setIntentAction(INTENT_SHOW_EMOJI);
942 | insetBottom(height);
943 | }
944 |
945 | /**
946 | * 隐藏表情布局
947 | */
948 | public void hideEmojiLayout() {
949 | if (intentAction == INTENT_HIDE_EMOJI) {
950 | return;
951 | }
952 |
953 | if (isEmojiLayoutShow()) {
954 | setIntentAction(INTENT_HIDE_EMOJI);
955 | insetBottom(0);
956 | }
957 | }
958 |
959 | public void setEnableSoftInputAnim(boolean enableSoftInputAnim) {
960 | this.enableSoftInputAnim = enableSoftInputAnim;
961 |
962 | enableSoftInputAnimHide = enableSoftInputAnim;
963 | enableSoftInputAnimShow = enableSoftInputAnim;
964 | }
965 |
966 | public void setEnableSoftInputAnimShow(boolean enableSoftInputAnimShow) {
967 | this.enableSoftInputAnimShow = enableSoftInputAnimShow;
968 | }
969 |
970 | public void setEnableSoftInputAnimHide(boolean enableSoftInputAnimHide) {
971 | this.enableSoftInputAnimHide = enableSoftInputAnimHide;
972 | }
973 |
974 | public void setSwitchCheckDelay(int switchCheckDelay) {
975 | this.switchCheckDelay = switchCheckDelay;
976 | }
977 |
978 | public void setAnimPaddingTop(int animPaddingTop) {
979 | this.animPaddingTop = animPaddingTop;
980 | requestLayout();
981 | }
982 |
983 | public void setAnimPaddingMinTop(int animPaddingMinTop) {
984 | this.animPaddingMinTop = animPaddingMinTop;
985 | }
986 |
987 | public int getBottomCurrentShowHeight() {
988 | return bottomCurrentShowHeight;
989 | }
990 |
991 | public int getBottomCurrentShowHeightAnim() {
992 | return bottomCurrentShowHeightAnim;
993 | }
994 |
995 | public long getAnimDuration() {
996 | return animDuration;
997 | }
998 |
999 | //
1000 |
1001 | //
1002 |
1003 | HashSet mEmojiLayoutChangeListeners = new HashSet<>();
1004 |
1005 | public void addOnEmojiLayoutChangeListener(OnEmojiLayoutChangeListener listener) {
1006 | mEmojiLayoutChangeListeners.add(listener);
1007 | adjustResize(getContext());
1008 | }
1009 |
1010 | public void removeOnEmojiLayoutChangeListener(OnEmojiLayoutChangeListener listener) {
1011 | mEmojiLayoutChangeListeners.remove(listener);
1012 | }
1013 |
1014 | private void notifyEmojiLayoutChangeListener(boolean isEmojiShow, boolean isKeyboardShow, int height) {
1015 | //L.w(hashCode() + " 表情:" + isEmojiShow + " 键盘:" + isKeyboardShow + " 高度:" + height);
1016 |
1017 | if (isKeyboardShow && !isInEditMode()) {
1018 | //Hawk.put(KEY_KEYBOARD_HEIGHT, height);
1019 | }
1020 |
1021 | Iterator iterator = mEmojiLayoutChangeListeners.iterator();
1022 | while (iterator.hasNext()) {
1023 | iterator.next().onEmojiLayoutChange(isEmojiShow, isKeyboardShow, height);
1024 | }
1025 | }
1026 |
1027 | public interface OnEmojiLayoutChangeListener {
1028 | /**
1029 | * @param height EmojiLayout弹出的高度 或者 键盘弹出的高度
1030 | * @param isEmojiShow 表情布局是否显示了
1031 | * @param isKeyboardShow 键盘是否显示了
1032 | */
1033 | void onEmojiLayoutChange(boolean isEmojiShow, boolean isKeyboardShow, int height);
1034 | }
1035 |
1036 |
1037 | /**
1038 | * 动画执行回调, 可以修改动画执行的值
1039 | */
1040 | public AnimatorCallback animatorCallback;
1041 |
1042 | public static class AnimatorCallback {
1043 |
1044 | /**
1045 | * 动画需要执行的值
1046 | *
1047 | * @return 按照入参顺序, 返回对应修改后的值
1048 | */
1049 | public int[] onAnimatorPreStart(int intentAction, int bottomHeightFrom, int bottomHeightTo, long duration) {
1050 | return new int[]{bottomHeightFrom, bottomHeightTo, (int) duration};
1051 | }
1052 |
1053 | /**
1054 | * 动画执行过程中的值
1055 | */
1056 | public int onUpdateAnimatorValue(int intentAction, float animatedFraction, int animatedValue) {
1057 | return animatedValue;
1058 | }
1059 |
1060 | public TimeInterpolator getInterpolator(int intentAction) {
1061 | return new DecelerateInterpolator();
1062 | }
1063 |
1064 | public void onAnimatorStart(int intentAction) {
1065 |
1066 | }
1067 |
1068 | public void onAnimatorEnd(int intentAction, boolean isCancel) {
1069 |
1070 | }
1071 | }
1072 |
1073 | //
1074 |
1075 | //
1076 |
1077 | /**
1078 | * 状态栏高度
1079 | */
1080 | public static int getStatusBarHeight(Context context) {
1081 | int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
1082 | if (resourceId > 0) {
1083 | return context.getResources().getDimensionPixelSize(resourceId);
1084 | }
1085 | return 0;
1086 | }
1087 |
1088 | public static void hideSoftInput(@NonNull View view) {
1089 | InputMethodManager manager = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
1090 | manager.hideSoftInputFromWindow(view.getWindowToken(), 0);
1091 | }
1092 |
1093 | public static void showSoftInput(@NonNull View view) {
1094 | view.requestFocus();
1095 | InputMethodManager manager = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
1096 | manager.showSoftInput(view, 0);
1097 | }
1098 |
1099 | public static boolean isLayoutFullScreen(@Nullable Context context) {
1100 | if (context == null) {
1101 | return false;
1102 | }
1103 | if (context instanceof Activity) {
1104 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
1105 | Window window = ((Activity) context).getWindow();
1106 | int systemUiVisibility = window.getDecorView().getSystemUiVisibility();
1107 | return (systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) == View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
1108 | } else {
1109 | return false;
1110 | }
1111 | } else {
1112 | return false;
1113 | }
1114 | }
1115 |
1116 | public static int getSoftKeyboardHeight(@NonNull View view) {
1117 | Context context = view.getContext();
1118 | int screenHeight = 0;
1119 | boolean isLollipop = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
1120 | if (context instanceof Activity && isLayoutFullScreen(context)) {
1121 | Window window = ((Activity) context).getWindow();
1122 | view = window.getDecorView();
1123 | screenHeight = window.findViewById(Window.ID_ANDROID_CONTENT).getMeasuredHeight();
1124 | } else {
1125 | screenHeight = view.getResources().getDisplayMetrics().heightPixels;
1126 | if (isLollipop) {
1127 | screenHeight += getStatusBarHeight(context);
1128 | }
1129 | }
1130 |
1131 | Rect rect = new Rect();
1132 | view.getWindowVisibleDisplayFrame(rect);
1133 | int visibleBottom = rect.bottom;
1134 | return screenHeight - visibleBottom;
1135 | }
1136 |
1137 | public static void adjustResize(Context context) {
1138 | //resize 必备条件
1139 | if (context instanceof Activity) {
1140 | Window window = ((Activity) context).getWindow();
1141 | int softInputMode = window.getAttributes().softInputMode;
1142 | if ((softInputMode & WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE)
1143 | != WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE) {
1144 | window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
1145 | }
1146 | }
1147 | }
1148 |
1149 | //
1150 |
1151 | private class KeyboardRunnable implements Runnable {
1152 | int w;
1153 | int h;
1154 | int oldw;
1155 | int oldh;
1156 |
1157 | private KeyboardRunnable(int w, int h, int oldw, int oldh) {
1158 | this.w = w;
1159 | this.h = h;
1160 | this.oldw = oldw;
1161 | this.oldh = oldh;
1162 | }
1163 |
1164 | @Override
1165 | public void run() {
1166 | onSizeChanged(w, h, oldw, oldh);
1167 | checkSizeChanged = null;
1168 | }
1169 | }
1170 |
1171 | private class DelaySizeChangeRunnable implements Runnable {
1172 | int w;
1173 | int h;
1174 | int oldw;
1175 | int oldh;
1176 | int delayIntentAction;
1177 |
1178 | private DelaySizeChangeRunnable(int w, int h, int oldw, int oldh, int action) {
1179 | this.w = w;
1180 | this.h = h;
1181 | this.oldw = oldw;
1182 | this.oldh = oldh;
1183 | this.delayIntentAction = action;
1184 | }
1185 |
1186 | @Override
1187 | public void run() {
1188 | int oldBottomCurrentShowHeight = bottomCurrentShowHeight;
1189 |
1190 | //L.i("size:" + oldh + "->" + h + " " + oldBottomCurrentShowHeight);
1191 |
1192 | bottomCurrentShowHeight = 0;
1193 | boolean needAnim = isEnableSoftInputAnim();
1194 | if (handleSizeChange(w, h, oldw, oldh)) {
1195 | //有可能是键盘弹出了
1196 | int diffHeight = oldh - h;
1197 |
1198 | boolean softKeyboardShow = isSoftKeyboardShow();
1199 | boolean emojiLayoutShow = false;
1200 |
1201 | if (softKeyboardShow) {
1202 | lastRestoreIntentAction2 = lastRestoreIntentAction;
1203 | } else {
1204 | lastRestoreIntentAction = intentAction;
1205 | }
1206 |
1207 | boolean layoutFullScreen = isLayoutFullScreen(getContext());
1208 |
1209 | //低版本, 普通输入框和密码输入框切换适配
1210 | if (!layoutFullScreen) {
1211 | if (softKeyboardShow) {
1212 | diffHeight = getSoftKeyboardHeight();
1213 | }
1214 | }
1215 |
1216 | if (diffHeight > 0) {
1217 | //当用代码调整了布局的height属性, 也会回调此方法.
1218 |
1219 | if (enableSoftInputInset) {
1220 | bottomCurrentShowHeight = diffHeight;
1221 | }
1222 |
1223 | if (softKeyboardShow) {
1224 | lastKeyboardHeight = diffHeight;
1225 | emojiLayoutShow = false;
1226 | } else {
1227 | emojiLayoutShow = intentAction == INTENT_SHOW_EMOJI;
1228 | //有可能是表情布局显示
1229 | }
1230 |
1231 | //键盘显示
1232 | if (!enableSoftInputAnimShow) {
1233 | needAnim = false;
1234 | }
1235 |
1236 | notifyEmojiLayoutChangeListener(emojiLayoutShow, softKeyboardShow, diffHeight);
1237 | if (needAnim && enableSoftInputInset) {
1238 | if (isAnimStart()) {
1239 | startAnim(Math.abs(bottomCurrentShowHeightAnim), diffHeight, animDuration);
1240 | } else {
1241 | startAnim(oldBottomCurrentShowHeight, diffHeight, animDuration);
1242 | }
1243 | }
1244 | } else {
1245 | if (lastRestoreIntentAction2 == INTENT_SHOW_EMOJI && enableEmojiRestore) {
1246 | emojiLayoutShow = true;
1247 | diffHeight = -diffHeight;
1248 |
1249 | bottomCurrentShowHeight = diffHeight;
1250 | lastRestoreIntentAction2 = INTENT_NONE;
1251 | }
1252 |
1253 | notifyEmojiLayoutChangeListener(emojiLayoutShow, false, diffHeight);
1254 |
1255 | if (isFirstLayout(oldw, oldh)) {
1256 | needAnim = false;
1257 | }
1258 |
1259 | //键盘显示或者表情显示
1260 | if (!enableSoftInputAnimHide) {
1261 | needAnim = false;
1262 | }
1263 |
1264 | if (needAnim && !emojiLayoutShow) {
1265 | if (isAnimStart()) {
1266 | startAnim(Math.abs(bottomCurrentShowHeightAnim), 0, animDuration);
1267 | } else {
1268 | startAnim(Math.abs(diffHeight), 0, animDuration);
1269 | }
1270 | }
1271 | }
1272 |
1273 | //低版本适配
1274 | if (!layoutFullScreen) {
1275 | setIntentAction(delayIntentAction);
1276 | }
1277 |
1278 | requestLayout();
1279 | }
1280 |
1281 | if (!needAnim) {
1282 | clearIntentAction();
1283 | }
1284 | delaySizeChanged = null;
1285 | }
1286 | }
1287 |
1288 | private class InsetRunnable implements Runnable {
1289 |
1290 | int insetBottom;
1291 |
1292 | private InsetRunnable(int insetBottom) {
1293 | this.insetBottom = insetBottom;
1294 | }
1295 |
1296 | @Override
1297 | public void run() {
1298 | if (intentAction <= INTENT_HIDE_KEYBOARD) {
1299 | if (insetBottom > 0) {
1300 | setIntentAction(INTENT_SHOW_KEYBOARD);
1301 | } else {
1302 | setIntentAction(INTENT_HIDE_KEYBOARD);
1303 | }
1304 | cancelAnim();
1305 | insetBottom(insetBottom);
1306 | }
1307 |
1308 | insetRunnable = null;
1309 | }
1310 | }
1311 | }
1312 |
--------------------------------------------------------------------------------