需求来源
目前做的是一个采集的App,配合金种子云平台的安卓采集端,有个界面是需要实现快速采集,每次采集完成后采集弹框不消失,还要动态去更新背后的recycleview
,然而弹框 + 软键盘的展示使得Recycleview
的可见区域很小。
初步实现
界面展示:
动态效果:
具体实现对应xml代码如下,不多做解释:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/root_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/tabbgcolor2"
android:orientation="vertical">
<com.nercita.commoncustomview.SearchTopBar
android:id="@+id/searchTopbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:isShowSearchEditText="true"
app:searchText="请输入要查找的小区号"
app:searchisShowLeft="true"
app:searchisShowRight="true"
app:searchleftSrc="@drawable/icon_white_back"
app:searchleftTopText="返回"
app:searchrightSrc="@drawable/icon_saoma"
app:searchrightTopText="扫码" />
<LinearLayout
android:id="@+id/top_liner"
android:layout_width="match_parent"
android:layout_height="48dp"
android:orientation="horizontal"
android:paddingBottom="5dp"
android:paddingLeft="20dp"
android:paddingRight="20dp"
android:paddingTop="5dp">
<TextView
android:id="@+id/tv_name"
android:layout_width="0dp"
android:layout_height="35dp"
android:layout_marginRight="40dp"
android:layout_weight="2"
android:background="@drawable/layout_name_bgcolor"
android:drawableRight="@drawable/pulldown"
android:gravity="center|left"
android:padding="5dp"
android:textColor="@color/txt_color"
android:textSize="18sp" />
<Button
android:id="@+id/bt_insert"
android:layout_width="0dp"
android:layout_height="27dp"
android:layout_weight="1"
android:background="@drawable/btn_shape_name"
android:drawableLeft="@drawable/edit"
android:gravity="center"
android:paddingBottom="1dp"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:paddingTop="1dp"
android:text="插入"
android:textColor="@color/white"
android:textSize="16sp" />
<Button
android:id="@+id/bt_delete"
android:layout_width="0dp"
android:layout_height="27dp"
android:layout_marginLeft="5dp"
android:layout_weight="1"
android:background="@drawable/btn_shape_name"
android:drawableLeft="@drawable/deletewhite"
android:gravity="center"
android:paddingBottom="1dp"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:paddingTop="1dp"
android:text="删除"
android:textColor="@color/white"
android:textSize="16sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="vertical">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="45dp"
android:orientation="horizontal">
<TextView
android:id="@+id/tv_sortNum"
android:layout_width="@dimen/distance_100"
android:layout_height="match_parent"
android:background="@drawable/shape_plan_hearder"
android:gravity="center"
android:text="序号"
android:textColor="@color/text_color"
android:textSize="18sp"
android:textStyle="bold" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tv_plotCode"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"
android:background="@drawable/shape_plan_hearder"
android:gravity="center"
android:text="小区号"
android:textColor="@color/text_color"
android:textSize="18sp"
android:textStyle="bold" />
<TextView
android:id="@+id/tv_totalRows"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@drawable/shape_plan_hearder"
android:gravity="center"
android:text="行数"
android:textColor="@color/text_color"
android:textSize="18sp"
android:textStyle="bold" />
<TextView
android:id="@+id/tv_sortOrder"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@drawable/shape_plan_hearder"
android:gravity="center"
android:text="方向"
android:textColor="@color/text_color"
android:textSize="18sp"
android:textStyle="bold" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/rv_compile"
android:layout_width="match_parent"
android:layout_height="match_parent"></android.support.v7.widget.RecyclerView>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="45dp"
android:layout_marginBottom="3dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:background="@drawable/fragment_bottom_bg"
android:gravity="center_vertical"
android:orientation="horizontal">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@color/white"
android:gravity="center"
android:orientation="horizontal">
<TextView
android:id="@+id/tv_last"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/icon_left"
android:text="上一列" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@color/white"
android:gravity="center"
android:orientation="horizontal">
<ImageView
android:id="@+id/iv_sub"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/subblack"
android:visibility="visible" />
<TextView
android:id="@+id/tv_current"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="/" />
<TextView
android:id="@+id/tv_total"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1" />
<ImageView
android:id="@+id/iv_add"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/addblack"
android:visibility="visible" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@color/white"
android:gravity="center"
android:orientation="horizontal">
<TextView
android:id="@+id/tv_next"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableRight="@drawable/icon_right"
android:text="下一列" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
有弹窗弹出,弹窗用DialogFragment
,弹窗弹出/收起对应top_liner
的隐藏/显示,这样做的目的是为recycleview
腾出点空间,不然recycleview
更矮的可怜。
可以看出recycleview
的可见区域变小了,被软键盘+弹窗给遮挡了,恰巧我们这里需求是:每次保存没必要关闭弹窗。所以新增的数据在recycleview
的可见区域里也看不到,这样的话用户就不知道到底有没有添加进去,导致用户体验不好
优化思路
1.弹窗弹出/收起对应top_liner
的隐藏/显示
2.软键盘弹出时(),让recycleview
高度缩小,软键盘收起时,恢复原样
3.每次保存或修改数据后,让弹窗背后的recycleview
滑动到当前修改行,让用户可以看到
优化方案实现
1.添加四个方法:
/**
* @param row
* 滑动到指定行
*/
public void scrollTo(int row) {
row--;
if (row < 0)
row = 0;
rvCompile.scrollToPosition(row);
}
/**
* 设置缩小高度
*/
public void setShortHeight() {
int height = mContext.getResources().getDimensionPixelOffset(R.dimen.distance_40);
LinearLayout.LayoutParams linearParams = (LinearLayout.LayoutParams) rvCompile.getLayoutParams();
linearParams.height = height * 3;
rvCompile.setLayoutParams(linearParams);
}
/**
* 保存原始高度
*/
public void saveNormalHeight() {
if (normalHeight == 0) {
LinearLayout.LayoutParams linearParams = (LinearLayout.LayoutParams) rvCompile.getLayoutParams();
normalHeight = linearParams.height;
Log.d("存储正常高度:" + normalHeight);
}
}
/**
* 设置正常高度
*/
public void setNormalHeight() {
LinearLayout.LayoutParams linearParams = (LinearLayout.LayoutParams) rvCompile.getLayoutParams();
linearParams.height = normalHeight;
rvCompile.setLayoutParams(linearParams);
}
2.在onCreate()
里调用saveNormalHeight
()保存原始高度,在onResume()
中实现软键盘监听,然后控制recycleview
高度和定位行,只贴出相代码
protected void onResume() {
super.onResume();
····
KeyboardStautusDetectorUtil keyboardStautusDetectorUtil = new KeyboardStautusDetectorUtil();
keyboardStautusDetectorUtil.setmVisibilityListener(new KeyboardStautusDetectorUtil.KeyboardVisibilityListener() {
@Override
public void onVisibilityChanged(boolean keyboardVisible) {
if (keyboardVisible && dialogIsDiss) {
setShortHeight();
if (mCurrentRow == 0 && dialogIsDiss) {
scrollTo(serial);
} else {
scrollTo(mCurrentRow);
}
} else {
setNormalHeight();
}
}
});
keyboardStautusDetectorUtil.registerActivity(this);
···
}
关于 if (keyboardVisible && dialogIsDiss) 判断条件加了个dialogIsDiss是因为要排除搜索框中的软键盘弹出
3.添加弹窗的监听事件,显示隐藏top_liner
@Override
public void dialogDismiss() {
topLiner.setVisibility(View.VISIBLE);
dialogIsDiss = false;
}
@Override
public void dialogShow() {
dialogIsDiss = true;
topLiner.setVisibility(View.GONE);
}
效果展示
遇到的坑:
在监听软键盘弹出隐藏时,刚开始打算用给跟布局添加addOnLayoutChangeListener
方法实现,然而发现不会成功,打断点调试时候发现bottom和oldBottom 不为0的情况下始终是相等的,但是网上却说这个方法确实能监听到。我猜测是我用了DialogFragment原因
@Override
public void onLayoutChange(View v, int left, int top, int right,
int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
// old是改变前的左上右下坐标点值,没有old的是改变后的左上右下坐标点值
// 现在认为只要控件将Activity向上推的高度超过了1/3屏幕高,就认为软键盘弹起
if (oldBottom != 0 && bottom != 0 && (oldBottom - bottom > keyHeight)) {
// ToastUtil.toast(CompileActivity.this, "监听到软键盘弹起...");
setShortHeight();
if (mCurrentRow == 0 && dialogIsDiss) {
scrollTo(serial);
} else {
scrollTo(mCurrentRow);
}
} else if (oldBottom != 0 && bottom != 0
&& (bottom - oldBottom > keyHeight))
// ToastUtil.toast(CompileActivity.this, "监听到软件盘关闭...");
setNormalHeight();
}
}
/**
* 创建时间:2018/8/31
* 编写人:kanghb
* 功能描述:
*/
public class KeyboardStautusDetectorUtil {
private static final int SOFT_KEY_BOARD_MIN_HEIGHT = 400;
private KeyboardVisibilityListener mVisibilityListener;
boolean keyboardVisible = false;
public void registerFragment(Fragment f) {
registerView(f.getView());
}
public void registerActivity(Activity a) {
registerView(a.getWindow().getDecorView().findViewById(android.R.id.content));
}
public KeyboardStautusDetectorUtil registerView(final View v) {
v.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
Rect r = new Rect();
v.getWindowVisibleDisplayFrame(r);
int heightDiff = v.getRootView().getHeight() - (r.bottom - r.top);
if (heightDiff > SOFT_KEY_BOARD_MIN_HEIGHT) { // if more than 100 pixels, its probably a keyboard...
if (!keyboardVisible) {
keyboardVisible = true;
if (mVisibilityListener != null) {
mVisibilityListener.onVisibilityChanged(true);
}
}
} else {
if (keyboardVisible) {
keyboardVisible = false;
if (mVisibilityListener != null) {
mVisibilityListener.onVisibilityChanged(false);
}
}
}
}
});
return this;
}
public KeyboardStautusDetectorUtil setmVisibilityListener(KeyboardVisibilityListener listener) {
mVisibilityListener = listener;
return this;
}
public interface KeyboardVisibilityListener {
void onVisibilityChanged(boolean keyboardVisible);
}
}
目前没发现什么问题,也解决了我所遇到的问题。