更改Android复合控件的启用状态,同时保持其样式设置



我有一个自定义按钮,我已经将其实现为一个复合控件,它由以下部分组成:

  • 根目录下的FrameLayout,我用@android:style/Widget.Holo.Button设计了它的样式,以便看起来和行为都像一个按钮
  • 两个TextView作为上述FrameLayout的子级,配置为duplicateParentState=true,因此如果我将FrameLayout上的enabled设置为false,它们将显示为禁用

修剪后的XML如下所示:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  style="@android:style/Widget.Holo.Button"
  android:id="@+id/layout_button">
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="PLACEHOLDER"
    android:layout_gravity="center_horizontal|top"
    android:duplicateParentState="true"
    android:id="@+id/text_button1"
    android:textSize="24sp"/>
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="PLACEHOLDER"
    android:layout_gravity="center_horizontal|bottom"
    android:duplicateParentState="true"
    android:id="@+id/text_button2"
    android:textSize="12sp"/>
</FrameLayout>

除了复合控件的XML布局外,我还创建了一个Java实现,如Android文档中所述,它看起来像这样:

public class CustomButton extends FrameLayout {
  public CustomButton (Context context, AttributeSet attrs) {
    super(context, attrs);
    LayoutInflater layoutInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    layoutInflater.inflate(R.layout.control_custombutton, this, true);
  }
}

如果我理解正确,当使用该控件时,构建的层次结构将是(括号表示视图的定义位置):

FrameLayout (Java) -> FrameLayout (XML) -> 2x TextViews (XML)

我希望能够通过获取对按钮的引用并设置启用的属性来切换我的自定义按钮是否启用,如下所示:

CustomButton button = (CustomButton)findViewById(R.id.button);
button.setEnabled(false);

但是,这不起作用,因为在XML中定义的FrameLayout没有继承其父项的属性,因此按钮继续显示为已启用。

我尝试将duplicateParentState=true添加到XML中定义的FrameLayout中,但在这种情况下,我的样式属性被覆盖/继承,控件看起来不再像按钮。

我也尝试过使用merge标记并以编程方式设置样式,但据我所知,以编程方式设定视图样式是不可能的。

到目前为止,我的解决方法是覆盖CustomButton上的setEnabled()方法,如下所示:

public void setEnabled(boolean enabled) {
    super.setEnabled(enabled);
    findViewById(R.id.button_rootLayout).setEnabled(enabled);
}

这是可行的,但我现在必须对我想以编程方式修改的每个属性都这样做,而且我在注册OnClickListeners时也遇到了类似的问题。

有更好的方法吗?

怎么样:

public void setEnabled(boolean enabled) {
    super.setEnabled(enabled);
    setClickable(enabled);
}

这就是我最终所做的。

最新更新