Android 輸入法鍵盤和自定義表情面板

序 、項目有一版本是在優化了直播的聊天功能 ,需要自定義表情面板 。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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章