I have a custom button which I've implemented as a composite control which is composed of:
- A FrameLayout at the root, which I've styled with @android:style/Widget.Holo.Button in order to look and act like a button;
- Two TextViews as children of the aforementioned FrameLayout, configured with duplicateParentState=true so that they will appear disabled if I set enabled on the FrameLayout to false.
The trimmed XML looks as follow:
<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>
Along with the XML layout for the composite control, I've created a Java implementation as described in the Android documentation, which looks something like this:
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);
}
}
If I understand correctly, when this control is used the constructed hierarchy will be (parenthesis indicating where the View is defined):
FrameLayout (Java) -> FrameLayout (XML) -> 2x TextViews (XML)
I want to be able to toggle whether my custom button is enabled or not by getting a reference to the button and setting the enabled property, like so:
CustomButton button = (CustomButton)findViewById(R.id.button);
button.setEnabled(false);
This does not work however, as the FrameLayout defined in the XML does not inherit its parent's properties, and as such the button continues to be displayed as enabled.
I've tried adding duplicateParentState=true to the FrameLayout defined in the XML, but in that case my style attribute is overwritten/inherited and the control doesn't look like a button anymore.
I've also tried using the merge tag and setting the style programmatically, but as far as I can tell it isn't possible to set View styles programmatically.
My workaround thus far has been to overwrite the setEnabled() method on CustomButton like so:
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
findViewById(R.id.button_rootLayout).setEnabled(enabled);
}
This works but I now have to do this for every property I want to modify programmatically, and I have similar issues with registering OnClickListeners.
Is there a better way?
How about:
This is what I ended up doing.