fweigl
fweigl

Reputation: 22028

Icon with text inside - how to define in layout?

I want to have a TextView (to show a count) hovering over an icon in the ActionBar. What I did was have a RelativeLayout, set a background to it, then put that TextView in that layout and screw with the margin until it fits, but that is broken as soon as the text length varies. Setting a background on the TextView isn't great either because I can't position the text in relation to the icon.

Here's my XML:

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:layout_gravity="fill_horizontal" >

    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:background="@drawable/cart" >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="0"
        android:layout_marginTop="5dp"      android:layout_marginLeft="43dp"
        android:textAppearance="?android:attr/textAppearanceMedium" />

</RelativeLayout> </RelativeLayout>

and here is a screenshot to show you what I mean:

enter image description here

Is there a stress-free way, a library perhaps, that lets me set a TextView over a Drawable so that the TextView is always centered/ positioned?

Upvotes: 4

Views: 1499

Answers (3)

Steven Byle
Steven Byle

Reputation: 13269

Setting a background on the TextView isn't great either because I can't position the text in relation to the icon.

Actually you can position your text relative to your icon. You need to separate the cart icon and the number badge icon as separate images, and lay them out individually. I had to do this myself not too long ago, and I did it with a RelativeLayout, with an ImageView of the cart icon and a TextView for the numbers with a 9-patch "badge" as the background.

The trick is to align your number TextView to the left and bottom of your cart icon ImageView, and then use the left and bottom margins to push your number badge to the top and right of your cart icon. This way, the number badge is always anchored based on your cart icon.

Also, set the gravity of your TextView to center, so as the numbers grow wider, the relative position of the text is about the same. Lastly, use padding on your TextView to control how much gap there is between the edge of the number and the edge of your "badge" 9-patch.

Here's a snippet of my implementation (I've redacted some of this):

   <RelativeLayout
        android:id="@+id/cartButton"
        android:layout_width="wrap_content"
        android:layout_height="fill_parent" >

        <ImageView
            android:id="@+id/cartIconImageView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:src="@drawable/ic_menu_cart" />

        <TextView
            android:id="@+id/cartBadge"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignBottom="@+id/cartIconImageView"
            android:layout_alignLeft="@+id/cartIconImageView"
            android:layout_marginBottom="10dp"
            android:layout_marginLeft="9dp"
            android:background="@drawable/state_list_cart_badge"
            android:gravity="center"
            android:includeFontPadding="false"
            android:lines="1"
            android:paddingLeft="8dp"
            android:paddingRight="8dp"
            android:text="7" />
    </RelativeLayout>

And this is what it looks like:

enter image description here

enter image description here

Upvotes: 3

S Fitz
S Fitz

Reputation: 1094

I would just use a TextView, and set a 9 patch as the background:

9 patch file

You might have to play around with it (I just whipped this up in a minute or two), but something like the very bottom right in the image is what you want. It will be a lot more consistent than dealing with two views.

Upvotes: 0

class stacker
class stacker

Reputation: 5347

Use a FrameLayout. It's always called useless but if you ask me it's perfect to lay out one View on top of another.

Quote:

Child views are drawn in a stack, with the most recently added child on top. The size of the FrameLayout is the size of its largest child (plus padding), visible or not (if the FrameLayout's parent permits). Views that are GONE are used for sizing only if setConsiderGoneChildrenWhenMeasuring() is set to true.

Upvotes: 0

Related Questions