序 、项目有一版本是在优化了直播的聊天功能 ,需要自定义表情面板 。emmmm 。
效果图
功能点 :
点击左边的笑脸会弹出表情面板 ,点击输入框会切换到键盘 。
直接上代码
package com.developers.superdemo01.smooth; import android.annotation.TargetApi; import android.content.Context; import android.content.SharedPreferences; import android.content.res.TypedArray; import android.util.AttributeSet; import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.view.inputmethod.InputMethodManager; import android.widget.LinearLayout; import com.developers.superdemo01.R; /** * @Author yinzh * @Date 2020/7/2 13:43 * @Description 表情输入面板 */ public class SmoothInputLayout extends LinearLayout { public static final int DEFAULT_KEYBOARD_HEIGHT = 387; public static final int MIN_KEYBOARD_HEIGHT = 20; private static final String SP_KEYBOARD = "keyboard"; private static final String KEY_HEIGHT = "height"; private int mMaxKeyboardHeight = Integer.MIN_VALUE; private int mDefaultKeyboardHeight = 387; private int mMinKeyboardHeight; private int mKeyboardHeight; private int mInputViewId; private View mInputView; private boolean mKeyboardOpen = false; private boolean mKeyboardOpenOne = false; private int mInputPaneId; private View mInputPane; private OnVisibilityChangeListener mListener; private OnKeyboardChangeListener keyboardChangeListener; private boolean mAutoSaveKeyboardHeight; private KeyboardProcessor mKeyboardProcessor; private boolean tShowInputPane = false; public SmoothInputLayout(Context context) { super(context); initView(null); } public SmoothInputLayout(Context context, AttributeSet attrs) { super(context, attrs); initView(attrs); } @TargetApi(11) public SmoothInputLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initView(attrs); } @TargetApi(21) public SmoothInputLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); initView(attrs); } private void initView(AttributeSet attrs) { int defaultInputHeight = (int) (DEFAULT_KEYBOARD_HEIGHT * getResources().getDisplayMetrics().density); int minInputHeight = (int) (MIN_KEYBOARD_HEIGHT * getResources().getDisplayMetrics().density); mInputViewId = NO_ID; mInputPaneId = NO_ID; boolean autoSave; TypedArray custom = getContext().obtainStyledAttributes(attrs, R.styleable.SmoothInputLayout); defaultInputHeight = custom.getDimensionPixelOffset( R.styleable.SmoothInputLayout_silDefaultKeyboardHeight, defaultInputHeight); minInputHeight = custom.getDimensionPixelOffset( R.styleable.SmoothInputLayout_silMinKeyboardHeight, minInputHeight); mInputViewId = custom.getResourceId(R.styleable.SmoothInputLayout_silInputView, mInputViewId); mInputPaneId = custom.getResourceId(R.styleable.SmoothInputLayout_silInputPane, mInputPaneId); autoSave = custom.getBoolean(R.styleable.SmoothInputLayout_silAutoSaveKeyboardHeight, true); custom.recycle(); setDefaultKeyboardHeight(defaultInputHeight); setMinKeyboardHeight(minInputHeight); setAutoSaveKeyboardHeight(autoSave); } @Override protected void onFinishInflate() { super.onFinishInflate(); if (mInputViewId != NO_ID) { setInputView(findViewById(mInputViewId)); } if (mInputPaneId != NO_ID) { setInputPane(findViewById(mInputPaneId)); } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { final int heightSize = MeasureSpec.getSize(heightMeasureSpec); if(mMaxKeyboardHeight > 3000){ // 此处代码是为了限制横竖屏切换的时候值过高问题 。 mMaxKeyboardHeight = heightSize; } if (heightSize > mMaxKeyboardHeight) { mMaxKeyboardHeight = heightSize; } final int heightChange = mMaxKeyboardHeight - heightSize; Log.i("SSSSSSSSSSSS", heightSize + "= heightSize=" + mMaxKeyboardHeight + "= mMaxKeyboardHeight = " + heightChange + "=heightChange = " + mMinKeyboardHeight + "=mMinKeyboardHeight"); if (heightChange > mMinKeyboardHeight) { if (mKeyboardHeight != heightChange) { mKeyboardHeight = heightChange; saveKeyboardHeight(); } mKeyboardOpen = true; // 输入法弹出,隐藏功能面板 if (mInputPane != null && mInputPane.getVisibility() == VISIBLE) { mInputPane.setVisibility(GONE); if (mListener != null) mListener.onVisibilityChange(GONE); } } else { mKeyboardOpen = false; if (tShowInputPane) { tShowInputPane = false; if (mInputPane != null && mInputPane.getVisibility() == GONE) { updateLayout(); mInputPane.setVisibility(VISIBLE); if (mListener != null) mListener.onVisibilityChange(VISIBLE); forceLayout(); } } } Log.i("SSSSSSSSSSSS", mKeyboardOpen + "========="); super.onMeasure(widthMeasureSpec, heightMeasureSpec); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); if (keyboardChangeListener != null) keyboardChangeListener.onKeyboardChanged(mKeyboardOpen); } /** * 获取键盘SP * * @return 键盘SP */ private SharedPreferences getKeyboardSharedPreferences() { return getContext().getSharedPreferences(SP_KEYBOARD, Context.MODE_PRIVATE); } /** * 存储键盘高度 */ private void saveKeyboardHeight() { if (mAutoSaveKeyboardHeight) getKeyboardSharedPreferences().edit().putInt(KEY_HEIGHT, mKeyboardHeight).commit(); else { if (mKeyboardProcessor != null) mKeyboardProcessor.onSaveKeyboardHeight(mKeyboardHeight); } } /** * 更新子项高度 */ private void updateLayout() { if (mInputPane == null) return; if (mKeyboardHeight == 0) mKeyboardHeight = getKeyboardHeight(mDefaultKeyboardHeight); ViewGroup.LayoutParams layoutParams = mInputPane.getLayoutParams(); if (layoutParams != null) { layoutParams.height = mKeyboardHeight; mInputPane.setLayoutParams(layoutParams); } } private int getKeyboardHeight(int defaultHeight) { if (mAutoSaveKeyboardHeight) return getKeyboardSharedPreferences().getInt(KEY_HEIGHT, defaultHeight); else return mKeyboardProcessor != null ? mKeyboardProcessor.getSavedKeyboardHeight(defaultHeight) : defaultHeight; } /** * 设置默认系统输入面板高度 * * @param height 输入面板高度 */ public void setDefaultKeyboardHeight(int height) { if (mDefaultKeyboardHeight != height) mDefaultKeyboardHeight = height; } /** * 设置最小系统输入面板高度 * * @param height 输入面板高度 */ public void setMinKeyboardHeight(int height) { if (mMinKeyboardHeight != height) mMinKeyboardHeight = height; } /** * 设置输入框 * * @param edit 输入框 */ public void setInputView(View edit) { if (mInputView != edit) mInputView = edit; } /** * 设置特殊输入面板 * * @param pane 面板 */ public void setInputPane(View pane) { if (mInputPane != pane) mInputPane = pane; } /** * 设置面板可见改变监听 * * @param listener 面板可见改变监听 */ public void setOnVisibilityChangeListener(OnVisibilityChangeListener listener) { mListener = listener; } /** * 设置键盘改变监听 * * @param listener 键盘改变监听 */ public void setOnKeyboardChangeListener(OnKeyboardChangeListener listener) { keyboardChangeListener = listener; } /** * 设置自动保存键盘高度 * * @param auto 是否自动 */ public void setAutoSaveKeyboardHeight(boolean auto) { mAutoSaveKeyboardHeight = auto; } /** * 设置键盘处理器 * 仅在关闭自动保存键盘高度时设置的处理器才有效{@link #setAutoSaveKeyboardHeight(boolean)} * * @param processor 处理器 */ public void setKeyboardProcessor(KeyboardProcessor processor) { mKeyboardProcessor = processor; } /** * 是否输入法已打开 * * @return 是否输入法已打开 */ public boolean isKeyBoardOpen() { return mKeyboardOpen; } public boolean isKeyboardOpenOne() { return mKeyboardOpenOne; } public void setmKeyboardOpenOne(boolean mKeyboardOpenOne) { this.mKeyboardOpenOne = mKeyboardOpenOne; } public void setKeyboardOpen(boolean mKeyboardOpen) { this.mKeyboardOpen = mKeyboardOpen; } /** * 是否特殊输入面板已打开 * * @return 特殊输入面板已打开 */ public boolean isInputPaneOpen() { return mInputPane != null && mInputPane.getVisibility() == VISIBLE; } /** * 关闭特殊输入面板 */ public void closeInputPane() { if (isInputPaneOpen()) { mInputPane.setVisibility(GONE); if (mListener != null) mListener.onVisibilityChange(GONE); } } /** * 显示特殊输入面板 * * @param focus 是否让输入框拥有焦点 */ public void showInputPane(boolean focus) { if (isKeyBoardOpen()) { tShowInputPane = true; InputMethodManager imm = ((InputMethodManager) (getContext() .getSystemService(Context.INPUT_METHOD_SERVICE))); if (imm != null) { imm.hideSoftInputFromWindow(getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); } } else { if (mInputPane != null && mInputPane.getVisibility() == GONE) { updateLayout(); mInputPane.setVisibility(VISIBLE); if (mListener != null) mListener.onVisibilityChange(VISIBLE); } } if (focus) { if (mInputView != null) { mInputView.requestFocus(); mInputView.requestFocusFromTouch(); } } else { if (mInputView != null) { setFocusable(true); setFocusableInTouchMode(true); mInputView.clearFocus(); } } } /** * 关闭键盘 * * @param clearFocus 是否清除输入框焦点 */ public void closeKeyboard(boolean clearFocus) { InputMethodManager imm = ((InputMethodManager) (getContext() .getSystemService(Context.INPUT_METHOD_SERVICE))); if (imm != null) { imm.hideSoftInputFromWindow(getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); } if (clearFocus && mInputView != null) { setFocusable(true); setFocusableInTouchMode(true); mInputView.clearFocus(); } } /** * 打开键盘 */ public void showKeyboard() { if (mInputView == null) { return; } mInputView.requestFocus(); mInputView.requestFocusFromTouch(); InputMethodManager imm = ((InputMethodManager) (getContext() .getSystemService(Context.INPUT_METHOD_SERVICE))); if (imm != null) { imm.showSoftInput(mInputView, InputMethodManager.SHOW_IMPLICIT); } } /** * 面板可见改变监听 */ public interface OnVisibilityChangeListener { void onVisibilityChange(int visibility); } /** * 键盘改变监听 */ public interface OnKeyboardChangeListener { void onKeyboardChanged(boolean open); } /** * 键盘处理器 */ public interface KeyboardProcessor { /** * 存储键盘高度 * * @param height 高度 */ void onSaveKeyboardHeight(int height); /** * 获取存储的键盘高度 * * @param defaultHeight 默认高度 * @return 键盘高度 */ int getSavedKeyboardHeight(int defaultHeight); } }
注意事项:
需要在配置清单设置
android:configChanges="keyboardHidden|orientation|screenSize" android:windowSoftInputMode="adjustResize" >
github地址 :
https://github.com/spuermax/SuperDemo01