接着上一篇的评论点赞弹框之后,这次来说说微信的评论输入框,点击屏幕外部评论框和键盘消失,滑动列表时输入框和键盘也要消失,这里不是说一定要舔微信啥的,只是单纯从技术角度出发,分析原理和实现,解决我们自己的需求.

实现的效果图如下:(软键盘在评论框下面)

1.布局文件main.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"><LinearLayoutandroid:id="@+id/ll_scroll"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><TextViewandroid:id="@+id/tv_city"android:layout_width="match_parent"android:layout_height="wrap_content"tools:text="城市名称"android:layout_gravity="center"android:layout_margin="5dp"android:gravity="center"/><androidx.recyclerview.widget.RecyclerViewandroid:id="@+id/recyclerView"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1" /></LinearLayout><LinearLayoutandroid:id="@+id/ll_comment"android:layout_width="match_parent"android:layout_height="45dp"android:layout_gravity="bottom"android:background="#f6f6f6"android:elevation="3dp"android:gravity="center_vertical"android:orientation="horizontal"android:visibility="gone"><EditTextandroid:id="@+id/et_comment"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_centerVertical="true"android:layout_marginLeft="15dp"android:layout_marginTop="6dp"android:layout_marginRight="7dp"android:layout_marginBottom="6dp"android:layout_weight="1"android:background="@drawable/shape_comment_bg"android:ellipsize="end"android:hint="说点什么"android:maxLength="300"android:paddingLeft="10dp"android:singleLine="true"android:textColorHint="#a2a2a2"android:textSize="13sp" /><TextViewandroid:id="@+id/tv_send_comment"android:layout_width="60dp"android:layout_height="30dp"android:layout_marginLeft="5dp"android:layout_marginRight="5dp"android:background="@drawable/shape_comment"android:gravity="center"android:paddingLeft="10dp"android:paddingTop="5dp"android:paddingRight="10dp"android:paddingBottom="5dp"android:text="发送"android:textColor="#fff"android:textSize="14sp" /></LinearLayout>
</FrameLayout>

2.MainActivity代码:

/*** @作者: njb* @时间: 2019/7/22 10:53* @描述: 仿微信朋友圈文本显示全文与收起*/
public class MainActivity extends AppCompatActivity implements CircleAdapter.MyClickListener, View.OnClickListener {private RecyclerView recyclerView;private CircleAdapter circleAdapter;private String content = "茫茫的长白大山,浩瀚的原始森林,大山脚下,原始森林环抱中散落着几十户人家的" +"一个小山村,茅草房,对面炕,烟筒立在屋后边。在村东头有一个独立的房子,那就是青年点," +"窗前有一道小溪流过。学子在这里吃饭,由这里出发每天随社员去地里干活。干的活要么上山伐" +"树,抬树,要么砍柳树毛子开荒种地。在山里,可听那吆呵声:“顺山倒了!”放树谨防回头棒!" +"树上的枯枝打到别的树上再蹦回来,这回头棒打人最厉害。";private List<String> strings;private LikePopupWindow likePopupWindow;private int page = 1;private EditText etComment;private LinearLayout llComment;private TextView tvSend;private LinearLayout llScroll;private int screenHeight;private int editTextBodyHeight;private int currentKeyboardH;private int selectCommentItemOffset;private int commentPosition;protected final String TAG = this.getClass().getSimpleName();CompositeDisposable compositeDisposable;private TextView tvCity;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initViews();initData();initAdapter();setListener();initRxBus();}private void initRxBus() {compositeDisposable = new CompositeDisposable();RxBus.getInstance().toObservable(WeatherEvent.class).subscribe(new Observer<WeatherEvent>() {@Overridepublic void onSubscribe(Disposable d) {compositeDisposable.add(d);}@Overridepublic void onNext(WeatherEvent weatherEvent) {Log.e("weather", weatherEvent.getTemperature()+"-**-"+weatherEvent.getCityName());tvCity.setText(String.format("%s %s", weatherEvent.getCityName(),weatherEvent.getTemperature()));}@Overridepublic void onError(Throwable e) {}@Overridepublic void onComplete() {}});}private void setListener() {tvSend.setOnClickListener(this);}private void setViewTreeObserver() {final ViewTreeObserver swipeRefreshLayoutVTO = llScroll.getViewTreeObserver();swipeRefreshLayoutVTO.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {@Overridepublic void onGlobalLayout() {Rect r = new Rect();llScroll.getWindowVisibleDisplayFrame(r);int statusBarH = Utils.getStatusBarHeight();//状态栏高度int screenH = llScroll.getRootView().getHeight();if (r.top != statusBarH) {//在这个demo中r.top代表的是状态栏高度,在沉浸式状态栏时r.top=0,通过getStatusBarHeight获取状态栏高度r.top = statusBarH;}int keyboardH = screenH - (r.bottom - r.top);Log.d(TAG, "screenH= " + screenH + " &keyboardH = " + keyboardH + " &r.bottom=" + r.bottom + " &top=" + r.top + " &statusBarH=" + statusBarH);if (keyboardH == currentKeyboardH) {//有变化时才处理,否则会陷入死循环return;}currentKeyboardH = keyboardH;screenHeight = screenH;//应用屏幕的高度editTextBodyHeight = llComment.getHeight();if (keyboardH < 150) {//说明是隐藏键盘的情况MainActivity.this.updateEditTextBodyVisible(View.GONE);return;}//偏移listview}});}/*** 初始化控件*/private void initViews() {recyclerView = findViewById(R.id.recyclerView);llComment = findViewById(R.id.ll_comment);etComment = findViewById(R.id.et_comment);tvSend = findViewById(R.id.tv_send_comment);llScroll = findViewById(R.id.ll_scroll);tvCity = findViewById(R.id.tv_city);}/*** 初始化数据** @param*/private void initData() {strings = new ArrayList<>();for (int i = 0; i < 14; i++) {strings.add(content);}}/*** 设置adapter*/private void initAdapter() {circleAdapter = new CircleAdapter(this, strings, this);recyclerView.setLayoutManager(new LinearLayoutManager(this));recyclerView.addItemDecoration(new SpaceDecoration(this));recyclerView.setAdapter(circleAdapter);recyclerView.setOnTouchListener(new View.OnTouchListener() {@Overridepublic boolean onTouch(View view, MotionEvent motionEvent) {if (llComment.getVisibility() == View.VISIBLE) {updateEditTextBodyVisible(View.GONE);return true;}return false;}});}@Overridepublic void onClick(int position, View v) {if (likePopupWindow == null) {likePopupWindow = new LikePopupWindow(this, 0);}likePopupWindow.setOnPraiseOrCommentClickListener(new OnPraiseOrCommentClickListener() {@Overridepublic void onPraiseClick(int position) {Toast.makeText(MainActivity.this, "点赞成功", Toast.LENGTH_SHORT).show();likePopupWindow.dismiss();Intent intent = new Intent(MainActivity.this, AddCityActivity.class);startActivity(intent);}@Overridepublic void onCommentClick(int position) {llComment.setVisibility(View.VISIBLE);etComment.requestFocus();CommonUtils.showSoftInput(MainActivity.this, llComment);likePopupWindow.dismiss();}@Overridepublic void onClickFrendCircleTopBg() {}@Overridepublic void onDeleteItem(String id, int position) {}}).setTextView(0).setCurrentPosition(position);if (likePopupWindow.isShowing()) {likePopupWindow.dismiss();} else {likePopupWindow.showPopupWindow(v);}}public void updateEditTextBodyVisible(int visibility) {llComment.setVisibility(visibility);if (View.VISIBLE == visibility) {llComment.requestFocus();//弹出键盘CommonUtils.showSoftInput(etComment.getContext(), etComment);} else if (View.GONE == visibility) {//隐藏键盘CommonUtils.hideSoftInput(etComment.getContext(), etComment);}}@Overridepublic void onClick(View view) {switch (view.getId()) {case R.id.tv_send_comment:if (TextUtils.isEmpty(etComment.getText().toString())) {Toast.makeText(MainActivity.this, "请输入评论内容", Toast.LENGTH_SHORT).show();return;}setViewTreeObserver();break;default:break;}}@Overrideprotected void onDestroy() {super.onDestroy();//取消订阅RxBus.rxBusUnbund(compositeDisposable);}
}

3.刚开始使用的是dispatchTouchEvent拦截事件

打断点调试发现点击屏幕外部时确实键盘和输入框都消失了,但是发现一个问题,输入文本内容后,只要一点击发送按钮,输入框和键盘就消失了,发送评论的接口都没有调用,以下是日志和断点截图:

4.dispatchTouchEvent事件分发原理:

dispatchTouchEvent函数在Activity,View 和ViewGroup中都有定义,并且处理的逻辑也是不同的。

Activity:
当发生点击事件后,最先响应的是Activity的dispatchTouchEvent()函数,Activity会把TouchEvent传给自身绑定的rootView(一般就是DecorView),由rootView进行处理。
如果TouchEvent一直没有消费掉,最后会调用Activity的onTouchEvent()函数来处理事件。

ViewGroup:
ViewGroup运行dispatchTouchEvent()函数时,首先会调用onInterceptTouchEvent()函数,这是个拦截函数,如果需要拦截子View的点击事件,可以在这里添加一些逻辑;默认返回值是false,此时会按照添加子View时的顺序将事件分发给各个子View,由各个子View处理事件;如果添加了拦截的逻辑,返回值为true的话,会给各个子View发送Action_Cancel指令,并且所有事件都变为已处理。
子View处理事件时逻辑类似,如果是ViewGroup则继续分发,如果是View的话,则执行View的逻辑。

View:
View处理事件时先看是否有onTouchListener,如果有的话,优先执行onTouchListener的onTouch函数,如果没有处理,则执行onTouchEvent函数。
ViewGroup本质也是View,子view都没消费事件的话,也会走View的逻辑。

当子view不想被拦截时可以通过requestDisallowInterceptTouchEvent(true)函数来阻止拦截。

由于Activity没有写onTouchListener事件,所以按照上面的事件分发原理,Activity不会拦截,点击屏幕外部时被消费了,输入评论内容后,点击发送按钮时也被消费了,所以dispatchTouchEvent拦截点击事件,这样肯定不行,于是看了下微信的效果,回想起事件分发原理,尝试了一下解决方法:

5.在recyclerview的触摸事件中处理onTouch事件,代码如下:

这时调试运行发现点击外部输入框和软键盘都消失了,发现这种方法是可行的。还有一个问题recyclerview滑动时也要消失,这又是一个问题,和同事讨论监听输入框的高度,参考资料后给出以下解决方法:

private void setViewTreeObserver() {final ViewTreeObserver swipeRefreshLayoutVTO = llScroll.getViewTreeObserver();swipeRefreshLayoutVTO.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {@Overridepublic void onGlobalLayout() {Rect r = new Rect();llScroll.getWindowVisibleDisplayFrame(r);int statusBarH = Utils.getStatusBarHeight();//状态栏高度int screenH = llScroll.getRootView().getHeight();if (r.top != statusBarH) {//在这个demo中r.top代表的是状态栏高度,在沉浸式状态栏时r.top=0,通过getStatusBarHeight获取状态栏高度r.top = statusBarH;}int keyboardH = screenH - (r.bottom - r.top);Log.d(TAG, "screenH= " + screenH + " &keyboardH = " + keyboardH + " &r.bottom=" + r.bottom + " &top=" + r.top + " &statusBarH=" + statusBarH);if (keyboardH == currentKeyboardH) {//有变化时才处理,否则会陷入死循环return;}currentKeyboardH = keyboardH;screenHeight = screenH;//应用屏幕的高度editTextBodyHeight = llComment.getHeight();if (keyboardH < 150) {//说明是隐藏键盘的情况MainActivity.this.updateEditTextBodyVisible(View.GONE);return;}}});
}

以上就是解决点击屏幕外部和列表滑动时隐藏输入框和键盘的解决方法,如果小伙伴们有更好的方法可以留言一起交流成长.

项目的完整地址如下:

ExpandTextView: 实现仿微信朋友圈列表多类型布局,图片点击放大、保存,包含点赞、评论、消息提醒、视频播放等功能

Android仿微信朋友圈3评论输入框及点击外部和列表滑动时隐藏输入框和键盘解决方法相关推荐

  1. Android自定义弹窗模仿微信,Android 仿微信朋友圈点赞和评论弹出框功能

    本文简单模仿微信朋友圈的点赞和评论弹出框,布局等细节请忽略,着重实现弹出框.发评论,及弹出位置的控制. 1. 微信弹出框 微信朋友圈的点赞和评论功能,有2个组成部分: 点击左下角的"更多&q ...

  2. android 仿微信朋友圈 评论,2020年android 仿微信朋友圈 评论

    2020年android 仿微信朋友圈 评论 1.如果有人问我:那些艰难的岁月你是怎么熬过来的?我想我只有一句话回答:我有一种强大的精神力量支撑着我,这种力量名字叫"想死又不敢" ...

  3. Android仿微信朋友圈发图片和文字

    Android仿微信朋友圈发图片和文字的一个开源项目,其在github上的项目主页是:https://github.com/zhangphil/FangWeiXinPengYouQuanFaTuPia ...

  4. Android仿微信朋友圈4实现评论动态时输入框和软键盘自动定位到内容下面

    最近做完朋友圈功能后,测试提出一个功能优化,在某些发布的动态下评论时软键盘和输入框遮当内容了,这个用户体验感觉不是很好,于是根据今日头条和其他热门的App评论时软键盘和输入框都是在内容下面.Scrol ...

  5. Android仿微信朋友圈2自定义点赞评论弹框

    最近在做类似微信朋友圈点赞评论的功能,有个点赞评论弹框交互,感觉效果很好,点击评论按钮弹框从按钮左边弹出,遇到了3个问题(弹出动画不对.弹框布局没有适配.弹出的位置显示不对),动画和布局好解决,弹出的 ...

  6. Android仿微信朋友圈7实现点赞功能

    前言: 之前一直有朋友问我点赞怎么实现?今天趁着休息时间整理出来,其实点赞的功能和用户评论差不多,都是显示一个用户列表,只不过评论有评论内容和回复评论功能.实现点赞的思路如下: 1.当用户点击点赞按钮 ...

  7. Android仿微信朋友圈5实现朋友圈列表

    前言: 微信朋友圈网上有很多开源的例子,本文是自己手写,之前的几篇都是单个功能,感觉很零散,这次放出完整的点赞评论和朋友圈列表功能,大家有兴趣可以看一下 1.定义四种item类型,可以按后台接口自行定 ...

  8. Android仿微信朋友圈6之实现消息提醒功能

    之前有朋友问我消息提醒咋实现,我一直没有整理出来,今天就放出来.微信朋友圈的消息提醒就是收到朋友的评论后背景底部显示消息条数和评论用户,顶部是一张相册背景和当前用户昵称头像. 1.消息提醒的布局如下: ...

  9. Android 仿微信朋友圈添加图片

    github地址(欢迎下载Demo) https://github.com/zhouxu88/WXCircleAddPic 老习惯,先上图,着急用的朋友,直接带走Demo,先拿来用吧,毕竟老板催的紧, ...

最新文章

  1. 源码安装httpd2.4.4
  2. 8086汇编基础 push,pop指令执行时,sp怎么变
  3. php-fpm 找不到 php-cgi.sock 怎么办
  4. flink的scala版本的wordcount+flink没有输出结果的几种原因
  5. eclipse maven 项目发布到tomcat 报错 Failed to scan JAR [file:/C:/xxxxx.jar] from WEB-INF/lib
  6. 字节取消大小周,部分员工:心疼,每个月少拿 1W 块
  7. 利用blink+MQ实现流计算中的超时统计问题
  8. discuz x2.5 mysql_DiscuzMySQL 优化 - Discuz! X2.5 效率机制 - 1314学习网
  9. Datalogic 得利捷推出超级灵活且坚固可靠的PowerScan 9600 系列 庆祝公司成立50周年
  10. ORL、Yale等人脸数据库百度云链接
  11. ART中 MIR -- LIR -- 机器码 的流程
  12. pimple idiom C++
  13. 拿棱镜门黑客软件攻击“俄版百度”,不偷情报只想装大V,FBI们被抓包了
  14. 团队作业——团队项目Alpha版本发布
  15. Intent的用法(初步)
  16. linux rewind函数,fseek(),ftell()和rewind()函数的用法详解
  17. js获取本月初与月底的时间、获取前一天的时间。
  18. expresscache和primocache加速资料整理
  19. 产品机会:痛点,痒点,爽点
  20. house of grey

热门文章

  1. 7z.001....7z.002.....格式的分卷压缩包
  2. MySQL 错误代码提示
  3. 项目实训-在线考试系统06
  4. 谁动了我的奶酪[By tina]
  5. 汾曲名家相国孙,翊登枢铉继承恩。继承
  6. Ubunut中文网站
  7. 网页中插入优酷土豆视频并让它自适应的方法
  8. SaaS为啥要业务+IT一体化
  9. 看国外“大神”程序员高大上的电脑桌
  10. ojdbc14.jar的坑