关于EditText屏蔽焦点的问题,及为什么clearFocus()方法失效了?

版权声明:https://blog.csdn.net/petterp https://blog.csdn.net/petterp/article/details/88087495

我们有时候的需求时,EditText 在不需要的时候,无法点击,或者取消它的默认焦点。

我们先看看通用解决方法。

setFousable() //设置该视图是否可以接收焦点

setFocusableInTouchMode(); //设置该视图在触摸模式下是否可以接收焦点

这里借鉴大佬的解释。 ​

类似非触屏手机时代,需要使用键盘的上下左右去选中某个应用,然后点击确定执行。而触屏手机,我们只需要对应用点击一次,即可,无需焦点。也就是会所焦点是为了标记你目前选中的位置的。而这个在日历中却是有用的。 android:focusable与android:focusableInTouchMode 前者针对在键盘下操作的情况,如果设置为true,则键盘上下左右选中,焦点会随之移动。 而后者,显然是针对触屏情况下的,也就是我们点击屏幕的上的某个控件时,不要立即执行相应的点击逻辑,而是先显示焦点(即控件被选中),再点击才执行逻辑。

android:focusable=“true”不会改变android:focusableInTouchMode,因此只在键盘状态下显示焦点,在TouchMode状态下,依旧无法显示焦点。

android:focusable=“false”,一定会使android:focusableInTouchMode=“false”。

相对的 android:focusableInTouchMode=“false”,不会影响android:focusable。

android:focusableInTouchMode=”true”,一定会是android:focusable=“true”

直接上解决方法

代码:
editText.setFocusable(false)
editText.setFocusableInTouchMode(false);
	  
xml  
android:focusable="false"
android:focusableInTouchMode="false"

按照上面的解决方案,我现在有5个 EditText,很多人会写出下面的例子:

EditText e1;
...

private void setFoucus(Boolean foucus){
    e1.setFoucusable(fouces)
    e1.setFocusableInTouchMode(focus)
    e2.setFoucusable(fouces)
    e2.setFocusableInTouchMode(focus)
    ...
    e5.setFoucusable(fouces)
    e5.setFocusableInTouchMode(focus)
}
简化版
用List来保存对象,然后for遍历,但是你的EditText,需要声明多少个呢

如果我现在有十几个输入框呢?难不成每一个都这样操作?

方法肯定有的,现在我们用另一个办法,从源头解决问题:

先上一波方法的解释

XML
android:descendantFocusability="blocksDescendants"

beforeDescendants:viewgroup会优先其子类控件而获取到焦点
afterDescendants:viewgroup只有当其子类控件不需要获取焦点时才获取焦点
blocksDescendants:viewgroup会覆盖子类控件而直接获得焦点


代码处
visable.setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);

问题定义:比如我们有EditText,由一个switch控制,当switch关闭时,editText可以输入,有焦点,否则无法点击,无焦点。

将这些输入框放在同一个线性布局里,然后利用 setDescendantFocusability() 方法,设置子类控件与viewgroup之间的焦点关系。  

 private LinearLayout layout;		//父布局实例
 ...
 private Boolean fouces=false;		//默认switch状态为false
 aSwitch.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (fouces) {
                    layout.setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
                    fouces=false;
                } else {
                    layout.clearFocus();	//清除fouces
                    layout.setDescendantFocusability(FOCUS_BLOCK_DESCENDANTS);
                    fouces=true;
                }
            }
        });
        

看到这,肯定很多人都觉得,这有啥难度啊,哼。我们先看运行结果。

 咦,clearFocus()方法失效了?为什么焦点还在呢?

不着急,我们从源码角度这次来分析一波,简单粗暴。

我们先看一下clearFocus的实现

  @Override
    public void clearFocus() {
        if (DBG) {
            System.out.println(this + " clearFocus()");
        }
        if (mFocused == null) {
            super.clearFocus();
        } else {
            View focused = mFocused;
            mFocused = null;
            focused.clearFocus();
        }
    }

 不管这些,我们顺着最后的调用方法走 focused.clearFocus();

 public void clearFocus() {
        if (DBG) {
            System.out.println(this + " clearFocus()");
        }

        final boolean refocus = sAlwaysAssignFocus || !isInTouchMode();
        clearFocusInternal(null, true, refocus);
    }

这里的意思是,如果焦点可用,或者非触控模式下,焦点会尝试将焦点放在第一个可以对焦的视图上,也就是说,相当于它被重置了,所以产生了我们上面图片里的问题,焦点没有被清除。

 接着继续顺着代码走 clearFocusInternal(null, true, refocus);

 
     void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
            mPrivateFlags &= ~PFLAG_FOCUSED;
            clearParentsWantFocus();

            if (propagate && mParent != null) {
                mParent.clearChildFocus(this);
            }

            onFocusChanged(false, 0, null);
            refreshDrawableState();

            if (propagate && (!refocus || !rootViewRequestFocus())) {
                notifyGlobalFocusCleared(this);
            }
        }
    }

 这里清除视图中的焦点,如果propagate为true,可选地将更改向上传播到父层次结构,并放置新的焦点。

  总结一下,也就是我们需要在父布局处添加 触控模式为true,即就是android:focusableInTouchMode="true",这样当清除焦点的时候,就会将焦点赋给父布局,而不是重置到第一个EditText.到了现在,我们可以尝试一下,如果设置第一个输入框focusableInTouchMode为false,那么当你点击了别的输入框,然后点击switch,会发现,焦点会在第二个输入框,而不会在第一个。

猜你喜欢

转载自blog.csdn.net/petterp/article/details/88087495
今日推荐