Android 制作一个评论框

需求介绍

我们经常在各种社交软件中经常能够看见评论框这一功能,这种评论框是用户在点击了某个“评论”按钮之后,会弹出这样一个评论框以及键盘,在用户输入完成之后或者点击任意其他位置之后就会消失。

微信朋友圈

分析一下之后,这种评论框有着这样的需求:

  1. 点击之后弹出这样一个带有EditText的布局;
  2. 弹出键盘;
  3. 点击回车可以完成输入;
  4. 弹出之后点击其他位置,布局消失,键盘收回。

经过一番思考之后,我认为使用自定义Dialog是实现这样的功能的较好方法,具体思路:

  1. Dialog自己可以实现弹出布局、点击其他位置时自动消失;
  2. Dialog通过设置theme以及WindowManager管理窗口外观;
  3. 键盘弹出、收回可以通过InputMethodManager实现;
  4. 点击回车完成输入可以通过OnEditorActionListener实现。

自定义Dialog

在我看来,实现一个Dialog和实现一个Fragment或者Acitivity差不多是一回事。都是自写一个继承Dialog的子类,在其中设置XML文件以及绑定各种控件方法就可以了。

设置theme

由于根据效果图来看,这个Dialog要实现水平方向充满屏幕、重力方向向下两个效果实现。所以我们需要在theme中像这样设置。

1
2
3
4
5
6
7
<style name="editDialogStyle" parent="android:style/Theme.Dialog">
<item name="android:windowBackground">@color/white10</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowIsFloating">true</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:scrollHorizontally">true</item>
</style>

windowContentOverlay设置的是ContentOverlay的背景

设置WindowManager

1
2
3
4
5
Window dialogWindow = dialog.getWindow();
dialogWindow.setGravity(Gravity.BOTTOM);
WindowManager.LayoutParams params = dialogWindow.getAttributes();
params.width = WindowManager.LayoutParams.MATCH_PARENT;
dialogWindow.setAttributes(params);

这段代码的效果是显而易见的,但是要注意的是:这一段代码一定要在show方法之后使用,不然就会没有效果。

设置InputMethodManager

1
inputManager = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);

inputManager通过getSystemService来获得。

1
inputManager.toggleSoftInput(0, InputMethodManager.SHOW_FORCED);

这个方法是用来强制弹出键盘的,我们将其放在某个按钮的点击事件之中便可实现。要注意的是,这个方法最好要有一定的延时,否则效果可能会有点怪。

1
inputManager.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0);

这个方法是用来强制收回键盘,只需要把它放在Dialog的onStop回调方法之中。这样的话,就不用做其他的判断,可以根据Dialog自己的stop方法来解决。

设置OnEditorActionListener

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
editText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView textView, int i, KeyEvent keyEvent) {
if (i == EditorInfo.IME_ACTION_SEND
|| (keyEvent != null && keyEvent.getKeyCode() == KeyEvent.KEYCODE_ENTER)) {
if(textView.getText().length() == 0) {
tagText.setText(getResources().getString(R.string.self_defined));
}else {
tagText.setText(textView.getText().toString());
}
presenter.addTag(tagText.getText().toString());
dialog.dismiss();
return true;
}
return false;
}
});

这样便设置了相应的方法以及Dialog的关闭。返回值如果是true的话表示本次操作被处理了,false表示没有被处理,该咋样就咋样。

整个Dialog的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public class ReplyEditDialog extends Dialog {
@BindView(R.id.detail_edit_text_reply)
EditText editText;
private Context context;
private InputMethodManager inputManager;
public ReplyEditDialog(Context context) {
super(context, R.style.editDialogStyle);
this.context = context;
setContentView(R.layout.dialog_detail_reply);
View view = getWindow().getDecorView();
ButterKnife.bind(this, view);
inputManager = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
}
public void onEnter(String hint, TextView.OnEditorActionListener listener){
editText.setText("");
editText.setHint(hint);
editText.setOnEditorActionListener(listener);
editText.requestFocus();
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
inputManager.toggleSoftInput(0, InputMethodManager.SHOW_FORCED);
}
}, 100);
}
@Override
public void onStop(){
super.onStop();
inputManager.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0);
}
}

以上代码非常的通俗易懂,可以看到和任何一个Acitivity都差不多一回事。

实现效果

如图所示

可以看到,效果还是很成功的。借此我们可以做出很多其他的类似的效果,比如qq聊天发送表情的那一个框等效果,还需要继续不断探索!

Powered by Hexo and Hexo-theme-hiker

Copyright © 2013 - 2018 Alex's Blog All Rights Reserved.

Yifeng Tang hält Urheberrechtsansprüche.