最近有个需求,就是输入法底部添加一个菜单栏,比如有个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