package com.testbbfemoj;import android.app.Activity;import android.os.Bundle;import android.view.MotionEvent;import android.view.View;import android.view.View.OnTouchListener;import android.view.ViewTreeObserver;import android.view.ViewTreeObserver.OnGlobalLayoutListener;import android.view.Window;import android.view.inputmethod.InputMethodManager;import android.widget.Button;import android.widget.EditText;import android.widget.LinearLayout;import android.widget.RelativeLayout;import android.widget.TextView;public class MainActivity extends Activity implements View.OnClickListener {private TextView topTitle;private Button btnEmotion;private EditText edtContent;private RelativeLayout rl_emotions;// 表情选择布局private LinearLayout ll_emotion;// 表情按钮+选择布局private int[] oldLocation = new int[2];// 获取表情按钮的位置private int HEIGHT_BOTTOM;// 关键值,用于判断键盘的关闭事件,在表情按钮invisible的时候测量到private InputMethodManager mInputMethodManager;private int STATE = 0;private static final int GONE_INVISIBLE = 1;// 当点击编辑框时,表情布局由GONE到INVISIBLE。// 之所以设为INVISIBL而不直接visible,是因为它首先会出现在底部,然后闪一下到输入法上面,出现闪屏,体验差。// 但是又不能不让它在底部先显示一下再跳到输入法上面,因为需要在初期就获取到表情按钮在底部的位置,否则上去了之后,无法监听输入法的关闭状态// 解决方案就是:先让它invisible,获取到表情按钮在底部的位置,然后在它跳到输入法上面时,再visible,完美解决闪屏的问题private static final int INVISIBLE_UP_SOFT = 2;// 当表情按钮由不可见到跳到输入法上边private static final int UP_EMOTION = 3;// 当显示表情选择框,表情按钮在框上面时private static final int SOFT_UP_DOWN = 4;// 当表情按钮掉到屏幕底部时,这就是键盘关闭事件private static final int DOWN_GONE = 5;// 当表情按钮消失时private boolean isNeedHide = true;// 当由输入法切换到表情时,或者表情切换到输入法时,会临时导致表情按钮掉到底部,触发监听事件,造成误判// 因此设为false时,忽略触发的监听private boolean isKeyboardShowing = false;private boolean isEmotionShowing = false;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);requestWindowFeature(Window.FEATURE_NO_TITLE);mInputMethodManager = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);setContentView(R.layout.activity_main);initView();initEvent();}private void initView() {topTitle = (TextView) findViewById(R.id.top_title);topTitle.setText("弹出表情");btnEmotion = (Button) findViewById(R.id.btnEmotion);edtContent = (EditText) findViewById(R.id.edt_content);ll_emotion = (LinearLayout) findViewById(R.id.m_table_menu);rl_emotions = (RelativeLayout) findViewById(R.id.rl_emotions);oldLocation[0] = 0;oldLocation[1] = 0;}private void initEvent() {btnEmotion.setOnClickListener(this);edtContent.setOnTouchListener(mOnTouchListener);ViewTreeObserver vto = ll_emotion.getViewTreeObserver();vto.addOnGlobalLayoutListener(mLayoutListener);}private OnTouchListener mOnTouchListener = new OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_UP:if (ll_emotion.getVisibility() == View.GONE) {HEIGHT_BOTTOM = 0;ll_emotion.setVisibility(View.INVISIBLE);// 如果直接visible,会导致屏幕下方有个一闪的画面STATE = GONE_INVISIBLE;// 下一个状态if (!isKeyboardShowing && !isEmotionShowing) {isKeyboardShowing = true;}}if (isEmotionShowing) {isNeedHide = false;// 避免误判STATE = INVISIBLE_UP_SOFT;// 处理当显示表情时,点击表情按钮和点击编辑框都将触发监听造成的冲突rl_emotions.setVisibility(View.GONE);mInputMethodManager.showSoftInput(edtContent, 0);isKeyboardShowing = true;isEmotionShowing = false;}}return false;}};private OnGlobalLayoutListener mLayoutListener = new OnGlobalLayoutListener() {@Overridepublic void onGlobalLayout() {handleHeightChange();}};private void handleHeightChange() {int[] newLocation = new int[2];ll_emotion.getLocationOnScreen(newLocation);if (newLocation[1] == HEIGHT_BOTTOM&& (STATE == INVISIBLE_UP_SOFT || STATE == UP_EMOTION)) {if (isNeedHide) {STATE = SOFT_UP_DOWN;} else {if (STATE == UP_EMOTION) {rl_emotions.setVisibility(View.VISIBLE);// 这里并不会及时地显示在屏幕下方,会在已经消失的输入法原来位置的上方停留一会才掉下去,造成闪屏,完美解决闪屏的问题,哈哈!!!}isNeedHide = true;// 确保在切换输入方式回调之后标志正确return;}}switch (STATE) {case GONE_INVISIBLE:HEIGHT_BOTTOM = newLocation[1];STATE = INVISIBLE_UP_SOFT;break;case INVISIBLE_UP_SOFT:if (ll_emotion.getVisibility() == View.INVISIBLE) {ll_emotion.setVisibility(View.VISIBLE);}break;case SOFT_UP_DOWN:ll_emotion.setVisibility(View.GONE);STATE = DOWN_GONE;break;case DOWN_GONE:break;case UP_EMOTION:break;}}@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.btnEmotion:// 如果在显示软键盘就显示表情if (isKeyboardShowing) {isNeedHide = false;// 避免误判isEmotionShowing = true;isKeyboardShowing = false;STATE = UP_EMOTION;hideInputMethod();} else if (isEmotionShowing) {// 如果在显示表情就显示软键盘isNeedHide = false;// 避免误判STATE = INVISIBLE_UP_SOFT;rl_emotions.setVisibility(View.GONE);mInputMethodManager.showSoftInput(edtContent, 0);isKeyboardShowing = true;isEmotionShowing = false;}break;}}public void hideInputMethod() {try {mInputMethodManager.hideSoftInputFromWindow(this.getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);} catch (Exception e) {e.printStackTrace();}}}
package com.testbbfemoj;import android.app.Acti