关于输入法表情包的问题

搜狗输入法打字的时候怎样打出表情符号?_百度知道
搜狗输入法打字的时候怎样打出表情符号?
电脑版的...
答题抽奖
首次认真答题后
即可获得3次抽奖机会,100%中奖。
来自电脑网络类芝麻团
采纳数:20416
获赞数:109663
参与团队:
直接输入表情符号的拼音就可以,第四候选项是表情符号,第五候选项是图片表情。想查看更多表情,在搜狗输入法状态下快捷键ctrl+shift+B
采纳数:21
获赞数:60
Ctrl+Shift+B,会跳出一个界面,里面有很多符号表情或者打出想要表达的意思,在第四项应该是符号表情,前提是搜狗有这个表情
采纳数:22
获赞数:157
随便摁一个字母,再 分号+F试试吧,不行找我
为你推荐:
其他类似问题
您可能关注的内容
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。那些颜文字里的表情都是些什么符号?离开输... | 问答 | 问答 | 果壳网 科技有意思
那些颜文字里的表情都是些什么符号?离开输入法我就不会打了……
(╯°Д°)╯︵ /(.□ . \)
ψ(`??)ψ
理學雙碩士,工學雙學士,運動控制研究員
左括弧、撇(漢字筆劃)、度(單位)、De(西里爾字母)、度、右括弧、撇、tie(拉丁語變音,一般位於字母上方)、斜杠、左括弧、句點、無相關字體、句點、反斜杠、右括弧、Psi(希臘字母)、左括弧、grave(拉丁語變音)、Nabla算子、acute(拉丁語變音)、右括弧、Psi。
后回答问题,你也可以用以下帐号直接登录
(C)果壳网&&&&京ICP证100430号&&&&京网文[-239号&&&&新出发京零字东150005号&&&&
违法和不良信息举报邮箱:&&&&举报电话:&&&&&&&&Android输入法与表情面板切换时的界面抖动问题解决方法
转载 &更新时间:日 14:13:32 & 作者:LanTingShuXu
这篇文章主要介绍了Android输入法与表情面板切换时的界面抖动问题解决方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
昨天琢磨了下Android的输入法弹出模式,突然发现利用动态切换输入法的弹出模式可以解决输入法抖动的问题。具体是怎样的抖动呢?我们先看微博的反面教材。
【具体表现为:表情面板与输入法面板高度不一致,从而导致弹出输入法(layout被挤压)时,同时又需要隐藏表情面板(layout被拉升),最终让界面产生了高度差抖动,所以在切换时明显会有不大好的抖动体验)】
使用了解决抖动的解决方案后,效果如下:
【这样的方案明显比微博的切换更平滑】
老样子,先说思路。主要我们要用到两个输入法弹出模式,分别是:adjustResize(调整模式) 、adjustNothing(不做任何调整) 。(更多介绍请参看我的上一篇文章:输入法弹出参数分析)
1.初始情况时(键盘和表情面板都未展开):我们为表情面板设置一个默认高度(因为我们还不知道键盘有多高)并将输入发弹出模式设置为adjustResize模式。
2.当我们点击了EditText时,系统将会弹出输入法,由于之前我们设置的模式为adjustResize,因此,输入法会挤压Layout,并且挤压的高度最终会固定到一个值(键盘的高度),当我们检测到挤压后,将这个挤压差值(也就是键盘高度)记录下来,作为表情面板的新高度值。于此同时,我们将表情面板隐藏。
3.当我们点击了表情按钮时,我们需要先判断输入法是否已展开。
1)如果已经展开,那么我们的任务是将键盘平滑隐藏并显示表情面板。具体做法为:先将Activity的输入法弹出模式设置为adjustNothing,然后将上一步记录下来的键盘高度作为表情面板的高度,再将表情面板显示,此时由于键盘弹出模式为adjustNothing,所以键盘不会有任何抖动,并且由于表情面板与键盘等高,因此EditText也不会下移,最后将输入法隐藏。
2)如果输入法未展开,我们再判断表情面板是否展开,如果展开了就隐藏并将输入法弹出模式归位为adjustResize,如果未展开就直接显示并将输入法弹出模式设置为adjustNothing。
大致的实现思路就是上面说到的,但是,既然都准备动手做帮助类了,就顺便将点击空白处折叠键盘和表情面板一起做了。具体实现思路为:在Activity的DecorView上面遮罩一层FrameLayout,用于监听触摸的Aciton_Down事件,如果在输入范围之外,则折叠表情面板和键盘。示意图如下:
该说的说完了,开动。
1、创建InputMethodUtils类,构造方法需要传递Activity参数,并申明所需要的成员变量,并实现View.OnClickListener接口(因为我们要监听表情按钮的点击事件)。代码如下:
public class InputMethodUtils implements View.OnClickListener {
// 键盘是否展开的标志位
private boolean sIsKeyboardS
// 键盘高度变量
private int sKeyBoardHeight = 0;
// 绑定的Activity
* 构造函数
* @param activity
需要处理输入法的当前的Activity
public InputMethodUtils(Activity activity) {
this.activity =
//DisplayUtils为屏幕尺寸工具类
DisplayUtils.init(activity);
// 默认键盘高度为267dp
setKeyBoardHeight(DisplayUtils.dp2px(267));
public void onClick(View v) {
//DisplayUtils的实现代码为:
* 屏幕参数的辅助工具类。例如:获取屏幕高度,宽度,statusBar的高度,px和dp互相转换等
* 【注意,使用之前一定要初始化!一次初始化就OK(建议APP启动时进行初始化)。 初始化代码 DisplayUtils.init(context)】
* @author 蓝亭书序
private static class DisplayUtils {
// 四舍五入的偏移值
private static final float ROUND_CEIL = 0.5f;
// 屏幕矩阵对象
private static DisplayMetrics sDisplayM
// 资源对象(用于获取屏幕矩阵)
private static Resources sR
// statusBar的高度(由于这里获取statusBar的高度使用的反射,比较耗时,所以用变量记录)
private static int statusBarHeight = -1;
* 初始化操作
* @param context
context上下文对象
public static void init(Context context) {
sDisplayMetrics = context.getResources().getDisplayMetrics();
sResources = context.getResources();
* 获取屏幕高度 单位:像素
* @return 屏幕高度
public static int getScreenHeight() {
return sDisplayMetrics.heightP
* 获取屏幕宽度 单位:像素
* @return 屏幕宽度
public static float getDensity() {
return sDisplayMetrics.
* dp 转 px
* @param dp
* @return 转换后的像素值
public static int dp2px(int dp) {
return (int) (dp * getDensity() + ROUND_CEIL);
* 获取状态栏高度
* @return 状态栏高度
public static int getStatusBarHeight() {
// 如果之前计算过,直接使用上次的计算结果
if (statusBarHeight == -1) {
final int defaultHeightInDp = 19;// statusBar默认19dp的高度
statusBarHeight = DisplayUtils.dp2px(defaultHeightInDp);
Class&?& c = Class.forName("com.android.internal.R$dimen");
Object obj = c.newInstance();
Field field = c.getField("status_bar_height");
statusBarHeight = sResources.getDimensionPixelSize(Integer
.parseInt(field.get(obj).toString()));
} catch (Exception e) {
e.printStackTrace();
return statusBarH
【搬砖去了,等会继续写… … 】好了,继续写… …
2、在继续往下写之前,我们得考虑如何设计表情按钮、表情按钮点击事件、表情面板之间的问题。我的做法是创建一个ViewBinder内部类。(因为在逻辑上来说,这三个属于一体的)
ViewBinder的实现代码如下:
* 用于控制点击某个按钮显示或者隐藏“表情面板”的绑定bean对象。&br/&
* 例如:我想点击“表情”按钮显示“表情面板”,我就可以这样做:&br/&
* ViewBinder viewBinder = new ViewBinder(btn_emotion,emotionPanel);&br/&
* 这样就创建出了一个ViewBinder对象&br/&
* &font color='red'&【注意事项,使用此类时,千万不要使用trigger的setOnClickListener来监听事件(
* 使用OnTriggerClickListener来代替),也不要使用setTag来设置Tag,否则会导致使用异常】&/font&
* @author 蓝亭书序
public static class ViewBinder {
private V//表情按钮对象
private V//表情面板对象
//替代的监听器
private OnTriggerClickL
* 创建ViewBinder对象&br/&
* 例如:我想点击“表情”按钮显示“表情面板”,我就可以这样做:&br/&
* ViewBinder viewBinder = new
* ViewBinder(btn_emotion,emotionPanel,listener);&br/&
* 这样就创建出了一个ViewBinder对象
* @param trigger
* @param panel
点击触发对象需要显示/隐藏的面板对象
* @param listener
Trigger点击的监听器(千万不要使用setOnClickListener,否则会覆盖本工具类的监听器)
public ViewBinder(View trigger, View panel,
OnTriggerClickListener listener) {
this.trigger =
this.panel =
this.listener =
trigger.setClickable(true);
public boolean equals(Object obj) {
if (this == obj)
if (obj == null)
if (getClass() != obj.getClass())
ViewBinder other = (ViewBinder)
if (panel == null) {
if (other.panel != null)
} else if (!panel.equals(other.panel))
if (trigger == null) {
if (other.trigger != null)
} else if (!trigger.equals(other.trigger))
public OnTriggerClickListener getListener() {
public void setListener(OnTriggerClickListener listener) {
this.listener =
public View getTrigger() {
public void setTrigger(View trigger) {
this.trigger =
public View getPanel() {
public void setPanel(View panel) {
this.panel =
其中OnTriggerClickListener是为了解决trigger占用监听器的问题(我们内部逻辑需要占用监听器,如果外部想实现额外的点击逻辑不能再为trigger添加监听器,所以使用OnTriggerClickListener来代替原原声的OnClickListener)。OnTriggerClickListener为一个接口,实现代码如下:
* ViewBinder的触发按钮点击的监听器
* @author 蓝亭书序
public static interface OnTriggerClickListener {
* 点击事件的回调函数
* @param v 被点击的按钮对象
public void onClick(View v);
3、实现了ViewBinder后,我们还需要实现一个遮罩View,用于监听ACTION_DOWN事件。代码如下:
* 点击软键盘区域以外自动关闭软键盘的遮罩View
* @author 蓝亭书序
private class CloseKeyboardOnOutsideContainer extends FrameLayout {
public CloseKeyboardOnOutsideContainer(Context context) {
this(context, null);
public CloseKeyboardOnOutsideContainer(Context context,
AttributeSet attrs) {
this(context, attrs, 0);
public CloseKeyboardOnOutsideContainer(Context context,
AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
/*如果不知道这个方法的作用的话,需要了解下Android的事件分发机制哈,如果有时间我也可以写个文章介绍下。dispatchTouchEvent方法主要是ViewGroup在事件分发之前进行事件进行判断,如果返回true表示此ViewGroup拦截此事件,这个事件将不会传递给他的子View,如果返回false,反之。*/
public boolean dispatchTouchEvent(MotionEvent event) {
//这段逻辑不复杂,看一遍应该就懂
boolean isKeyboardShowing = isKeyboardShowing();
boolean isEmotionPanelShowing = hasPanelShowing();
if ((isKeyboardShowing || isEmotionPanelShowing)
&& event.getAction() == MotionEvent.ACTION_DOWN) {
int touchY = (int) (event.getY());
int touchX = (int) (event.getX());
if (isTouchKeyboardOutside(touchY)) {
if (isKeyboardShowing) {
hideKeyBordAndSetFlag(activity.getCurrentFocus());
if (isEmotionPanelShowing) {
closeAllPanels();
if (isTouchedFoucusView(touchX, touchY)) {
// 如果点击的是输入框(会弹出输入框),那么延时折叠表情面板
postDelayed(new Runnable() {
public void run() {
setKeyboardShowing(true);
return super.onTouchEvent(event);
* 是否点击软键盘和输入法外面区域
* @param activity
当前activity
* @param touchY
点击y坐标(不包括statusBar的高度)
private boolean isTouchKeyboardOutside(int touchY) {
View foucusView = activity.getCurrentFocus();
if (foucusView == null) {
int[] location = new int[2];
foucusView.getLocationOnScreen(location);
int editY = location[1] - DisplayUtils.getStatusBarHeight();
int offset = touchY - editY;
if (offset & 0 && offset & foucusView.getMeasuredHeight()) {
* 是否点击的是当前焦点View的范围
* @param x
* @param y
y方向坐标(不包括statusBar的高度)
* @return true表示点击的焦点View,false反之
private boolean isTouchedFoucusView(int x, int y) {
View foucusView = activity.getCurrentFocus();
if (foucusView == null) {
int[] location = new int[2];
foucusView.getLocationOnScreen(location);
int foucusViewTop = location[1] - DisplayUtils.getStatusBarHeight();
int offsetY = y - foucusViewT
if (offsetY & 0 && offsetY & foucusView.getMeasuredHeight()) {
int foucusViewLeft = location[0];
int foucusViewLength = foucusView.getWidth();
int offsetX = x - foucusViewL
if (offsetX &= 0 && offsetX &= foucusViewLength) {
4、准备工作做完,我们可以继续完善InputMethodUtils类了,由于我们需要存储ViewBinder对象(主要用于控制按钮和面板之间的关联关系),所以,我们还需要在InputMethodUtils中申明一个集合。代码如下:
// 触发与面板对象集合(使用set可以自动过滤相同的ViewBinder)
private Set&ViewBinder& viewBinders = new HashSet&ViewBinder&();
5、与viewBinders 随之而来的一些常用方法有必要写一下(例如折叠所有表情面板、获取当前哪个表情面板展开着等),代码如下:
* 添加ViewBinder
* @param viewBinder
public void setViewBinders(ViewBinder... viewBinder) {
for (ViewBinder vBinder : viewBinder) {
if (vBinder != null) {
viewBinders.add(vBinder);
vBinder.trigger.setTag(vBinder);
vBinder.trigger.setOnClickListener(this);
updateAllPanelHeight(sKeyBoardHeight);
* 重置所有面板
* @param dstPanel
重置操作例外的对象
private void resetOtherPanels(View dstPanel) {
for (ViewBinder vBinder : viewBinders) {
if (dstPanel != vBinder.panel) {
vBinder.panel.setVisibility(View.GONE);
* 关闭所有的面板
public void closeAllPanels() {
resetOtherPanels(null);
//重置面板后,需要将输入法弹出模式一并重置
updateSoftInputMethod(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
* 判断是否存在正在显示的面板
* @return true表示存在,false表示不存在
public boolean hasPanelShowing() {
for (ViewBinder viewBinder : viewBinders) {
if (viewBinder.panel.isShown()) {
* 更新所有面板的高度
* @param height
具体高度(单位px)
private void updateAllPanelHeight(int height) {
for (ViewBinder vBinder : viewBinders) {
ViewGroup.LayoutParams params = vBinder.panel.getLayoutParams();
params.height =
vBinder.panel.setLayoutParams(params);
6、通过监听Layout的变化来判断输入法是否已经展开。代码如下:
* 设置View树监听,以便判断键盘是否弹出。&br/&
* 【只有当Activity的windowSoftInputMode设置为adjustResize时才有效!所以我们要处理adjustNoting(不会引起Layout的形变)的情况键盘监听(后文会提到)】
private void detectKeyboard() {
final View activityRootView = ((ViewGroup) activity
.findViewById(android.R.id.content)).getChildAt(0);
if (activityRootView != null) {
ViewTreeObserver observer = activityRootView.getViewTreeObserver();
if (observer == null) {
observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
public void onGlobalLayout() {
final Rect r = new Rect();
activityRootView.getWindowVisibleDisplayFrame(r);
int heightDiff = DisplayUtils.getScreenHeight()
- (r.bottom - r.top);
//Layout形变超过键盘的一半表示键盘已经展开了
boolean show = heightDiff &= sKeyBoardHeight / 2;
setKeyboardShowing(show);// 设置键盘是否展开状态
if (show) {
int keyboardHeight = heightDiff
- DisplayUtils.getStatusBarHeight();
// 设置新的键盘高度
setKeyBoardHeight(keyboardHeight);
7、完成键盘的显示/隐藏和动态控制输入法弹出模式的常用方法。代码如下:
* 隐藏输入法
* @param currentFocusView
当前焦点view
public static void hideKeyboard(View currentFocusView) {
if (currentFocusView != null) {
IBinder token = currentFocusView.getWindowToken();
if (token != null) {
InputMethodManager im = (InputMethodManager) currentFocusView
.getContext().getSystemService(
Context.INPUT_METHOD_SERVICE);
im.hideSoftInputFromWindow(token, 0);
* 更新输入法的弹出模式(注意这是静态方法,可以直接当做工具方法使用)
* @param activity 对应的Activity
* @param softInputMode
键盘弹出模式:WindowManager.LayoutParams的参数有:&br/&
&&&&可见状态: SOFT_INPUT_STATE_UNSPECIFIED,
SOFT_INPUT_STATE_UNCHANGED, SOFT_INPUT_STATE_HIDDEN,
SOFT_INPUT_STATE_ALWAYS_VISIBLE, or SOFT_INPUT_STATE_VISIBLE.&br/&
&&&&适配选项有: SOFT_INPUT_ADJUST_UNSPECIFIED,
SOFT_INPUT_ADJUST_RESIZE, or SOFT_INPUT_ADJUST_PAN.
public static void updateSoftInputMethod(Activity activity,
int softInputMode) {
if (!activity.isFinishing()) {
WindowManager.LayoutParams params = activity.getWindow()
.getAttributes();
if (params.softInputMode != softInputMode) {
params.softInputMode = softInputM
activity.getWindow().setAttributes(params);
* 更新输入法的弹出模式(遇上面的静态方法的区别是直接使用的是绑定的activity对象)
* @param softInputMode
键盘弹出模式:WindowManager.LayoutParams的参数有:&br/&
&&&&可见状态: SOFT_INPUT_STATE_UNSPECIFIED,
SOFT_INPUT_STATE_UNCHANGED, SOFT_INPUT_STATE_HIDDEN,
SOFT_INPUT_STATE_ALWAYS_VISIBLE, or SOFT_INPUT_STATE_VISIBLE.&br/&
&&&&适配选项有: SOFT_INPUT_ADJUST_UNSPECIFIED,
SOFT_INPUT_ADJUST_RESIZE, or SOFT_INPUT_ADJUST_PAN.
public void updateSoftInputMethod(int softInputMode) {
updateSoftInputMethod(activity, softInputMode);
8、在构造方法中将这些组件都初始化,并做相关设置,代码如下:
* 构造函数
* @param activity
需要处理输入法的当前的Activity
public InputMethodUtils(Activity activity) {
this.activity =
DisplayUtils.init(activity);
// 默认键盘高度为267dp
setKeyBoardHeight(DisplayUtils.dp2px(267));
updateSoftInputMethod(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
detectKeyboard();// 监听View树变化,以便监听键盘是否弹出
enableCloseKeyboardOnTouchOutside(activity);
1. 设置键盘的高度
3. @param keyBoardHeight
键盘的高度(px单位)
private void setKeyBoardHeight(int keyBoardHeight) {
sKeyBoardHeight = keyBoardH
updateAllPanelHeight(keyBoardHeight);
5. 开启点击外部关闭键盘的功能(其实就是将遮罩View添加到Decorview)
7. @param activity
private void enableCloseKeyboardOnTouchOutside(Activity activity) {
CloseKeyboardOnOutsideContainer frameLayout = new CloseKeyboardOnOutsideContainer(
activity);
activity.addContentView(frameLayout, new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
【突然有事,先写到这,等会来完善…】回来了,接着写。
上面的代码基本完成需求,需要重点说的是如何检测键盘弹出/隐藏状态的问题(有人可能会说用InputMethodManager.isActive()啊,恩…反正我用有这个方法问题,他永远都给我返回true),下面简单介绍下如何实现的键盘的弹出和隐藏状态的检测。
1、如果当前输入法是adjustResize模式,那么我们直接可以用Layout的形变监听即可实现,也就是之前detectKeyboard()实现的代码。
2、如果当前输入法是adjustNoting模式,这个就有点难处理了,因为没有形变可以监听。我的实现方式是:通过遮罩View判断ACTION_DOWN的坐标,如果该坐标落在输入框内(就是用户点击了输入框,此时系统将会弹出输入框),那么我们就可以认为键盘为弹出模式。代码体现在CloseKeyboardOnOutsideContainer的dispatchTouchEvent()方法中。
到此,开发就告一段落了。按照惯例,完整代码如下:
* 解决输入法与表情面板之间切换时抖动冲突的控制辅助工具类(能做到将面板与输入法之间平滑切换).另外,具备点击空白处自动收起面板和输入法的功能.&br/&
* 使用方法介绍如下:
* &font color= 'red'&申明:【此类中,我们将表情面板选项、显示表情面板的按钮、表情面板按钮的点击事件
* 作为一个整体,包装在ViewBinder类中(点击表情面板按钮时,将会展开表情面 板 ) 】&/font& &br/&
* 因此,第一步,我们将需要操作的表情面板、按钮、事件绑定在一起,创建ViewBinder类(可以是很多个)代码示例如下:&br/&
* //如果不想监听按钮点击事件,之间将listener参数替换成null即可&br/&
* ViewBinder viewBinder1 = new ViewBinder(btn_1,panel1,listener1);&br/&
* ViewBinder viewBinder2 = new ViewBinder(btn_2,panel2,listener2);&br/&
* ...&br/&
* 第二步:创建InputMethodUtils类&br/&
* InputMethodUtils inputMethodUtils = new InputMethodUtils(this);&br/&
* 第三部:将ViewBinder传递给InputMethodUtils。&br/&
* inputMethodUtils.setViewBinders(viewBinder1,viewBinder2);//这个参数为动态参数,
* 支持多个参数传递进来
* 本类还提供两个常用的工具方法:&br/&
* InputMethodUtils.hideKeyboard();//用于隐藏输入法&br/&
* InputMethodUtils.updateSoftInputMethod();//用于将当前Activity的输入法模式切换成指定的输入法模式
* @author 李长军
public class InputMethodUtils implements View.OnClickListener {
// 键盘是否展开的标志位
private boolean sIsKeyboardS
// 键盘高度
private int sKeyBoardHeight = 0;
// 绑定的Activity
// 触发与面板对象集合
private Set&ViewBinder& viewBinders = new HashSet&ViewBinder&();
* 构造函数
* @param activity
需要处理输入法的当前的Activity
public InputMethodUtils(Activity activity) {
this.activity =
DisplayUtils.init(activity);
// 默认键盘高度为267dp
setKeyBoardHeight(DisplayUtils.dp2px(267));
updateSoftInputMethod(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
detectKeyboard();// 监听View树变化,以便监听键盘是否弹出
enableCloseKeyboardOnTouchOutside(activity);
* 添加ViewBinder
* @param viewBinder
public void setViewBinders(ViewBinder... viewBinder) {
for (ViewBinder vBinder : viewBinder) {
if (vBinder != null) {
viewBinders.add(vBinder);
vBinder.trigger.setTag(vBinder);
vBinder.trigger.setOnClickListener(this);
updateAllPanelHeight(sKeyBoardHeight);
public void onClick(View v) {
ViewBinder viewBinder = (ViewBinder) v.getTag();
View panel = viewBinder.
resetOtherPanels(panel);// 重置所有面板
if (isKeyboardShowing()) {
updateSoftInputMethod(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING);
panel.setVisibility(View.VISIBLE);
hideKeyBordAndSetFlag(activity.getCurrentFocus());
} else if (panel.isShown()) {
updateSoftInputMethod(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
panel.setVisibility(View.GONE);
updateSoftInputMethod(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
panel.setVisibility(View.VISIBLE);
if (viewBinder.listener != null) {
viewBinder.listener.onClick(v);
* 获取键盘是否弹出
* @return true表示弹出
public boolean isKeyboardShowing() {
return sIsKeyboardS
* 获取键盘的高度
* @return 键盘的高度(px单位)
public int getKeyBoardHeight() {
return sKeyBoardH
* 关闭所有的面板
public void closeAllPanels() {
resetOtherPanels(null);
updateSoftInputMethod(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
* 判断是否存在正在显示的面板
* @return true表示存在,false表示不存在
public boolean hasPanelShowing() {
for (ViewBinder viewBinder : viewBinders) {
if (viewBinder.panel.isShown()) {
* 更新输入法的弹出模式
* @param softInputMode
键盘弹出模式:WindowManager.LayoutParams的参数有:&br/&
&&&&可见状态: SOFT_INPUT_STATE_UNSPECIFIED,
SOFT_INPUT_STATE_UNCHANGED, SOFT_INPUT_STATE_HIDDEN,
SOFT_INPUT_STATE_ALWAYS_VISIBLE, or SOFT_INPUT_STATE_VISIBLE.&br/&
&&&&适配选项有: SOFT_INPUT_ADJUST_UNSPECIFIED,
SOFT_INPUT_ADJUST_RESIZE, or SOFT_INPUT_ADJUST_PAN.
public void updateSoftInputMethod(int softInputMode) {
updateSoftInputMethod(activity, softInputMode);
* 隐藏输入法
* @param currentFocusView
当前焦点view
public static void hideKeyboard(View currentFocusView) {
if (currentFocusView != null) {
IBinder token = currentFocusView.getWindowToken();
if (token != null) {
InputMethodManager im = (InputMethodManager) currentFocusView
.getContext().getSystemService(
Context.INPUT_METHOD_SERVICE);
im.hideSoftInputFromWindow(token, 0);
* 更新输入法的弹出模式
* @param activity
* @param softInputMode
键盘弹出模式:WindowManager.LayoutParams的参数有:&br/&
&&&&可见状态: SOFT_INPUT_STATE_UNSPECIFIED,
SOFT_INPUT_STATE_UNCHANGED, SOFT_INPUT_STATE_HIDDEN,
SOFT_INPUT_STATE_ALWAYS_VISIBLE, or SOFT_INPUT_STATE_VISIBLE.&br/&
&&&&适配选项有: SOFT_INPUT_ADJUST_UNSPECIFIED,
SOFT_INPUT_ADJUST_RESIZE, or SOFT_INPUT_ADJUST_PAN.
public static void updateSoftInputMethod(Activity activity,
int softInputMode) {
if (!activity.isFinishing()) {
WindowManager.LayoutParams params = activity.getWindow()
.getAttributes();
if (params.softInputMode != softInputMode) {
params.softInputMode = softInputM
activity.getWindow().setAttributes(params);
* 隐藏键盘,并维护显示或不显示的逻辑
* @param currentFocusView
当前的焦点View
private void hideKeyBordAndSetFlag(View currentFocusView) {
sIsKeyboardShowing =
hideKeyboard(currentFocusView);
* 重置所有面板
private void resetOtherPanels(View dstPanel) {
for (ViewBinder vBinder : viewBinders) {
if (dstPanel != vBinder.panel) {
vBinder.panel.setVisibility(View.GONE);
* 更新所有面板的高度
* @param height
private void updateAllPanelHeight(int height) {
for (ViewBinder vBinder : viewBinders) {
ViewGroup.LayoutParams params = vBinder.panel.getLayoutParams();
params.height =
vBinder.panel.setLayoutParams(params);
* 设置键盘弹出与否状态
* @param show
true表示弹出,false表示未弹出
private void setKeyboardShowing(boolean show) {
sIsKeyboardShowing =
if (show) {
resetOtherPanels(null);
updateSoftInputMethod(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
* 设置键盘的高度
* @param keyBoardHeight
键盘的高度(px单位)
private void setKeyBoardHeight(int keyBoardHeight) {
sKeyBoardHeight = keyBoardH
updateAllPanelHeight(keyBoardHeight);
* 是否点击软键盘和输入法外面区域
* @param activity
当前activity
* @param touchY
点击y坐标(不包括statusBar的高度)
private boolean isTouchKeyboardOutside(int touchY) {
View foucusView = activity.getCurrentFocus();
if (foucusView == null) {
int[] location = new int[2];
foucusView.getLocationOnScreen(location);
int editY = location[1] - DisplayUtils.getStatusBarHeight();
int offset = touchY - editY;
if (offset & 0 && offset & foucusView.getMeasuredHeight()) {
* 是否点击的是当前焦点View的范围
* @param x
* @param y
y方向坐标(不包括statusBar的高度)
* @return true表示点击的焦点View,false反之
private boolean isTouchedFoucusView(int x, int y) {
View foucusView = activity.getCurrentFocus();
if (foucusView == null) {
int[] location = new int[2];
foucusView.getLocationOnScreen(location);
int foucusViewTop = location[1] - DisplayUtils.getStatusBarHeight();
int offsetY = y - foucusViewT
if (offsetY & 0 && offsetY & foucusView.getMeasuredHeight()) {
int foucusViewLeft = location[0];
int foucusViewLength = foucusView.getWidth();
int offsetX = x - foucusViewL
if (offsetX &= 0 && offsetX &= foucusViewLength) {
* 开启点击外部关闭键盘的功能
* @param activity
private void enableCloseKeyboardOnTouchOutside(Activity activity) {
CloseKeyboardOnOutsideContainer frameLayout = new CloseKeyboardOnOutsideContainer(
activity);
activity.addContentView(frameLayout, new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
* 设置View树监听,以便判断键盘是否弹出。&br/&
* 【只有当Activity的windowSoftInputMode设置为adjustResize时才有效】
private void detectKeyboard() {
final View activityRootView = ((ViewGroup) activity
.findViewById(android.R.id.content)).getChildAt(0);
if (activityRootView != null) {
ViewTreeObserver observer = activityRootView.getViewTreeObserver();
if (observer == null) {
observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
public void onGlobalLayout() {
final Rect r = new Rect();
activityRootView.getWindowVisibleDisplayFrame(r);
int heightDiff = DisplayUtils.getScreenHeight()
- (r.bottom - r.top);
boolean show = heightDiff &= sKeyBoardHeight / 2;
setKeyboardShowing(show);// 设置键盘是否展开状态
if (show) {
int keyboardHeight = heightDiff
- DisplayUtils.getStatusBarHeight();
// 设置新的键盘高度
setKeyBoardHeight(keyboardHeight);
* ViewBinder的触发按钮点击的监听器
* @author 李长军
public static interface OnTriggerClickListener {
* @param v
public void onClick(View v);
* 用于控制点击某个按钮显示或者隐藏“表情面板”的绑定bean对象。&br/&
* 例如:我想点击“表情”按钮显示“表情面板”,我就可以这样做:&br/&
* ViewBinder viewBinder = new ViewBinder(btn_emotion,emotionPanel);&br/&
* 这样就创建出了一个ViewBinder对象&br/&
* &font color='red'&【注意事项,使用此类时,千万不要使用trigger的setOnClickListener来监听事件(
* 使用OnTriggerClickListener来代替),也不要使用setTag来设置Tag,否则会导致使用异常】&/font&
* @author 李长军
public static class ViewBinder {
private OnTriggerClickL
* 创建ViewBinder对象&br/&
* 例如:我想点击“表情”按钮显示“表情面板”,我就可以这样做:&br/&
* ViewBinder viewBinder = new
* ViewBinder(btn_emotion,emotionPanel,listener);&br/&
* 这样就创建出了一个ViewBinder对象
* @param trigger
* @param panel
点击触发对象需要显示/隐藏的面板对象
* @param listener
Trigger点击的监听器(千万不要使用setOnClickListener,否则会覆盖本工具类的监听器)
public ViewBinder(View trigger, View panel,
OnTriggerClickListener listener) {
this.trigger =
this.panel =
this.listener =
trigger.setClickable(true);
public boolean equals(Object obj) {
if (this == obj)
if (obj == null)
if (getClass() != obj.getClass())
ViewBinder other = (ViewBinder)
if (panel == null) {
if (other.panel != null)
} else if (!panel.equals(other.panel))
if (trigger == null) {
if (other.trigger != null)
} else if (!trigger.equals(other.trigger))
public OnTriggerClickListener getListener() {
public void setListener(OnTriggerClickListener listener) {
this.listener =
public View getTrigger() {
public void setTrigger(View trigger) {
this.trigger =
public View getPanel() {
public void setPanel(View panel) {
this.panel =
* 点击软键盘区域以外自动关闭软键盘的遮罩View
* @author 李长军
private class CloseKeyboardOnOutsideContainer extends FrameLayout {
public CloseKeyboardOnOutsideContainer(Context context) {
this(context, null);
public CloseKeyboardOnOutsideContainer(Context context,
AttributeSet attrs) {
this(context, attrs, 0);
public CloseKeyboardOnOutsideContainer(Context context,
AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
public boolean dispatchTouchEvent(MotionEvent event) {
boolean isKeyboardShowing = isKeyboardShowing();
boolean isEmotionPanelShowing = hasPanelShowing();
if ((isKeyboardShowing || isEmotionPanelShowing)
&& event.getAction() == MotionEvent.ACTION_DOWN) {
int touchY = (int) (event.getY());
int touchX = (int) (event.getX());
if (isTouchKeyboardOutside(touchY)) {
if (isKeyboardShowing) {
hideKeyBordAndSetFlag(activity.getCurrentFocus());
if (isEmotionPanelShowing) {
closeAllPanels();
if (isTouchedFoucusView(touchX, touchY)) {
// 如果点击的是输入框,那么延时折叠表情面板
postDelayed(new Runnable() {
public void run() {
setKeyboardShowing(true);
return super.onTouchEvent(event);
* 屏幕参数的辅助工具类。例如:获取屏幕高度,宽度,statusBar的高度,px和dp互相转换等
* 【注意,使用之前一定要初始化!一次初始化就OK(建议APP启动时进行初始化)。 初始化代码 DisplayUtils.init(context)】
* @author 李长军
private static class DisplayUtils {
// 四舍五入的偏移值
private static final float ROUND_CEIL = 0.5f;
// 屏幕矩阵对象
private static DisplayMetrics sDisplayM
// 资源对象(用于获取屏幕矩阵)
private static Resources sR
// statusBar的高度(由于这里获取statusBar的高度使用的反射,比较耗时,所以用变量记录)
private static int statusBarHeight = -1;
* 初始化操作
* @param context
context上下文对象
public static void init(Context context) {
sDisplayMetrics = context.getResources().getDisplayMetrics();
sResources = context.getResources();
* 获取屏幕高度 单位:像素
* @return 屏幕高度
public static int getScreenHeight() {
return sDisplayMetrics.heightP
* 获取屏幕宽度 单位:像素
* @return 屏幕宽度
public static float getDensity() {
return sDisplayMetrics.
* dp 转 px
* @param dp
* @return 转换后的像素值
public static int dp2px(int dp) {
return (int) (dp * getDensity() + ROUND_CEIL);
* 获取状态栏高度
* @return 状态栏高度
public static int getStatusBarHeight() {
// 如果之前计算过,直接使用上次的计算结果
if (statusBarHeight == -1) {
final int defaultHeightInDp = 19;// statusBar默认19dp的高度
statusBarHeight = DisplayUtils.dp2px(defaultHeightInDp);
Class&?& c = Class.forName("com.android.internal.R$dimen");
Object obj = c.newInstance();
Field field = c.getField("status_bar_height");
statusBarHeight = sResources.getDimensionPixelSize(Integer
.parseInt(field.get(obj).toString()));
} catch (Exception e) {
e.printStackTrace();
return statusBarH
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具

我要回帖

更多关于 什么输入法表情最多 的文章

 

随机推荐