Reputation: 22028
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:
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
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:
Upvotes: 3
Reputation: 1094
I would just use a TextView, and set a 9 patch as the background:
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
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.
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