9

我刚刚发现 View.setEnabled(false) 在 android 中无法正常工作,具体方式如下:

  1. 禁用父视图不会自动禁用子视图。这很不方便。
  2. 虽然颜色变灰,但禁用的视图仍然可以获得焦点并获得键盘输入、做出选择等。这是不对的。
  3. DEL/BACK 在获取键盘输入时,无论输入多少,都只能向后删除一个键。此行为仅显示在禁用的 EditText 中。
  4. 单选标签变灰,但单选按钮图像未变灰。

这似乎是一个错误。但是如何获得真正的 DISABLE 功能?

编辑:忘了提第一个。

4

4 回答 4

5

需要递归设置所有后代,否则布局中的 RadioButtons 将不会设置启用,因为 RadioButtons 是孙子而不是直子,中间有 RadioGroup。我根据其他人的回答记录了我迄今为止最好的解决方案。

public static void setEnabledAll(View v, boolean enabled) {
    v.setEnabled(enabled);
    v.setFocusable(enabled);

    if(v instanceof ViewGroup) {
        ViewGroup vg = (ViewGroup) v;
        for (int i = 0; i < vg.getChildCount(); i++)
            setEnabledAll(vg.getChildAt(i), enabled);
    }
}

子类此时不工作。如果我有:

public MyView class View {
    protected void setEnabled(boolean enabled, boolean setChildren){
        setEnabled(enabled);
        setFocusable(enabled);
        if(setChildren && this isinstanceof ViewGroup){
              for ( int i = 0 ; i < this.getChildCount() ; i++ )
                  //this line will have issue if it is not MyView                      
                  this.getChildAt(i).setEnabled(enabled, true); 
        }
    }
}

除非 View 本身有这个重载的 setEnabled ,如下所示:

public class View {
    protected void setEnabled(boolean enabled, boolean setChildren){
        setEnabled(enabled);
        setFocusable(enabled);
        if(setChildren && this isinstanceof ViewGroup){
              for ( int i = 0 ; i < this.getChildCount() ; i++ )         
                  this.getChildAt(i).setEnabled(enabled, true); 
        }
    }
}

This solution will eliminate problems 1, 2, 3. Problem 4 can be solved by setting disabled style selector for RadioGroup - I am not sure why android has no default disabled style selector for RadioGroup. Maybe another point for Android enhancement. Android is very flexible in SDK design also means sometimes extra work needed.

于 2013-10-07T21:23:00.233 回答
2

凭记忆,请原谅错别字:

class ExtendedLinearLayout extends LinearLayout{

    protected void setEnabled(boolean enabled, boolean setChildren){

        super.setEnabled(enabled);

        if(setChildren){
              for ( int idx = 0 ; idx < this.getChildCount() ; idx++ ) {
                  (View)(this.getChildAt(idx)).setEnabled(enabled);
              }
        }
    }
}
于 2013-10-07T13:39:03.733 回答
1

我没有你所有问题的答案,但我会first努力second

  • 1在禁用父母时不禁用孩子绝对没问题。考虑一种情况,您想单击布局的按钮但不想单击外部区域。Listrow 中的最佳示例,您有想要单击但不想单击行的按钮。

    一次禁用所有孩子

    LinearLayout layout = (LinearLayout) findViewById(R.id.my_layout);
    for (int i = 0; i < layout.getChildCount(); i++) {
    View child = layout.getChildAt(i);
    child.setEnabled(false);
     }
    
  • 2它仅适用于 EditText,但您也可以停止它。并且view.setFocusable(false);是正确的停止视图获得焦点

于 2013-10-07T12:33:34.163 回答
1

Just want to update this Michael SM' solution with kotlin. Override for view will looks like:

override fun setEnabled(enabled: Boolean) {
    super.setEnabled(enabled)
    children.forEach { it.isEnabled = enabled }
}

Call now is:

view.isEnabled = false
于 2018-08-06T13:30:52.947 回答