14

I have the following situation:

in styles.xml:

<style name="fooStyle">
    <item name="android:padding">?fooView.padding</item>
    <item name="android:background">?fooView.background</item>
    <item name="android:gravity">?fooView.gravity</item>
</style>

in attrs.xml:

<attr name="fooView.padding" format="dimension" />
<attr name="fooView.background" format="color|reference" />
<attr name="fooView.gravity" format="????"/>

in themes.xml:

<style name="fooViewTheme" parent="android:Theme">
    <item name="fooView.padding" >2dip</item>
    <item name="fooView.background" >#AA000000</item>
    <item name="fooView.gravity">right|bottom</item>
</style>

The problem is that I cannot figure out what the format for the fooView.gravity should be. I've already tried with string, enum and flag but none seem to work: I always get a java.lang.NumberFormatException: unable to parse 'right|bottom' as integer as soon as the view that uses this theme gets loaded.

All answers are appreciated.

Mopper
  • 1,677
  • 2
  • 18
  • 41

4 Answers4

33

Those are the gravity values used by Android. You can use that in your attrs.xml:

<resources>
    <declare-styleable name="MyCustomView">
        <attr name="gravity">
            <flag name="bottom" value="80" />
            <flag name="center" value="17" />
            <flag name="center_horizontal" value="1" />
            <flag name="center_vertical" value="16" />
            <flag name="clip_horizontal" value="8" />
            <flag name="clip_vertical" value="128" />
            <flag name="end" value="8388613" />
            <flag name="fill" value="119" />
            <flag name="fill_horizontal" value="7" />
            <flag name="fill_vertical" value="112" />
            <flag name="left" value="3" />
            <flag name="right" value="5" />
            <flag name="start" value="8388611" />
            <flag name="top" value="48" />
        </attr>
    </declare-styleable>
</resources>

In your layout XML you can use it this way:

<MyCustomView
        custom:gravity="center|bottom"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

And in Java code you can read the value using this:

int gravity = a.getInt(R.styleable.MyCustomView_gravity, Gravity.NO_GRAVITY);

and directly set it to a sub view, if that makes sense for you:

someSubView.setGravity(gravity);

You can look up those gravity values in the source of android.view.Gravity or here

Michael Geier
  • 1,653
  • 1
  • 16
  • 18
4

It's a flag attribute. You need to define it in your attributes xml like this:

    <attr name="gravity">
      <flag name="right" value="0x01" />
      <flag name="bottom" value="0x02" />
      <flag name="left" value="0x04" />
      <!-- etc. -->
    </attr>

...and then access the values using bit masks, like this:

    boolean right = (array.getInt(R.styleable.fooView_gravity, 0) & 0x01) == 0x01;
    boolean bottom = (array.getInt(R.styleable.fooView_gravity, 0) & 0x02) == 0x02;
    boolean left = (array.getInt(R.styleable.fooView_gravity, 0) & 0x04) == 0x04;
    // etc.

...and of course, these values can be used from XML as well:

<style name="fooViewTheme" parent="android:Theme">
    <item name="fooView.gravity">right|bottom</item>
</style>
Lorne Laliberte
  • 6,261
  • 2
  • 35
  • 36
  • Well, I'll have to give that a try sometime. I honestly cannot remember in which project I had this issue, it's been a while :) – Mopper Aug 07 '12 at 13:12
  • @YoushaAleayoub the original question already included examples of how to use such values in XML, so I didn't feel it was necessary to repeat that in my answer. My answer showed how custom attributes must be declared in XML in order to make that possible. However, I've edited an XML usage example into my answer. – Lorne Laliberte Sep 12 '16 at 16:59
3

As you only need a small selection of attributes, I'd suggest using the type "enum".

http://developer.android.com/training/custom-views/create-view.html

<attr name="labelPosition" format="enum">
    <enum name="left" value="0"/>
    <enum name="right" value="1"/>
</attr>

Referencing:

custom:labelPosition="left" 

In Code:

mTextPos = a.getInteger(R.styleable.PieChart_labelPosition, 0);
Graeme
  • 25,714
  • 24
  • 124
  • 186
2

Seems to be integer? Doc.

Would make sense since it can be 'ored'

Edit: sorry, probably misread the problem... It's clearly saying in the error that it's int, but bottom can't be converted to int :/

Edit2: Here are the int values if you need to work-around. Sorry for no real solution.

tobi.b
  • 224
  • 2
  • 12
  • I'm going to accept this as an answer since there doesn't seem to be a good way to do this. Possible workarounds are either hardcoding the int value as you suggested, or simply taking the android:gravity out of the theme and setting it manually on each component that requires it. I went with the latter option because I didn't feel like figuring out whether the int values for android:gravity have changed between certain releases of android. – Mopper Mar 02 '12 at 10:20