最近在使用映客App的时候,发现IOS端和 android端房间内效果有一些的出入,android端明显少了右滑隐藏上方礼物区域,上下滑动切换房间的需求。于是我就寻思着能否在android上实现IOS端的效果(虽然映客android端没做)。
截图
要解决的问题:
1.点击 1 位置的按钮显示 EditText 的同时 **上层界面 **被键盘顶上去,但是 下层界面 (视频播放区域) 不被键盘往上顶
- 左滑效果实现
- 上下滑效果实现
关于问题 1
这里涉及到activity的 windowSoftInputMode 各种模式的使用
但是问题就出在这里,无论 windowSoftInputMode 设置成什么值(各个值的含义google一下会有一大推 传送门),上下两层都会被键盘弹出而往上顶,因为windowSoftInputMode是作用于整个 activity的 根布局的
寻思苦想出了2个解决方案
1.下层视频播放用一个 Activity,上层礼物消息等用 另一个 Activity,然后两个Activity设置不同的windowSoftInputMode,就可以实现1的效果.但是 这样会变得很 “庞大”和臃肿,真的一定需要两个Activity? 于是有了第二个方案
- 既然Activity内部的所以view都会随根布局被顶上去而跟着动,那就采用一个具有系统窗口属性的 DialogFragment来实现,DialogFragment有一个好处就是他是一个单独的窗口,不会随activity的被顶而被顶。于是设计一个Activity启动的时候 底层用一个 Fragment放视频播放的区域,上层用DialogFragment处理礼物各种的具体界面
界面分成移动的代码片段 Github
代码实现了只会移动上层,而下层保持状态的效果
但是接下来又会出现一个问题: 用户是需要点击某个按钮才会显示 EditText,然后弹出软键盘,在按系统返回键的时候会收起系统软键盘,在显示按钮同时隐藏 EditText,这个需求看起来貌似很简单,实现的时候就发现我们无法获取到系统 软键盘 显示/隐藏的监听
于是google了一堆解决方案 大致如下:
//监听软键盘的隐藏和显示
但是activity的配置必须是android:windowSoftInputMode="adjustResize"
但是此处的需求不能resize>>activity中的布局,在此需要设置 DialogFragment中Dialog 的 SoftInputMode 在
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
中设置
getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
// rootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {// }else {
// @Override
// public void onGlobalLayout() {
// int heightDiff = rootView.getRootView().getHeight() - rootView.getHeight();
// if (heightDiff > 100) { // 软键盘存在
// Log.e("onGlobalLayout","show");
// }else{
// Log.e("onGlobalLayout","gone");
// }
// }
// });
~~~二一个是自定义EditText 重写onKeyPreIme(intkeyCode,KeyEventevent)
方法
具体实现代码 CustomEditText.java 这个目前看来是最好的方法~~~
关于问题2
最初的想法是在DialogFragment中自定义根布局的ViewGroup,然后用 ViewDragHelper来处理滑动事件 来左右滑动 根布局。但是,实际操作起来也不是那么轻松。于是我又想到了一个更好的实现方案,毕竟少写code才是王道 --- 用ViewPager来实现滚动滑动不是很简单???
ViewPager 一共两页,左边一页为空白页,右边一页为真正的上层视图页,初始化的时候设置 viewPager.setCurrentItem(1);
很轻松就实现了想要的效果
具体代码见 主布局用viewpager做左滑效果
关于问题3
相当于显示是要在 DialogFragment中ViewPager的第二页实现上下滑动的效果
要想实现上下滚动,无非就是各种滚动的View的使用,ListView ? RecyclerView ? ScrollView? 但是好像这几种方案都要很恶心在滚动时判断是否滚动过半,然后松手后再自动滚动到上一页或者下一页或者还原到当前页。这样貌似很麻烦,直接pass掉。
假如有 垂直滚动的ViewPager就好了,对 垂直滚动的ViewPager ,于是Github上乱找一通,发现一个靠谱的 VerticalViewPager ,主要是 将原生的ViewPager所有的事件截断,然后通过宽高比的将原来横向的宽度变成现在垂直的高度,然后通过 event.setLocation(swappedX, swappedY);
来重新设置MotionEvent的坐标。说起来有些绕 还是直接看代码吧。
BTW viewPager.setOverScrollMode(ViewPager.OVER_SCROLL_NEVER);
需要设置这个属性,否则在overScroll效果的时候会发现是在左右侧而非上下侧,干脆直接禁止掉OverScrollMode
到此为止上下滑动算是实现了,但是 映客 IOS App中上下滚动的时候下层视频播放区域也是会跟随滚动的,而我显示的实现方案只是在上层的DialogFragment中ViewPager的第二页实现的滚动,要必须实现滚动的相关性,在此就下层Fragment中就必须有一个回调处理来至上层ViewPager滚动监听时的位置变化的大小和方向。(当初想过用EventBus来发送和处理这个滚动位置的Y坐标变化的信息,但是项目中EventBus大都接收TCP的各种消息而担心频繁滚动会致使性能问题,所以放弃了)
支持上下滚动且下层也跟随滚动的相关代码 添加上下滚动的支持
最后上一张没加上上下滚动时的GIF图片
效果
具体的代码参见 Github brucetoo
网友评论