仿微信控制输入法的显示和隐藏

最近有个需求,就是输入法底部添加一个菜单栏,比如有个Button,可以切换输入法面板和自定义表情面板。如下图:


点击编辑框跳出该界面。点击表情,切换本地表情界面:


具体实现如下:

该界面的布局为:

<com.hotpic.cn.widget.ResizeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/root_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <include
        android:id="@id/actionBar"
        layout="@layout/actionbar_layout" />

    <EditText
        android:id="@+id/textContentEdit"
        android:layout_width="match_parent"
        android:layout_height="108dp"
        android:layout_below="@id/actionBar"
        android:background="@color/white"
        android:hint="@string/content_hint"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin" />

    <RelativeLayout
        android:id="@+id/reLayoutInputMethod"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:background="@color/green_send_enable">

        <Button
            android:id="@+id/inputMethodImgBtn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/face_img"
            android:visibility="visible" />

        <RelativeLayout
            android:id="@+id/footer_for_emoticons"
            android:layout_width="match_parent"
            android:layout_height="230dp"
            android:background="@android:color/transparent"
            android:visibility="gone"
            android:layout_below="@id/inputMethodImgBtn">
        </RelativeLayout>
    </RelativeLayout>

</com.hotpic.cn.widget.ResizeLayout>

其中ResizeLayout的作用是实现软键盘的监听,具体可以 参考,实现如下:

package com.hotpic.cn.widget;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.RelativeLayout;

/**
 * TODO: document your custom view class.
 */
public class ResizeLayout extends RelativeLayout {

    private OnResizeListener mListener;

    public interface OnResizeListener {
        void OnResize(int w, int h, int oldw, int oldh);
    }

    public void setOnResizeListener(OnResizeListener l) {
        mListener = l;
    }

    public ResizeLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        if (mListener != null) {
            mListener.OnResize(w, h, oldw, oldh);
        }
    }
}
activity的实现如下:

package com.hotpic.cn;

import android.app.Activity;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
import android.widget.RelativeLayout;
import android.widget.Toast;

import com.hotpic.cn.widget.ResizeLayout;

/**
 * 文字编写,图片添加操作界面
 */
public class OperationContentActivity extends Activity implements View.OnClickListener,ResizeLayout.OnResizeListener{
    private ResizeLayout rootLayout;
    private EditText textContentEdit;
    private Button backBtn;
    private Button sendBtn;
    private RelativeLayout reLayoutInputMethod;  //输入时的布局
    private Button inputMethodImgBtn;
    private View popUpView; //本地表情布局
    private PopupWindow popupWindow;  //本地表情布局
    private boolean isKeyBoardVisible;  // 输入法软盘是否显示

    private int softHeight;  //输入法的高度
    /**
     * activity_main布局线性布局,没有子控件
     */
    private RelativeLayout emoticonsCover;

    private static final int BIGGER = 1;
    private static final int SMALLER = 2;
    private static final int MSG_RESIZE = 1;

    private static final int HEIGHT_THREADHOLD = 30;

    class InputHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_RESIZE: {
                    if (msg.arg1 == BIGGER) {
                        findViewById(R.id.reLayoutInputMethod).setVisibility(View.VISIBLE);
                    } else {
                        findViewById(R.id.reLayoutInputMethod).setVisibility(View.GONE);
                    }
                }
                break;

                default:
                    break;
            }
            super.handleMessage(msg);
        }
    }

    private InputHandler mHandler = new InputHandler();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_operation_content);

        init();
    }

    private void init() {
        rootLayout = (ResizeLayout)findViewById(R.id.root_layout);
        rootLayout.setOnResizeListener(this);
        textContentEdit = (EditText) findViewById(R.id.textContentEdit);
        textContentEdit.addTextChangedListener(new EditChangeListener());

        backBtn = (Button) findViewById(R.id.backBtn);
        sendBtn = (Button) findViewById(R.id.sendBtn);
        backBtn.setOnClickListener(this);
        sendBtn.setOnClickListener(this);
        reLayoutInputMethod = (RelativeLayout) findViewById(R.id.reLayoutInputMethod);

        inputMethodImgBtn = (Button)findViewById(R.id.inputMethodImgBtn);
        inputMethodImgBtn.setOnClickListener(this);
        emoticonsCover = (RelativeLayout) findViewById(R.id.footer_for_emoticons);
        popUpView = LayoutInflater.from(this).inflate(R.layout.emoticons_popup,null);

        changeKeyboardHeight(200);

        enablePopupView();
        checkKeyboardHeight(rootLayout);
        enableFooterView();
    }

    private void enablePopupView() {
        popupWindow = new PopupWindow(popUpView, RelativeLayout.LayoutParams.MATCH_PARENT,
                 softHeight, false);
        popupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {

            @Override
            public void onDismiss() {
                emoticonsCover.setVisibility(LinearLayout.GONE);
            }
        });
    }

    /**
     * Checking keyboard height and keyboard visibility
     */
    int previousHeightDiffrence = 0;
    private void checkKeyboardHeight(final View parentLayout) {
        parentLayout.getViewTreeObserver().addOnGlobalLayoutListener(
                new ViewTreeObserver.OnGlobalLayoutListener() {

                    @Override
                    public void onGlobalLayout() {

                        Rect r = new Rect();
                        parentLayout.getWindowVisibleDisplayFrame(r);

                        int screenHeight = parentLayout.getRootView()
                                .getHeight();
                        int heightDifference = screenHeight - (r.bottom);

                        if (previousHeightDiffrence - heightDifference > 50) {
                            popupWindow.dismiss();
                        }

                        previousHeightDiffrence = heightDifference;
                        if (heightDifference > 100) {

                            isKeyBoardVisible = true;
                            changeKeyboardHeight(heightDifference-165);   //减165为了使菜单显示

                        } else {
                            isKeyBoardVisible = false;
                        }

                    }
                });
    }

    /**
     * change height of emoticons keyboard according to height of actual
     * keyboard
     *
     * @param height
     *            minimum height by which we can make sure actual keyboard is
     *            open or not
     */
    private void changeKeyboardHeight(int height) {

        if (height > 100) {
            softHeight = height;
            RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
                    RelativeLayout.LayoutParams.MATCH_PARENT, softHeight);
            emoticonsCover.setLayoutParams(params);
        }

    }

    /**
     * Enabling all content in footer i.e. post window
     */
    private void enableFooterView() {

        textContentEdit.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (popupWindow.isShowing()) {
                    popupWindow.dismiss();
                }
            }
        });
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (popupWindow.isShowing()){
            popupWindow.dismiss();
            return false;
        }else {
            return super.onKeyDown(keyCode, event);
        }
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.backBtn:
                OperationContentActivity.this.finish();
                break;
            case R.id.sendBtn:
                Toast.makeText(OperationContentActivity.this, "发送成功", Toast.LENGTH_LONG).show();
                break;
            case R.id.inputMethodImgBtn:   //隐藏输入法,切换至本地表情小图标

                if (!popupWindow.isShowing()){

                    popupWindow.setHeight(softHeight);

                    if (isKeyBoardVisible){
                        emoticonsCover.setVisibility(View.GONE);
                    }else {
                        emoticonsCover.setVisibility(View.VISIBLE);
                    }
                    popupWindow.showAtLocation(rootLayout, Gravity.BOTTOM,0,0);
                }else {
                    popupWindow.dismiss();
                }
                break;
            default:
                break;
        }
    }

    private class EditChangeListener implements TextWatcher {
        @Override
        public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
        }

        @Override
        public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
            sendBtnStateChange();
        }

        @Override
        public void afterTextChanged(Editable editable) {
            sendBtnStateChange();
        }
    }

    /**
     * 发送按钮控制
     */
    private void sendBtnStateChange() {
        if (textContentEdit.getText().length() > 0) {
            sendBtn.setEnabled(true);
            sendBtn.setBackgroundColor(getResources().getColor(R.color.green_send_enable));
        } else {
            sendBtn.setEnabled(false);
            sendBtn.setBackgroundColor(getResources().getColor(R.color.green_send_unenable));
        }
    }

    @Override
    public void OnResize(int w, int h, int oldw, int oldh) {
        int change = BIGGER;
        if (h > oldh) {
            change = SMALLER;
        }
        Message msg = new Message();
        msg.what = 1;
        msg.arg1 = change;
        mHandler.sendMessage(msg);
    }
}

其中emotions_popup布局如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/material_blue_grey_800">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:textColor="@color/white"
        android:text="本地表情"/>
</RelativeLayout>
这样就可以实现了。

配置文件需要声明:

<activity
    android:name="com.hotpic.cn.OperationContentActivity"
    android:windowSoftInputMode="adjustResize"
    android:label="@string/title_activity_operation_content" >
</activity>


注:

这其中报了一个错误,以前没有遇见过的,在此记录下:

java.lang.ClassCastException: android.widget.LinearLayout$LayoutParams cannot be cast to android.widget.RelativeLayout$LayoutParams

这个错误很奇怪,单看代码是找不到的,问题是在子控件第二次添加params的时候,需要保持和父控件一直。说的有点乱,给个链接吧:

http://blog.csdn.net/nobaddd/article/details/7370688 



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值