winform是如何自动弹出软键盘_EditText与软键盘的相爱相杀

这周完成了一个需求,涉及到EditText和软键盘,其中一个要求是:键盘出现时,文本输入框和键盘的间距大于16dp。

现在回头看,没想到EditText能折腾出新鲜东西。

整个页面的布局走常规路线,我画了一张草图,其中ScrollView和EditText用红色标注了一下:

e14365859d6f1188e0015c73cf1646c2.png

一、键盘出现时,遮盖住了部分EditText

这个问题,写项目的时候我是没有遇到的,为了这篇文章写Demo时出现了,真是amazing。

然后这个问题的解法,在搜索引擎上查找到,但是结果并不理想,看到的方案太复杂,比如:使用ViewTreeObserver.OnGlobalLayoutListener监听整个页面布局变化,在回调里滑动ScrollView

于是我对比了一下项目和Demo关于使用EditText的代码。发现区别在于:layout_height的值。

  • 当layout_height="xxdp"时,会出现软键盘遮盖部分EditText的问题
  • 下面这种写法则不会导致软键盘遮盖的问题

所以,这个问题我们可以规避掉。至于这两种写法,为何会造成键盘表现不同,有兴趣的朋友可以深拔拔看,又知道的也请告知一下,感谢~

图【EditText 被键盘遮盖部分底部】:

b32ecf8a12dba057cd836ef746330957.png

二、如何控制文本输入框和键盘的间距

首先,ScrollView会自动滚动合适的距离将带焦点的View滑动到屏幕的可见区域,这个知识在做这次的需求之前我已知道。后面所有的思路,就是如何利用ScrollView的这一特点。

解法一:

设置EditText的bottom padding,结合InsetDrawable,在视觉上可以以假乱真。

最后没有采取这种方案,这个方案会导致EditText和它底部临近的控件间距变大(如果没底部没有其他控件这个方案就很适合)

效果大概是这样的:

ceebe0d7369f6daee3c090945a52eb03.png

解法二:

巧用ScrollView自动滚动带焦点View的特点。当带焦点的View不在屏幕可见的范围时,ScrollView内部会根据这个View的bounds,计算一个合适的偏移量,然后将该View滚动到可见的合适范围。

我们看一下ScrollView#onSizeChanged()方法的源码:

@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {        super.onSizeChanged(w, h, oldw, oldh);        View currentFocused = findFocus();        if (null == currentFocused || this == currentFocused)                return;        // If the currently-focused view was visible on the screen when the        // screen was at the old height, then scroll the screen to make that       // view visible with the new screen height.        if (isWithinDeltaOfScreen(currentFocused, 0, oldh)) {         //获取View的位置宽高信息等        currentFocused.getDrawingRect(mTempRect);                offsetDescendantRectToMyCoords(currentFocused, mTempRect);        //根据此时获取到焦点的View计算滑动距离,        int scrollDelta = computeScrollDeltaToGetChildRectOnScreen(mTempRect);                doScrollY(scrollDelta);    }}

computeScrollDeltaToGetChildRectOnScreen方法名好长,打开这个方法的文档,我们能看到:

Compute the amount to scroll in the Y direction in order to get a rectangle completely on the screen (or, if taller than the screen, at least the first screen size chunk of it).

大意是:计算rectangle表示的View完全可见需要的的滑动距离,这个是我们需要的方法。该方法的修饰符是protected,意味着我们通过可以继承的方式重写该方法,通过修改该方法的返回值,达到我们的目的,整个修改的开发量巨小,如下:

class FITBScrollView(    context: Context?,    attrs: AttributeSet?) : ScrollView(context, attrs) {    var extraMargin = TypedValue.applyDimension(        TypedValue.COMPLEX_UNIT_DIP,         16f,         resources.displayMetrics    ).roundToInt()        /**     *  EditText获取焦点后,ScrollView会将它滑动到屏幕显示的范围内,这个时候这个方法会被触发,用来计算Y轴滚动距离     */    override fun computeScrollDeltaToGetChildRectOnScreen(rect: Rect?): Int {        //Child非完全可见时        if (rect?.bottom ?: 0 > scrollY + height - extraMargin) {            return super.computeScrollDeltaToGetChildRectOnScreen(rect) + extraMargin                }        return super.computeScrollDeltaToGetChildRectOnScreen(rect)    }}

效果大概是这样的:

558afbbf3a8e01eef665bc7edff2dbda.gif

希望对有类似问题的开发朋友们有帮助。尤其是EditText被软键盘遮挡的问题,不希望大家用太复杂的方案,因为复杂的方案常常意味着更多的风险。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值