0

I'm trying to add a style to a button in Xamarin Android from code, because the buttons will be generated dynamically and need to change colors based on other system events.

Using the code shown here, I expect that the two rows, one rendered from XML and the other from code, will look exactly alike. Instead, I see that the style ButtonDefaultTheme is only applied to the first row.

I know setting the style from code is possible based on this answer and this one. I think I could accomplish what I need using a layout inflater as in this answer, but I'm very curious why the code I have won't work.

public class MainActivity : Activity
{
    protected override void OnCreate(Bundle bundle)
    {
        base.OnCreate(bundle);
        SetContentView (Resource.Layout.Main);

        LinearLayout roomButtonLayout = FindViewById<LinearLayout>(Resource.Id.roomButtonLayout);
        LinearLayout roomInfo = new LinearLayout(this)
        {
            Orientation = Orientation.Horizontal,
            LayoutParameters = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MatchParent, LinearLayout.LayoutParams.MatchParent, 1f)
        };
        roomInfo.SetGravity(GravityFlags.CenterVertical);
        roomInfo.SetPadding(20, 10, 0, 10);

        TextView roomNameDisplay = new TextView(this)
        {
            Gravity = GravityFlags.Left,
            TextSize = 20, // defaults to scaled pixels
            Text = "Room 100",
            LayoutParameters = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WrapContent, LinearLayout.LayoutParams.WrapContent, 1f)
        };

        roomInfo.AddView(roomNameDisplay);

        Button button2 = new Button(new ContextThemeWrapper(this, Resource.Style.ButtonDefaultTheme), null, 0)
        {
            Text = "View2"
        };

        roomInfo.AddView(button2);

        roomButtonLayout.AddView(roomInfo);
    }  
}

In Main.axml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:gravity="center_horizontal"
    android:layout_width="match_parent"
    android:paddingLeft="10dp"
    android:paddingRight="10dp"
    android:layout_height="wrap_content"
    android:id="@+id/roomButtonLayout">
    <LinearLayout
        android:orientation="horizontal"
        android:gravity="center_vertical"
        android:paddingLeft="20dp"
        android:paddingRight="0dp"
        android:paddingTop="10dp"
        android:paddingBottom="10dp"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1">
        <TextView
            android:gravity="left"
            android:textSize="20sp"
            android:text="Room 100"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1" />
        <Button
            android:text="View1"
            style="@style/ButtonDefaultTheme" />
      </LinearLayout>
  </LinearLayout>

In styles.xml

<?xml version="1.0" encoding="utf-8" ?>
<resources>
  <style name="ButtonDefaultTheme" parent="android:style/Widget.Holo.Button">
    <item name="android:paddingBottom">0dp</item>
    <item name="android:paddingTop">0dp</item>
    <item name="android:paddingLeft">10dp</item>
    <item name="android:paddingRight">10dp</item>
    <item name="android:layout_width">wrap_content</item>
    <item name="android:layout_height">wrap_content</item>
    <item name="android:layout_weight">1</item>
    <item name="android:minWidth">100dp</item>
  </style>
</resources>

Result:

Screenshot showing the TextView in the first row has greater left padding, and the button for View2 is much shorter than the button for View1

  • Minimum API level needed: 19

  • Compiling using: 21 in actual app, 23 in test app. Same visual results in both.

Community
  • 1
  • 1
Cass
  • 870
  • 8
  • 21
  • Possibly related: http://stackoverflow.com/questions/40706301/style-not-working-entirely-when-applied-on-button-programmatically Seems that a certain constructor doesn't want to work unless it uses an `Attribute` and not a `Style`. – Jon Douglas Apr 27 '17 at 00:44
  • I'm not seeing that the constructor only works on Attribute - can you get me the permalink of what you're referencing? The first answer on that question is where I got a couple of the links from my original question, one of which shows I should be able to do this. – Cass Apr 27 '17 at 00:49
  • [ContextThemeWrapper](https://developer.android.com/reference/android/view/ContextThemeWrapper.html#ContextThemeWrapper(android.content.Context, int)) "The specified theme will be applied on top of the base context's theme. Any attributes not explicitly defined in the theme identified by themeResId will retain their original values." Another example: http://stackoverflow.com/a/24267107/1048571 Finally: [View](https://developer.android.com/reference/android/view/View.html#View(android.content.Context,%20android.util.AttributeSet,%20int)) – Jon Douglas Apr 27 '17 at 00:54
  • Thanks, I hadn't seen that. I updated my styles.xml file to https://gist.github.com/clottman/55e9c223928f36d856471c43f84cd740, set the base theme in my app manifest (which is working), and changed the constructor to `Button button2 = new Button(this, null, Resource.Attribute.buttonAttrReference)`. I still get the same result, though. Possibly a Xamarin-specific issue? – Cass Apr 27 '17 at 01:54
  • I doubt it. There's many documented oddities with this API in regular java and the possibility that what you're trying to do is limited. Highly recommend trying a java project though since it's simple to convert the code over to test. – Jon Douglas Apr 27 '17 at 02:12

0 Answers0