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?
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:
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.
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.
Related
I know this sounds simple but I wanted to change a button's font size to fill the Button .Even though the text doesn't take all the space inside the button when I decrease text height for example the Button's height decreases as well.Is there any way I can change The text-size so it fills that space inside the Button or do I have to just use an Image Button .
Here is the case :-
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="#android:color/black"
android:id="#+id/led"
>
<Button
android:id="#+id/grow"
android:layout_width="match_parent"
android:layout_height="39dp"
android:layout_marginRight="1dp"
android:layout_weight="1"
android:textSize="15dp"
android:background="#color/Lightbrown"
android:text="A▲"
android:textAllCaps="false"
/>
<Button
android:layout_width="match_parent"
android:layout_height="39dp"
android:text="A▼"
android:textAllCaps="false"
android:id="#+id/shrink"
android:background="#color/Lightbrown"
android:layout_marginRight="1dp"
android:layout_weight="1"
android:padding="0dp"
android:textSize="10dp"
/>
See I used my Linearlayout as a background for my Buttons the second button's size changes with its font size I just want its size to remain the same as the first Button but with a smaller textsize.
Update
Your second button is not actually smaller, it is just aligned in a way you wouldn't necessarily expect.
Horizontal LinearLayouts with TextView (or subclass, which Button is) children will "baseline align" the children. That means they will make sure that the bottom edge of all the text in the row is at the same height. Since your second button uses smaller text, the text bottom would be higher up inside the button, so the LinearLayout forces the whole button down to accomodate.
Add this attribute to your LinearLayout:
android:baselineAligned="false"
Original
First, I assume you're using android:layout_height="wrap_content". If you don't want your button's height to scale with font size, you'll have to change this to some fixed value (or match_parent if you want it to be the same size as its parent).
As for why the text "doesn't take up all the space", that's because Buttons have padding built into them automatically. You can remove this padding by defining android:padding="0dp"
However, you'll soon notice that the button looks really bad if you give it no padding and too-large text. How to solve that is really up to the requirements of your design.
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:layout_width="wrap_content"
android:layout_height="32dp"
android:layout_gravity="center_horizontal"
android:padding="0dp"
android:textSize="36sp"
android:text="Hello world"/>
</FrameLayout>
Use a fixed size instead of wrap_content for your button.
f that doesn't work for your design, consider overlaying a TextView on top of your Button (with ConstraintLayout or FrameLayout or RelativeLayout). After that, you can set the TextView's focusable, focusableInTouchMode, and clickable properties to false so that it doesn't intercept your Button's clicks.
This is my layout:
TEXTVIEW
IMAGEVIEW (optional)
LINEARLAYOUT - to which I add Buttons dynamically
LINEARLAYOUT - with two buttons side by side (left button and right button)
What do I need to do to ensure that the bottom two linear layouts are fixed to the bottom of the screen, regardless of how much space they may take up? ie. The first linear layout might have 3 buttons and take up over half the screen, which is okay. It just needs to be above the left/right buttons in the last linear layout, which is fixed to the bottom.
Then I want my TextView and my ImageView vertically centred in the remaining space. The ImageView will be set to invisible if there is no image, so it could only be the text view which needs to be centred.
I've been playing around with android:gravity="bottom", android:layout_height="0dip"/android:layout_weight="1" (I later realised this would only give 50% to the text/imageview and 50% to the 2 linear layouts), but I can't get my desired result.
Any advice appreciated.
You have to take RelativeLayout.
There you have a better control of the relative position of the views, something like this:
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
>
<TextView
android:id="#+id/textView"
android:layout_above="#+id/imageView"
android:layout_centerVertical="true"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<ImageView
android:id="#+id/imageView"
android:layout_above="#+id/ll_1"
android:layout_centerVertical="true"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<LinearLyout
android:id="#+id/ll_1"
android:layout_above="#+id/ll_2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<LinearLyout
android:id="#+id/ll_2"
android:layout_alignParentBottom="true"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
</RelativeLayout>
I have a horizontal LinearLayout set to wrap_content. Inside is a vertical LinearLayout containing a single TextView that allows multiple lines (also wrap_content) and an ImageButton (wrap_content). Several of the components have margins and padding so things space out nicely.
When the text in the TextView is short, everything is fine. When the text wraps to multiple lines, still fine. When the text is almost long enough to wrap, the ImageButton gets clipped horizontally - its left and right sides are lopped off. If I pull out the margins and padding it works, but of course it doesn't look good.
My guess is that the layout system is calculating the text width without taking into account some of the margins and padding. Then it's laying things out, and there's less total space than that first pass at the TextView thought, so it's clipping the second item in the layout and honoring the calculated TextView width. But that is just a guess.
Short of writing my own layout, any ideas?
EDIT
Here's a screen shot from hierarchy viewer, showing where the ImageButton is clipped and with the relevant XML highlighted. The ImageButton's bounds are consistent with what I'm seeing: 27dp wide, whereas the circle image itself is actually 36dp wide, and the ImageButton has 4dp padding specified on each side.
Again, I had to choose that text carefully: any shorter and the button is fine; longer and it would wrap, and the button's fine again.
EDIT
And, here's my XML:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/messageBubble"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:minHeight="#dimen/message_bubble_min_height"
android:layout_alignTop="#id/avatar"
android:layout_alignLeft="#id/avatar"
android:layout_marginTop="#dimen/message_bubble_margin_top"
android:layout_marginLeft="#dimen/message_bubble_inset"
android:layout_marginRight="#dimen/message_inbound_padding_inside"
android:paddingLeft="#dimen/message_bubble_padding_outside"
android:paddingRight="#dimen/message_bubble_padding_inside"
android:paddingTop="#dimen/message_bubble_padding_v"
android:paddingBottom="#dimen/message_bubble_padding_v"
android:orientation="horizontal">
<LinearLayout
android:id="#+id/contentContainer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="left"
android:orientation="vertical">
<TextView
android:id="#+id/messageBody"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="#dimen/message_body_margin_outside"
android:layout_marginRight="#dimen/message_body_margin_inside"
android:layout_marginTop="#dimen/message_body_margin_v"
android:layout_marginBottom="#dimen/message_body_margin_v"
android:gravity="left"
android:autoLink="all"
android:textSize="17dp" />
</LinearLayout>
<include layout="#layout/view_message_action_btn" />
</LinearLayout>
And the included view_message_action_btn:
<ImageButton xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/actionButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#null"
android:src="#drawable/action_btn"
android:paddingLeft="#dimen/message_action_btn_padding_h"
android:paddingRight="#dimen/message_action_btn_padding_h" />
Today I have been playing a bit with the LinearLayout and have been suprised with the results:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/textView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Big Text"
android:gravity="center_vertical|center_horizontal"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="#+id/textView2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Medium Text"
android:textAppearance="?android:attr/textAppearanceMedium" />
<Button
android:id="#+id/button1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:text="Button"
/>
</LinearLayout>
This is a simple layout with a text view header, then a text view that I want it to cover all parent (but the space occupied by the bottom button) and a button that is placed at the botton side with the layout_gravity="bottom".
This produces a layout where header is shown correctly, center text view covers all remaining free space and the button does not appear. Why is this? Shouldn't the center text view just calculate its size taking into account the bottom button size?.
Use layout_weight="1" in your center TextView.
Always remember thumb rule
If you are using linear layout with vertical orientation as soon as it finds the control
with
android:layout_height="match_parent"
The layout will ignore all the controls present below it.
Hope this help
Vipul
In place of this
android:layout_width="match_parent"
android:layout_height="match_parent"
use 'wrap_content' like this
android:layout_width="wrap_content"/"fill_parent"
android:layout_height="wrap_content"/"fill_parent"
Shouldn't the center text view just calculate its size taking into account the bottom button size?.
No, because you tell the second TextView to match its parent's height, thus FILL_PARENT and hence it will fill up all remaining space, leaving none for the last TextView.
(...) and a button that is placed at the botton side with the layout_gravity="bottom".
Unfortunately, that's not how a LinearLayout works. If you set the orientation to vertical, basically only the left and right gravities will have effect. Vice versa, with the (default) horizontal orientation, only top and bottom work. The orientation determines in which direction the View children are dynamically positioned in order, which implies you cannot manually change the 'position' in that direction.
Now, to get the desired effect, you can give the second TextView a height of 0dp and a weight of 1, resulting in it dynamically filling up all remaining space without pushing the third TextView off the bottom. Alternatively, you can use a RelativeLayout, with which you can directly set the position, and simply instruct the middle TextView to sit below the first, but above the last.
So it's possible to align the top, bottom, left, and right of one view with another so that their edges are flush with each other. However, I've been wondering if it's possible to align the centers of two views of different sizes. My situation occurs when I have an ImageView side by side with a TextView, like this: [ImageView] [TextView]. The ImageView is bit taller than the TextView and so what I do is add padding/margins to the bottom of TextView to get it align and look like the ImageView and TextView horizontal centers are aligned. Problem is, when this view is displayed on larger tablet screens, the padding and margins don't work out right and the TextView doesn't look aligned with the ImageView. I'm sure there is an easy fix to allow this to always work out, so could someone provide me with some insights? Thanks!
This is how I did for a listview row:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#FFFFFF"
android:padding="5dp"
android:gravity="center_vertical">
<TextView android:id="#+id/questionItemTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textSize="20sp"
android:textColor="#000000"
android:gravity="center_vertical"/>
<ImageView android:id="#+id/questionViewed"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/eye"
android:layout_marginLeft="5dp" />
<ImageView android:id="#+id/questionAnswered"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/check"
android:layout_marginLeft="5dp" />
</LinearLayout>
Use weightSum rather than padding in dips or pxs, that will make your layout look fine regardless of the size of the user's device.
or you could use gravity as well.
Or you can create a second xml file and insert that one into your res/xlarge file, the phone will pick which xml to read.