The keyboard with the function of facial expression input and photo upload

Keywords: Android Attribute github xml

Because of the company's business requirements, we need to make a page similar to Wechat Chat. The most important thing is to input facial expressions, take photos and upload pictures. So we imitate God.( https://github.com/dss886/Android-EmotionInputDetector ) I wrote an Emotion Keyboard. Don't talk too much nonsense. First, I'll show you the results.~

github address: https://github.com/KaneShaw/EmotionKeyboard

Design sketch


Core class

Put out the core code first, basically there are comments on the code, can not see the private, the code is not perfect enough, what suggestions can be commented below, thank you.~

public class EmotionKeyboard {
    private static final String SHARE_PREFERENCE_NAME = "com.xk2318.EmotionKeyboard";
    private static final String SHARE_PREFERENCE_TAG = "soft_input_height";

    private Activity mActivity;
    private InputMethodManager mInputManager;
    private SharedPreferences sp;
    private View mEmotionLayout;//Expression layout
    private View mExtendLayout;//Extended layout (uploading pictures, photographing, location, red envelope, etc.)
    private EditText mEditText;
    private View mContentView;

    private EmotionKeyboard() {}

    public static EmotionKeyboard with(Activity activity) {
        EmotionKeyboard EmotionKeyboard = new EmotionKeyboard();
        EmotionKeyboard.mActivity = activity;
        EmotionKeyboard.mInputManager = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
        EmotionKeyboard.sp = activity.getSharedPreferences(SHARE_PREFERENCE_NAME, Context.MODE_PRIVATE);
        return EmotionKeyboard;
    }

    public EmotionKeyboard bindToContent(View contentView) {
        mContentView = contentView;
        return this;
    }

    /* Binding input box */
    public EmotionKeyboard bindToEditText(EditText editText) {
        mEditText = editText;
        mEditText.requestFocus();
        mEditText.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if (event.getAction() == MotionEvent.ACTION_UP) {
                    /*
                     * If the expression layout is visible, lock the content layout height, hide the expression layout, display the soft keyboard, and unlock the content layout height.
                     * If the extended layout is visible, lock the content layout height, hide the extended layout, display the soft keyboard, and unlock the content layout height.
                     * If neither the expression layout nor the extended layout is visible, do nothing
                     */
                    if(mEmotionLayout.isShown()){
                        lockContentHeight();
                        hideLayout(mEmotionLayout, true);
                        mEditText.postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                unlockContentHeightDelayed();
                            }
                        }, 200L);
                    } else if(mExtendLayout.isShown()){
                        lockContentHeight();
                        hideLayout(mExtendLayout, true);
                        mEditText.postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                unlockContentHeightDelayed();
                            }
                        }, 200L);
                    }
                }
                return false;
            }
        });
        return this;
    }

    /* Binding expression button */
    public EmotionKeyboard bindToEmotionButton(View emotionButton) {
        emotionButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mEmotionLayout.isShown()) {
                    lockContentHeight();
                    hideLayout(mEmotionLayout, true);
                    unlockContentHeightDelayed();
                } else {
                    if (isSoftInputShown()) {
                        lockContentHeight();
                        showLayout(mEmotionLayout);
                        unlockContentHeightDelayed();
                    } else {
                        if(mExtendLayout.isShown()){
                            hideLayout(mExtendLayout, false);
                        }
                        showLayout(mEmotionLayout);
                    }
                }
            }
        });
        return this;
    }

    /* Binding extension buttons (photo upload, location, red envelope, etc.) */
    public EmotionKeyboard bindToExtendbutton(View extendButton){
        extendButton.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View view) {
                if (mExtendLayout.isShown()) {
                    lockContentHeight();
                    hideLayout(mExtendLayout, true);
                    unlockContentHeightDelayed();
                } else {
                    if (isSoftInputShown()) {
                        lockContentHeight();
                        showLayout(mExtendLayout);
                        unlockContentHeightDelayed();
                    } else {
                        if (mEmotionLayout.isShown()) {
                            hideLayout(mEmotionLayout, false);
                        }
                        showLayout(mExtendLayout);
                    }
                }
            }
        });
        return this;
    }

    /* Set the expression layout to display */
    public EmotionKeyboard setEmotionView(View emotionView) {
        mEmotionLayout = emotionView;
        return this;
    }

    /* Set the extended layout to display */
    public EmotionKeyboard setExtendView(View extendView){
        mExtendLayout = extendView;
        return this;
    }

    public EmotionKeyboard build(){
        mActivity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN |
                WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
        hideSoftInput();
        return this;
    }

    public boolean interceptBackPress() {
        // TODO: 15/11/2 change this method's name
        if (mEmotionLayout.isShown()) {
            hideLayout(mEmotionLayout, false);
            return true;
        }
        return false;
    }

    /**
     *  Display the specified layout
     *  @param layout Layout to be displayed
     */
    private void showLayout(View layout) {
        int softInputHeight = getSupportSoftInputHeight();
        if (softInputHeight == 0) {
            softInputHeight = sp.getInt(SHARE_PREFERENCE_TAG, 750);
        }
        hideSoftInput();
        layout.getLayoutParams().height = softInputHeight;
        layout.setVisibility(View.VISIBLE);
    }

    /**
     * @param layout Layout view that needs to be hidden
     * @param showSoftInput Whether to display soft keyboard
     */
    private void hideLayout(View layout,boolean showSoftInput) {
        if (layout.isShown()) {
            layout.setVisibility(View.GONE);
            if (showSoftInput) {
                showSoftInput();
            }
        }
    }

    private void lockContentHeight() {
        LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) mContentView.getLayoutParams();
        params.height = mContentView.getHeight();
        params.weight = 0.0F;
    }

    private void unlockContentHeightDelayed() {
        mEditText.postDelayed(new Runnable() {
            @Override
            public void run() {
                ((LinearLayout.LayoutParams) mContentView.getLayoutParams()).weight = 1.0F;
            }
        }, 200L);
    }

    private void showSoftInput() {
        mEditText.requestFocus();
        mEditText.post(new Runnable() {
            @Override
            public void run() {
                mInputManager.showSoftInput(mEditText, 0);
            }
        });
    }

    private void hideSoftInput() {
        mInputManager.hideSoftInputFromWindow(mEditText.getWindowToken(), 0);
    }

    private boolean isSoftInputShown() {
        return getSupportSoftInputHeight() != 0;
    }

    private int getSupportSoftInputHeight() {
        Rect r = new Rect();
        mActivity.getWindow().getDecorView().getWindowVisibleDisplayFrame(r);
        int screenHeight = mActivity.getWindow().getDecorView().getRootView().getHeight();
        int softInputHeight = screenHeight - r.bottom;
        if (softInputHeight < 0) {
            Log.w("EmotionKeyboard", "Warning: value of softInputHeight is below zero!");
        }
        if (softInputHeight > 0) {
            sp.edit().putInt(SHARE_PREFERENCE_TAG, softInputHeight).apply();
        }
        return softInputHeight;
    }
}

How to use

1. Create the corresponding layout (here I put my picture, you can do whatever you want, if you don't want to set the extended layout, you don't want the + button; the expression layout is similar)


2. Bind the corresponding view

EmotionKeyboard emotionKeyboard = EmotionKeyboard.with(this)
             .setExtendView(extendView)
             .setEmotionView(emotionView)
             .bindToContent(contentView)
             .bindToEditText(edittext)
             .bindToExtendbutton(extendButton)
             .bindToEmotionButton(emotionButton)
             .build();

It's still very simple to use. If you don't have an extended layout, you don't call setExtendView and bindToEmotionButton.

3. Setting expressions or extended views (completely self-defined, customizable according to business needs)

  • xml of expression layout
    ViewPager + Fragment + GridView Displays Expressions
    RadioGroup Displays Tip Points
<FrameLayout
        android:id="@+id/emotion_layout"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:visibility="gone"
        tools:layout_height="200dp"
        tools:visibility="visible"
        android:orientation="vertical">

        <View
            android:layout_width="match_parent"
            android:layout_height="15dp"
            android:background="@color/transparent" />

        <android.support.v4.view.ViewPager
            android:id="@+id/pager"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

        <RadioGroup
            android:id="@+id/rg_reply_layout"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|center"
            android:layout_marginBottom="30dp"
            android:orientation="horizontal" >
        </RadioGroup>
    </FrameLayout>
  • xml for extended layout
    Actually, it's no different from expressing xml...
<FrameLayout
        android:id="@+id/extend_layout"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        tools:layout_height="200dp"
        android:orientation="vertical"
        android:visibility="gone"
        tools:visibility="visible" >

        <Button
            android:id="@+id/btn_replay_layout_pic"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:drawableTop="@drawable/photo"
            android:text="@string/photo"
            android:background="@null"
            android:textColor="@color/dark_gray"
            android:layout_margin="5dp"/>

    </FrameLayout>
  • Code for handling expression views and extended views
    Because I'm lazy, I won't post it here. Refer to the setUpEmotionViewPager() and setUpExtendView() methods of MainActivity on github, hahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahaha .

Okay, that's about it. The code needs to be optimized later. Any good suggestions can also tell me.~

Posted by DesertFox07 on Mon, 25 Mar 2019 09:30:29 -0700