最近在做弹幕的功能,弹幕功能的实现是使用的DanmakuFlameMaster。这篇文章主要是分享发射弹幕的dialog的具体实现以及遇到的问题。
实现的效果如下:
现在就开始分享具体的代码实现:
问题一:点击某个按键发射弹幕,需要弹出EditText输入框,并且要不挤压布局。
最原始的思路是,让带有EditText控件的View浮在播放器view的上层。整体布局是一个FrameLayout。多次试验之后,发现每当EditText出现的时候,总是会把播放器的View向上挤压,视频播放的窗口会受到影响。效果如下:
后来经过大神指点,只要把这个View做成Dialog的样式就可以不会影响布局了。
dialog的View布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ll_send"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#F3F6F6"
android:gravity="center_vertical"
android:orientation="horizontal">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginBottom="7dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginTop="7dp"
android:layout_weight="1"
android:background="@drawable/edit_bg"
android:gravity="center_vertical"
android:orientation="horizontal">
<EditText
android:id="@+id/et_keywored"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@null"
android:hint="发送弹幕一起high!"
android:imeOptions="flagNoExtractUi"
android:maxLength="11"
android:maxLines="1"
android:paddingBottom="7dp"
android:paddingLeft="14dp"
android:paddingTop="7dp"
android:textColor="#898989"
android:textSize="16sp" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="7dp"
android:src="@drawable/iv_dm_pen" />
<TextView
android:id="@+id/tv_textcount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="7dp"
android:layout_marginRight="14dp"
android:text="10"
android:textColor="#898989"
android:textSize="20sp" />
</LinearLayout>
<Button
android:id="@+id/btn_sub"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="14dp"
android:background="@drawable/chat_list_button_btn_send_n"
android:text="发射"
android:textColor="#FFFFFF"
android:textSize="14sp" />
</LinearLayout>
EditText有这样一个属性 android:imeOptions=”flagNoExtractUi”
是控制使软键盘不全屏显示,只占用一部分屏幕。如果不设置,edittext会全屏显示。
具体的效果是参考的爱奇艺app。
问题二:
在dialog弹出的时候,输入法不能自动弹出来。
在网上查找了很多资料
1)显示输入法
inputManager.toggleSoftInput(InputMethodManager.SHOW_FORCED,0);
2)隐藏输入法
inputManager.toggleSoftInput(InputMethodManager.SHOW_FORCED,0);
没错显示和隐藏是一样的代码,成对使用就可以了。
但是遇到了问题,在dialog显示出来的时候,点击dialog外缘区域需要隐藏掉dialog和输入法。
监听的实现是这样的:
dialog.setCanceledOnTouchOutside(true);
dialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(final DialogInterface dialog) {
inputManager.toggleSoftInput(InputMethodManager.SHOW_FORCED,0);
}
}
);
3)遇到的问题
输入法不仅仅能在点击dialog外缘的时候隐藏,而它也自带一个隐藏的按键,如下图
点击这个按键的时候,输入法就自己隐藏了。
动作:第一步 点击按钮自动弹出dialog 弹出输入法
第二步 点击输入法自带的下箭头的按键隐藏输入法
第三步 点击dialog 外缘,隐藏dialog。这个时候,你会发现一个问题,本来隐藏的键盘又自动弹出来了!
我的理解是:点击输入法自带的隐藏按键,更改了系统判断的键盘显示隐藏的标识符。由于上面的代码, 弹出和隐藏都是同一段代码,当键盘处于隐藏状态的时候,又调用了一次代码,键盘就自动显示出来了。
4)寻求解决方法 思路就是判断键盘的显示和隐藏的状态,如果键盘处于隐藏状态就不调用这个代码
inputManager.toggleSoftInput(InputMethodManager.SHOW_FORCED,0);
各种百度 google,发现大家监听软键盘是否隐藏的方法 基本是建立在一个认识上:
有一个view,如果键盘显示的话,应该会挤压布局,布局的高度会发生变化,通过监听这个高度是否改变来判断键盘是否显示。问题来了,我们的dialog形式的输入框,键盘弹出的时候,并不会挤压布局,他们提供的方法无效。
。。。。。。各种纠结。。。。。。。
5)最终的解决方法
et_keywored.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
et_keywored.post(new Runnable() {
@Override
public void run() {
InputMethodManager imm = (InputMethodManager) MainActivity.this.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, 0);
//自动弹出
try {
Thread.sleep(40);
} catch (InterruptedException e) {
}
}
});
}
}
}
);
用post() 和Thread.sleep()做了一个延时,让界面刷新不是那么快,键盘就能顺利的弹出。
隐藏键盘的方法:
InputMethodManager imm = (InputMethodManager) MainActivity.this.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, InputMethodManager.HIDE_NOT_ALWAYS);
测试小米3和普通的手机不一样,键盘隐藏的时候 也需要做一个延时:
et_keywored.post(new Runnable() {
@Override
public void run() {
InputMethodManager imm = (InputMethodManager) MainActivity.this.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, InputMethodManager.HIDE_NOT_ALWAYS);
try {
Thread.sleep(100);
} catch (Exception e) {
}
}
});
问题三:dialog样式的调整问题:
最原始的效果如下:
可以看到输入框下边缘和输入法紧紧的挨着,显示效果并不好
//设置展示范围
WindowManager m = getWindowManager();
Display d = m.getDefaultDisplay(); //为获取屏幕宽、高
int width = d.getWidth();
dialog.getWindow().setLayout(width, 120); //设置生效
dialog.getWindow().setGravity(Gravity.BOTTOM);
因为设置了dialog 的高度为120px,所以不能显示padding的区域。
后来更改为
dialog.getWindow().setLayout((int) screenWith, WindowManager.LayoutParams.WRAP_CONTENT); //设置生效
高度自适应。
查看源码
/**
* Special value for the height or width requested by a View.
* WRAP_CONTENT means that the view wants to be just large enough to fit
* its own internal content, taking its own padding into account.
*/
public static final int WRAP_CONTENT = -2;
wrap_content 包含了自身view的padding。所以如果要显示边距的话,设置margin是不行的。
可以加我微信好友,进技术讨论群。