很久没写博客了,因为最近有些茫然,好了不废话,说主题,做IM模块的同学应该都知道有一个UI效果一般是跑不掉的,就是发送消息到公屏上
我现在要在这里展示的就是模仿映客做的一个键盘弹出,发送消息的效果.,先上一张图,不然看不到效果大伙也没兴趣往下看了.
开始的时候觉得很简单,设置下windowSoftInputMode,写一个EditText,然后点击之后弹出来,点击空白区域消失吗,在一系列的demo之后发觉真的不是那么简单,各种方法试过,什么 ViewTreeObserver,onSizeChanged(),要么就是得不到键盘高度,要么就是视图被压缩了,总之就是都失败了
苦试无果之后,各种百度,google,可惜没有找到一个满意的demo,看了别人说可以用浮层来做,就想到了popupwindow,又一番实验之后发觉不可行,最好决定再试试dialog,然后,嘿,可以了,达到了满意的效果,好了说这么多废话,上代码了,
自定义dialog:
package org.dync.softkeyboarddemo;
import android.app.Dialog;
import android.content.Context;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.text.InputType;
import android.text.TextUtils;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
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;
import android.widget.Toast;
import java.lang.reflect.Field;
/**
* 文本输入框
*/
public class InputTextDialog extends Dialog {
public interface OnTextSendListener {
void onTextSend(String msg, boolean tanmuOpen);
}
private TextView confirmBtn;
private LinearLayout mBarrageArea;
private EditText messageTextView;
private static final String TAG = InputTextDialog.class.getSimpleName();
private Context mContext;
private InputMethodManager imm;
private RelativeLayout rlDlg;
private int mLastDiff = 0;
private LinearLayout mConfirmArea;
private OnTextSendListener mOnTextSendListener;
private boolean mDanmuOpen = false;
// private final String reg = "[`~@#$%^&*()-_+=|{}':;,/.<>¥…()—【】‘;:”“’。,、]";
// private Pattern pattern = Pattern.compile(reg);
public InputTextDialog(Context context, int theme) {
super(context, theme);
mContext = context;
setContentView(R.layout.dialog_input_text);
messageTextView = (EditText) findViewById(R.id.et_input_message);
messageTextView.setInputType(InputType.TYPE_CLASS_TEXT);
//修改下划线颜色
messageTextView.getBackground().setColorFilter(context.getResources().getColor(R.color.transparent), PorterDuff.Mode.CLEAR);
try {
//修改光光标颜色
Field ft = TextView.class.getDeclaredField("mCursorDrawableRes");
ft.setAccessible(true);
ft.set(messageTextView, R.drawable.edit_select);
} catch (Exception e) {
e.printStackTrace();
}
confirmBtn = (TextView) findViewById(R.id.confrim_btn);
imm = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
confirmBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String msg = messageTextView.getText().toString().trim();
if (!TextUtils.isEmpty(msg)) {
mOnTextSendListener.onTextSend(msg, mDanmuOpen);
imm.showSoftInput(messageTextView, InputMethodManager.SHOW_FORCED);
imm.hideSoftInputFromWindow(messageTextView.getWindowToken(), 0);
messageTextView.setText("");
dismiss();
} else {
Toast.makeText(mContext, "input can not be empty!", Toast.LENGTH_LONG).show();
}
messageTextView.setText(null);
}
});
final Button barrageBtn = (Button) findViewById(R.id.barrage_btn);
barrageBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mDanmuOpen = !mDanmuOpen;
if (mDanmuOpen) {
barrageBtn.setBackgroundResource(R.drawable.barrage_slider_on);
} else {
barrageBtn.setBackgroundResource(R.drawable.barrage_slider_off);
}
}
});
mBarrageArea = (LinearLayout) findViewById(R.id.barrage_area);
mBarrageArea.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mDanmuOpen = !mDanmuOpen;
if (mDanmuOpen) {
barrageBtn.setBackgroundResource(R.drawable.barrage_slider_on);
} else {
barrageBtn.setBackgroundResource(R.drawable.barrage_slider_off);
}
}
});
//监听键盘
messageTextView.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
switch (actionId) {
case KeyEvent.KEYCODE_ENDCALL:
case KeyEvent.KEYCODE_ENTER:
if (messageTextView.getText().length() > 0) {
// mOnTextSendListener.onTextSend("" + messageTextView.getText(), mDanmuOpen);
//sendText("" + messageTextView.getText());
//imm.showSoftInput(messageTextView, InputMethodManager.SHOW_FORCED);
imm.hideSoftInputFromWindow(messageTextView.getWindowToken(), 0);
// messageTextView.setText("");
dismiss();
} else {
Toast.makeText(mContext, "input can not be empty!", Toast.LENGTH_LONG).show();
}
return true;
case KeyEvent.KEYCODE_BACK:
dismiss();
return false;
default:
return false;
}
}
});
mConfirmArea = (LinearLayout) findViewById(R.id.confirm_area);
mConfirmArea.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String msg = messageTextView.getText().toString().trim();
if (!TextUtils.isEmpty(msg)) {
mOnTextSendListener.onTextSend(msg, mDanmuOpen);
imm.showSoftInput(messageTextView, InputMethodManager.SHOW_FORCED);
imm.hideSoftInputFromWindow(messageTextView.getWindowToken(), 0);
messageTextView.setText("");
dismiss();
} else {
Toast.makeText(mContext, "input can not be empty!", Toast.LENGTH_LONG).show();
}
messageTextView.setText(null);
}
});
messageTextView.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View view, int i, KeyEvent keyEvent) {
Log.d("My test", "onKey " + keyEvent.getCharacters());
return false;
}
});
rlDlg = (RelativeLayout) findViewById(R.id.rl_outside_view);
rlDlg.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//点击编辑区域以上的位置,dialog消失
if (v.getId() != R.id.rl_inputdlg_view)
dismiss();
}
});
final LinearLayout rldlgview = (LinearLayout) findViewById(R.id.rl_inputdlg_view);
//dialog消失键盘会消失,但是键盘消失,dialog不一定消失,比如按软键盘上的消失键,键盘消失,dialog不会消失
// 所以在这里监听键盘的高度,如果高度为0则表示键盘消失,那么就应该dimiss dialog
rldlgview.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
@Override
public void onLayoutChange(View view, int i, int i1, int i2, int i3, int i4, int i5, int i6, int i7) {
Rect r = new Rect();
//获取当前界面可视部分
getWindow().getDecorView().getWindowVisibleDisplayFrame(r);
//获取屏幕的高度
int screenHeight = getWindow().getDecorView().getRootView().getHeight();
//此处就是用来获取键盘的高度的, 在键盘没有弹出的时候 此高度为0 键盘弹出的时候为一个正数
int heightDifference = screenHeight - r.bottom;
if (heightDifference <= 0 && mLastDiff > 0) {
//imm.hideSoftInputFromWindow(messageTextView.getWindowToken(), 0);
dismiss();
}
mLastDiff = heightDifference;
}
});
//点击编辑外部layout键盘消失,这个可有可无
// rldlgview.setOnClickListener(new View.OnClickListener() {
// @Override
// public void onClick(View v) {
// imm.hideSoftInputFromWindow(messageTextView.getWindowToken(), 0);
// dismiss();
// }
// });
}
public void setmOnTextSendListener(OnTextSendListener onTextSendListener) {
this.mOnTextSendListener = onTextSendListener;
}
@Override
public void dismiss() {
super.dismiss();
//dismiss之前重置mLastDiff值避免下次无法打开
mLastDiff = 0;
}
@Override
public void show() {
super.show();
}
}
直接看这个代码可能有点不太懂,其实原理就是利用dialog的dimiss,因为EditText纯在与dialog中,dialog消失之后,EditText也会消失,那么键盘自然就消失了,注释也写的很详细了,有基础的同学肯定可以看懂的,后面也会把demo地址发出来
dialog_input_text.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/rl_outside_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/rl_inputdlg_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/color_input_dialog_background"
android:orientation="horizontal"
android:layout_alignParentBottom="true">
<LinearLayout
android:id="@+id/barrage_area"
android:orientation="horizontal"
android:layout_weight="0.3"
android:layout_gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<Button
android:id="@+id/barrage_btn"
android:layout_width="40dp"
android:layout_marginLeft="10dp"
android:layout_height="25dp"
android:layout_marginRight="10dp"
android:background="@drawable/barrage_slider_off" />
</LinearLayout>
<View android:layout_width="0.5dp"
android:layout_height="match_parent"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:layout_marginLeft="6dp"
android:layout_marginStart="6dp"
android:background="@color/colorTransparentBlack"/>
<EditText
android:id="@+id/et_input_message"
android:hint="@string/dialog_input_text_hint"
android:layout_width="match_parent"
android:layout_weight="4"
android:layout_height="wrap_content"
android:imeActionId="@+id/login"
android:imeOptions="actionUnspecified"
android:inputType="text"
android:maxLength="32"
android:textColor="@color/black"
android:maxLines="1"
android:singleLine="true" />
<View android:layout_width="0.5dp"
android:layout_height="match_parent"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:layout_marginLeft="6dp"
android:layout_marginStart="6dp"
android:background="@color/colorTransparentBlack"/>
<LinearLayout
android:id="@+id/confirm_area"
android:layout_width="wrap_content"
android:layout_gravity="center"
android:layout_height="wrap_content">
<Button
android:id="@+id/confrim_btn"
android:layout_width="50dp"
android:layout_height="30dp"
android:background="@drawable/btn_send_message"
android:gravity="center"
android:textColor="@color/colorAccent"
android:text="发送" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>
这个是输入消息的dialog,嗯,没什么可说的,后面的也不发了,小demo,资源文件也有一些,太久没写博客了,自定义空间方面的东西也没啥好说的,还是直接上地址,大家去copy了看效果吧.
地址:百度网盘