In the image above, the black speech bubble and the red background behind it are a single ImageView that spans the width of a vertical phone screen. The "Hello" is a TextView and the layout is relative. Using margins, I was able to position the "Hello" inside the speech bubble in my Android emulator -- but the positioning is off when I emulate a different phone.
Is there a better way to position my TextView
is there a way to make it responsive (so that the Hello is always in
the speech bubble, no matter what the device)?
Here's my xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/relativeLayout">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/mainGraphic"
android:src="#drawable/finished2"
android:layout_marginBottom="97dp"
android:layout_above="#+id/enterValue"
android:layout_alignParentStart="true" />
<TextView
android:maxWidth="200dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Medium Text"
android:id="#+id/helloText"
android:textColor="#FFFFFF"
android:layout_marginEnd="29dp"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_marginTop="45dp" />
</RelativeLayout>
I would use a FrameLayout instead of the RelativeLayout with same size like the image.
Then use the attributes android:layout_gravity="center" and android:gravity="center" for the TextView.
Try this:
...
<TextView
android:maxWidth="200dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Medium Text"
android:id="#+id/helloText"
android:textColor="#FFFFFF"
android:layout_alignTop="#+id/mainGraphic"
android:layout_alignBottom="#+id/mainGraphic"
android:layout_alignLeft="#+id/mainGraphic"
android:layout_alignRight="#+id/mainGraphic"
android:gravity="center" />
...
Best approach is to use 9-patch image & set it as the background of the Textview. If you use a normal png file, we can't guarantee that it will align correctly on all resolutions & it can become blurred when stretched.
9-Patch image automatically resize to accommodate the contents of the view and the size of the screen. Android SDK provides a tool for creating 9-patch images which is inside SDK sdk/tools directory. See https://developer.android.com/studio/write/draw9patch.html.
You should use a 9-patch for the message shape. What you can do is make the root view of your layout as a FrameLayout and then add a TextView to it. Set the message shape Nine-patch as the background of the TextView.
For creating the 9-patch visit https://romannurik.github.io/AndroidAssetStudio/nine-patches.html by Roman Nurik. There just upload a png file of the image asset and choose the xhdpi definition for best results. The Nine-patch has 3 main properties -
Stretch regions : Defines which areas of the asset can stretch for accommodating different screen densities.
Content Padding : Defines the padding area for the content (text) that is going to appear inside the image.
Optical Bounds : Defines how much area should be optically visible around the asset.
Pros of using Nine-patches :
Scalable
Easy to use
Lightweight
Any amount of content can be put in it.
Hope this helps.
Ideally, you should be using a complete red background to the RelativeLayout, and a black speech 9patch image for the TextView.
But if you really want the RelativeLayout to have background as red with speech bubble, you have to set it at run time.
Calculate the height and width of RelativeLayout at run time say 150px and 300px respectively.
Carefully look at the background image, and determine the edge points of bubble from top, right, bottom and left. For example, if image height is 100px by 200px, and bubble top starts at 30px and bottom ends at 70px, right edge starts at 150px and left ends at 250px. Also calculate the width and height of TextView.
At run time, change the position of TextView based on the above figures.
Related
I have a textview which has to use a 9-patch drawable as the background. But the 9-patch drawable has left and right paddings which make the background image not stretch properly to cover the whole text. I tried resetting the paddings for the textview itself but it doesn't fix the problem.
Would anyone have any idea how to make it work?
Thanks.
The black lines on the left and top defines the stretchable are, and those on the right and bottom marks the "content" area in a 9-patch image.
So, if you don't want padding means you want a full-length content area. You should mark full-width content area by drawing a full-length line at the bottom and right of the 9patch image.
In this image, the black lines on the right and bottom represent the content area. You can see the preview on the right side, and notice the content area in light blue color. You can fill the content area by extending the bottom and right lines.
Editing 9-patch file is not a good idea, because this method may deform the background image.
I used a trick to handle this:
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<View
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/textView"
android:layout_alignTop="#+id/textView"
android:background="#drawable/your_9_patch_image"/>
<TextView
android:id="#+id/textView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="a custom text!"/>
</RelativeLayout>
I have set the 9-patch background drawable for a View behind my TextView in a RelativeLayout. So the there is no unwanted padding :)
Theoretically you cant really change the padding of 9 patch image programatically.
So you have two options:
1) Have several 9 patch images in your drawable folder for each resolution: drawable-hdpi, drawable-xhdpi etc
2) Embed a inner layout:
<RelativeLayout
android:background="#drawable/nine_patch_image_without_padding"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_margin="10dp" // Your padding goes here
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:text="How you doing"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</RelativeLayout>
It worked for me. I use the second options as it is simpler and quicker to use :)
Ok here is the problem...
I have a image background that need some text and additional graphics on it. The background image needs to be in the center of the screen and may not stretch. Here is what i need to do:
The problem is that i need to align the text to the background image.
I've tried to wrap it all into a relative layout - something like this:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/bg_image"
android:layout_centerInParent="true"
android:src="#drawable/member_card"/>
<TextView
android:layout_height="wrap_content"
android:layout_alignLeft="#id/bg_image"
android:text="#string/membercard_info"
android:layout_marginTop="40dp"
/>
<TextView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_alignLeft="#id/bg_image"
android:layout_marginTop="200dp"
/>
</RelativeLayout>
This will not work since android adds additional padding to the image to avoid it from stretching.
Here is what happens in two different cases:
So how do I align the text to the background image?
I've solved this problem in the past in code by baking it all into one image,- but would like to do this in xml.
If you want to remove padding, you can use manually set it. However, if you want overlapping elements, you generally want to use FrameLayout. Look here: http://mobile.tutsplus.com/tutorials/android/android-sdk_frame-layout/
Set a gravity inside the frame layout to align it.
if you want an ImageView with additional layers drawn on top of that, see this thread: How to maintain multi layers of ImageViews and keep their aspect ratio based on the largest one?
There a padding around the image because you set the imageView size to fill its parent ( using match_parent )
You should try to set it to wrap its content :
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
.../>
EDIT : If your picture is bigger that the screen size, you need to have it scaled keeping the aspect ratio.
To do this, use match_parent in vertical with a scaleType to FIT_CENTER
and keep the wrap_content setting for the width ( since we want the image view left/right bounds stuck to the image content )
<ImageView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:scaleType="fitCenter"
.../>
Is this better ?
I am having scaling problems when using the 9-patch images for the background of EditText fields. I have a table which stretches the entire width, inside here I have the following tablerow which fills the width of the table.
The problem is that I am using a 9-patch image as the background but the edit text field is not stretching to the entire width, it only stretches to the width of the hint text.
<TableRow
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical|center_horizontal" >
<EditText
android:id="#+id/et_username"
android:contentDescription="#string/hint_enterUsername"
android:hint="#string/hint_enterUsername"
android:singleLine="true"
android:textSize="#dimen/edittext_textsize"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal|center_vertical"
android:background="#drawable/background_field_top" />
</TableRow>
I can see in the graphical view that the width of the row does stretch but the EditText field does not, as shown in the attached image
Has anyone any ideas on how to make the edittext stretch to the entire size? The following is the 9-patch image I'm using.
From Android Developers documentation on TableRow
A layout that arranges its children horizontally. A TableRow should
always be used as a child of a TableLayout. If a TableRow's parent is
not a TableLayout, the TableRow will behave as an horizontal
LinearLayout.
#Nipun Gogia answer is not correct, why put a TableRow (behaving like a Horizontal LinearLayout) inside a LinearLayout with only one EditText child?
You should instead place the EditText view as a direct child of the TableLayout, it will then be displayed as a single row that spans all the table columns. And you can add more TableRow's and Columns if you want.
Stretch a background image of a EditText View with Nine-Patch:
You need to edit the 9-patch rule of the 9.png file setting the stretchable area of the image, place the top rule (black 1px line) in the middle of the image, now it is only stretching at the transparent end leaving the image un stretched.
Learn how to her: http://developer.android.com/tools/help/draw9patch.html
Importent! remember to save the image with the extension .9.png
Nine-patch Image saved with file extension: background.9.png
Modified smaller image, it will look the same as the above because of the nine-patch rules.
Modified image, but with a non stretchable height.
Note: if downloading the images above with "save image as..", remember to add .9.png to the file name for it to work.
your is working fine for me ..i am using my own 9 patch... here is my code :
<LinearLayout
android:id="#+id/layout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TableRow
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical|center_horizontal" >
<EditText
android:id="#+id/et_username"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#drawable/areanumber"
android:gravity="center_horizontal|center_vertical"
android:singleLine="true"
android:text="hello" />
</TableRow>
</LinearLayout>
here areanumber is my 9 patch image... just try to wrap your code inside linearlayout
i implemented your 9 patch image and its also working fine
Make sure that your image file name is background_field_top.9.png (make sure that the .9. is there)
I made small changes to your image, so that the corner rounding is smoother, but that is not the core issue.
If this does not help, check if the background works well without the table, to isolate if the issue is the layout or the background image.
I've got following 9patch, which I got thanks to nice people who answered my previous question:
I use it for background in relative layout and TextView and got following.
Thats for RelativeLayout:
<RelativeLayout
android:id="#+id/relativeHeader"
android:layout_width="fill_parent"
android:layout_height="60dp"
android:orientation="horizontal"
android: background="#drawable/cap_stack">
And for TextView:
<TextView
android:paddingTop="5dp"
android:gravity="center_vertical"
android:layout_width="fill_parent"
android:layout_height="22dp"
android:background="#drawable/cap_stack"
android:textStyle="bold"
android:textColor="#FFFFFF"/>
As you can see, I got 1px wide line visible in both cases. And in case of TextView text is not placed in the center vertical. How can I fix it(is it drawable problem or xml)? Will appreciate any help
You shouldn't have a solid border all the way around. The top and left borders define the stretch areas (you only need one pixel on the top for stretching, and you want JUST the gradient to stretch on the vertical axis). The bottom and right borders define the content area, so you want to leave some padding as well. The four corner pixels should never be filled.
Try this one:
or this one:
try this for your textview, the problem is your layout_height You are wanting the textSize attribute instead. Also, notice I used the SP unit instead of DP as that is what the docs recommend for text size values. I hope this helps!
<TextView
android:paddingTop="5dp"
android:gravity="center_vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:textSize="22sp"
android:background="#drawable/cap_stack"
android:textStyle="bold"
android:textColor="#FFFFFF"/>
Did you named your image as cap_stack.9.png? It seems android is not processing it as 9patch.
android:gravity="center_vertical" works with LinearLayout Only , Use Layout_centerVertical=true for relativeLayout .
and that lines on border seems part of your image , not seeing any other possibility //////so rechecking image once might be helpful .
I have an ImageView, and I want it to be clickable. The image itself is only 32x32 pixels, but I want the clickable region to be larger so it's easier to hit. I was hoping I could set the layout margin values to increase the size of the imageview's clickable area:
<ImageView
layout_width="32dip"
layout_height="32dip"
layout_margin="20dip" />
That doesn't work, what I could do is just recreate the image resource to have a larger transparent region around it. That's a bit annoying because it's hard to tweak if I ever need to change the clickable region. It's not just a single png either, it's a statelistdrawable so I have to resize 3 different pngs if I ever need to tweak the clickable area.
Anything else I can do?
Thanks
Use padding. layout margins are used if for inserting space outside the boundary of the view.
for equal padding on all sides
<ImageView
android:padding="20dip" />
or to set the padding on each side
<ImageView
android:paddingLeft="10dip"
android:paddingRight="15dip"
android:paddingTop="23dip"
android:paddingBottom="12dip" />
Hope that helps !
Instead of resizing the image (Peter Knego's answer) or increasing padding (Saimon's answer) I suggest to set the minWidth and minHeight attributes in combination with scaleType="center":
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="40dp"
android:minHeight="40dp"
android:scaleType="center"
android:src="#drawable/your_image" />
That makes sure that small images have at least a size of 40x40dp while the image is not up-scaled if it's smaller. If one day the image is going to be replaced with another image larger than minWidth and minHeight it will not grow larger than 40x40dp as it gets downscaled. Thus a minimum clickable dimension of 40x40dp is always guaranted and the image is always displayed nicely.
Suggestions (never tried it myself):
Create ImageView as large as you want than put image into it without scaling
ImageView.setScaleType(ImageView.ScaleType.CENTER).
Brute force approach: create new larger png that has original image centered and the rest of it is transparent.
Use like below; where width/height is your touch radius
<ImageView
android:id="#+id/editProfile"
android:layout_width="32dp"
android:layout_height="32dp"
android:padding="8dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:src="#drawable/ic_edit"
android:scaleType="fitCenter"
/>
In the above code, I wanted my src size to be viewed as 24dp width/height. And touch radius of 32dp. so I had used padding of 8dp.