Relative Layout: Different behavior on Api < 11 - android

I don't know why, but layout is shown well on device with Api 11+, isn't for older.
This is xml:
<LinearLayout
android:id="#+id/workers_linearlayout"
android:layout_width="50dp"
android:layout_height="70dp"
android:layout_weight="1" >
<RelativeLayout
android:id="#+id/workers_relative_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center" >
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="#drawable/workers_small" />
<ImageView
android:id="#+id/imageView3"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:scaleX="0.5"
android:scaleY="0.5"
android:src="#drawable/ic_cerchio_rosso"
android:translationX="25dp"
android:translationY="-20dp" />
<TextView
android:id="#+id/workers_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="9"
android:textAppearance="?android:attr/textAppearanceMedium"
android:translationX="25dp"
android:translationY="-20dp" />
</RelativeLayout>
</LinearLayout>
This is result on API 11+:
This on API 10-:
I tried to fix it playing with layouts and I can obtain a quite good result, but never like the first one.
Can someone help me?
EDIT:
Photo on devices:
EDIT2
Triangle warning are:
String "9" should use string resource
ImageView1 and 3: missing content description attribute
RelativeLayout or it's parent possibly useless
Nested weights are bad for performance
By the way, nothing of these fixed solving my problem i think

Ok. I fixed it. Playing with the layout and following NikkyD's suggestion about "center in parent" feature, I followed this policy:
It's not possible to use scale and translation properties because older Apis (maybe) don't recognize them. So, I deleted translation and scaling options and scaled image by setting a fixed height and width for IV3 (30dpx30dp). Now dimension is right, but if I call "align parent Top" with "align parent Right" for IV3 and TextView, their position is good, but TextView is not positioned at the center of IV3. Exactly like this:
For fixing it, I added a new relative layout inside "workersRelativeLayout" and I put inside it IV3 and TextView and set, for each one, "center in the parent" to TRUE. Then, I set for a new relative layout "align parent Top" and "align parent Right". This is the final result:
This is new xml layout:
<LinearLayout
android:id="#+id/workers_linearlayout"
android:layout_width="50dp"
android:layout_height="70dp"
android:layout_weight="1" >
<RelativeLayout
android:id="#+id/workers_relative_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center" >
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="#drawable/workers_small" />
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true" >
<ImageView
android:id="#+id/imageView3"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_centerInParent="true"
android:src="#drawable/ic_cerchio_rosso" />
<TextView
android:id="#+id/workers_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="9"
android:textAppearance="?android:attr/textAppearanceMedium" />
</RelativeLayout>
</RelativeLayout>
</LinearLayout>
Hope this helps someone :)
EDIT
Pay attention to parent width size. If you set weight's parent to 1, naturally size is dynamic according to display size. The image is positioned always at the center parent and relative Layout of IV3 and TextView will be always top|right. So if parent width size grows, the distance between image centered and new relative layout grows too, and can happen something like this:

The first LinearLayout has a weight. If it has a weight, then it needs to have one dimension set to 0dp, that would be the dimension in which it is scaled by its weight.
All 3 elements of the Relative Layout have "centeredinparent" true. The parent is the RelLayout.
IV3 has a height of match_parent, so it will be stretched to the height of the rel-layout. I am pretty sure that this overrides your scale 0.5 options.
Im not that sure but id guess the rel-layout centeredinparent overrides the translation as well.
Layouts are VERY ugly with options. Some are considered superior to others and they dont take effect. I played around a fair bit of time with relative layouts and found out, that in my case i could only arrange them with "below" but never "above" because for some reason the above positioning would not work (not even in the eclipse preview!!) but there was absolutely nothing wrong with the xml.
So im guessing some of your options overrule the others and this comes to bear on more modern APIs as they might be even more restrictive (or more broken, its still android ;) )

Related

Replacing image without influencing frame

Here is a small gif of my current situation. I guess many images are better than many words.
As you notice, when I switch for the smaller image, the seekbar size changes. I know this is because of the seekbar's width being set to match_parentand the image's width to wrap_content.
What I don't know is how to overcome this problem, as I can't really hardcode width value otherwise it'll probably get messed up on various screensizes.
So my question is :
Is there a way to prevent this behaviour that is clean? I could simply get the width at runtime and set it as minimal width and it would probably work (heck, I could try it now to make sure), but that is just a horrible thing to do code-wise.
Ideally, I'm guessing there is a way to prevent this in the .xml file, but I couldn't figure it out, playing with the different paddings, margins, scaling and layout sizes.
Here is what you're looking at :
<RelativeLayout
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="0dp">
<ImageButton
android:background="#android:color/transparent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="center"
android:id="#+id/playButton"
android:layout_alignParentLeft="true"
android:layout_marginLeft="30dp"
android:layout_centerVertical="true"
android:src="#drawable/play"
android:onClick="PlayButtonClicked" />
<SeekBar
android:max="100"
android:id="#+id/volumeSeekBar"
android:layout_centerVertical="true"
android:layout_margin="15dp"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_toRightOf="#+id/playButton"
android:layout_toLeftOf="#+id/muteButton" />
<ImageButton
android:background="#android:color/transparent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="center"
android:id="#+id/muteButton"
android:layout_alignParentRight="true"
android:layout_marginRight="30dp"
android:layout_centerVertical="true"
android:onClick="MuteButtonClicked"
android:src="#drawable/sound" />
</RelativeLayout>
Ideally it would be nice for the volume icons to be of the same size.
If that is not an option, try replacing android:layout_toLeftOf="#+id/muteButton" with android:layout_marginRight="15dp+30dp+largest_icon_width_in_dp"
where 15dp is your seekbar right margin, 30dp is the mute button right margin.
The third option would be to set a fixed width for the mute button equal to the width of the largest image.

Same position of Buttons on Image with all screen resolutions

I'm trying to stick some ImageButtons on specific positions on ImageView.
the problem is that i have to use absolute layout for the ImageButtons, and when I change the screen resolution all the ImageButtons moving from their places.
I've looking for an answer in all the web and just can't find anything.
Thank you.
I recommand you to not use absolute position in your layout. Use containers and some margins if you can to put your buttons at the right position.
If you really need absolute position depending on device, you can use specific dimensions for each kind of resolution. See here:
http://developer.android.com/training/basics/supporting-devices/screens.html
Just use relative layout instead of absolute layout. if you dont like relative layout, you may use absolute layout, there is nothing wrong with it, its just not practical in most situations. You may use absolute layout and scale the views on the screen with something like this: Scale a view and its layered subviews relatively
Dianne Hackborn (works at google) says:
I'll say again: we are not going to remove AbsoluteLayout from a future release, but we strongly discourage people from using it.
If you choose to not believe me, you are welcome to, but I am not responsible for you making that decision.
This is how to overlay buttons:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/RelativeLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:src="#drawable/image" />
<Button
android:id="#+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginBottom="34dp"
android:layout_marginRight="40dp"
android:text="Button" />
<Button
android:id="#+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignRight="#+id/button2"
android:layout_below="#+id/button1"
android:layout_marginRight="37dp"
android:layout_marginTop="108dp"
android:text="Button" />
</RelativeLayout>

Android - layout_weight makes image clickable on the sides

I have a layout of 3 images. I assigned weights to each of them to control
the width they allocate.
The problem is that the weight makes all the width of the image
clickable, when I want the clickable area to be the image only, how can i achieve that?
This is the relevant part of the layout:
<ImageView
android:id="#+id/1"
android:layout_gravity="left|center_vertical"
android:paddingBottom="5dp"
android:layout_weight="1"
android:layout_width="40dp"
android:layout_height="40dp"/>
<ImageView
android:id="#+id/2"
android:layout_gravity="left|center_vertical"
android:src="#drawable/2"
android:paddingBottom="5dp"
android:layout_weight="1"
android:layout_width="40dp"
android:layout_height="40dp"/>
<ImageView
android:id="#+id/3"
android:gravity="center"
android:layout_gravity="right"
android:src="#drawable/3"
android:layout_weight="9"
android:layout_width="40dp"
android:layout_height="40dp"/>
Thanks!
Probably the easiest solution would be to wrap each ImageView into a container, e.g. a simple FrameLayout. You then set the weights on the container rather than the ImageView itself. That way the container will scale, but the images (and hence the clickable area) won't. The downside is that this introduces an extra layer in your view hierarchy.
An alternative could be to check at runtime whether the selection was on the 'visible' area of the image. It will mean more work for you, but potentially less for the system, although the difference is probably marginal at best.

RelativeLayout: layout_marginLeft inconsistent behaviour

Context: I have a widget which basically consists of a RelativeLayout wrapping a bunch of TextViews. Here's what I want the widget to visually look like, followed by the the XML Layout code:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/alarm_widget_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<TextView
android:id="#+id/alarm_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:text="8:30"
android:textSize="40sp"
/>
<TextView
android:id="#+id/alarm_am_pm"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#id/alarm_time"
android:layout_marginLeft="2dp"
android:layout_alignTop="#id/alarm_time"
android:textSize="18sp"
android:text="AM"
/>
<TextView
android:id="#+id/alarm_days"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_below="#id/alarm_time"
android:textSize="16sp"
android:text="M T W T F S S"
/>
<TextView
android:id="#+id/toggle_indicator"
android:layout_height="8sp"
android:layout_width="80sp"
android:layout_below="#id/alarm_days"
android:layout_centerHorizontal="true"
android:background="#drawable/toggle_button_oval"
/>
</RelativeLayout>
Question: I'm stumped with the inconsistent behaviour of layout_marginLeft in the following scenarios:
When these widgets are stacked vertically inside a LinearLayout, the AM/PM text in the top-right requires android:layout_marginLeft="15dp" to look like it does in the picture above.
However, when the widgets are stacked in a 2x2 TableLayout, the AM/PM text requires android:layout_marginLeft="2dp" to look correct.
Why am I seeing this inconsistent behaviour? What does layout_marginLeft use as it's "origin"?
Since you are using a vertical LinearLayout (orientation = vertical), android:layout_marginLeft will take the extreme left of the screen as origin, thereby requiring a large dip value ~15. However, if you would have been using orientation = horizontal, the origin would be the end of the element just before your am_pm, and hence you would require a smaller dip value ~2.
Similar is the case with Relative nd Tabular Layout. Since while using RelativeLayout, you have mentioned android:layout_toRightOf="#id/alarm_time", the origin will be the end of alarm_time, thereby requiring a smaller dip value.

How do I vertically align an item within a list using relative layout?

I am using a list view in Android 1.5 to show a list of images and text next to the image. I am trying to vertically center the text but the text is at the top of the row instead of centered. Below is my layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/row"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="10dip">
<ImageView android:id="#+id/item_image" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:paddingRight="10dip"
android:src="#drawable/default_image" android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_alignParentBottom="true"
android:layout_centerVertical="true"
android:gravity="center_vertical"/>
<TextView android:id="#+id/item_title"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_toRightOf="#id/item_image"
android:layout_alignParentTop="true"
android:layout_alignParentBottom="true"
android:layout_centerVertical="true"
android:gravity="center_vertical"
/>
</RelativeLayout>
It seems strange that I need to set alignParentTop="true" when I'm trying to vertically center the text, but if I don't the text does not even show up. What am I doing wrong?
EDIT following the comments:
It turns out making this work with RelativeLayout isn't easy. At the bottom of the answer I've included a RelativeLayout that gives the effect wanted, but only until it's included in a ListView. After that, the same problems as described in the question occurred. This was fixed by instead using LinearLayout(s).
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:orientation="horizontal">
<ImageView android:id="#+id/pickImageImage"
android:layout_width="100dp"
android:layout_height="80dp"
android:background="#drawable/icon"
android:scaleType="fitXY"
android:layout_marginRight="10dp"/>
<TextView android:id="#+id/pickImageText"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:gravity="left|center_vertical"
android:text="I'm the text"/>
</LinearLayout>
If you want to have two text boxes, you can nest a second orientation="vertical" and LinearLayout after the ImageView and then put the text boxes in there.
This works, but I have to admit I don't know why the RelativeLayouts didn't. For example, this blog post by Romain Guy specifically says that the RelativeLayout should. When I tried it, I never got it to quite work; admittedly I didn't do it exactly as he did, but my only changes were with some attributes of the TextViews, which shouldn't have made that much of a difference.
Here's the original answer:
I think you're confusing Android with all those somewhat contradictory instructions in RelativeLayout. I reformatted your thing to this:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/row"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="10dip">
<ImageView android:id="#+id/item_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="10dip"
android:src="#drawable/icon"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"/>
<TextView android:id="#+id/item_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#id/item_image"
android:layout_centerVertical="true"
android:text="Blah!"/>
</RelativeLayout>
And that works fine. I removed many of your redundant android:layout_alignParentxxx because they weren't necessary. This view now comes up with the picture in the top left corner and the text vertically centered next to it. If you want the picture vertically centered as well, then you can't have the RelativeLayout be on android:layout_height="wrap_content" because it's trying to make itself no taller than the height of the picture. You'd have to specify a height, e.g. 80dp, and then set the ImageView to a fixed height like 60dp with android:scaleType="fitXY" to make it scale down to fit properly.
Was stuck on a similar issue for a while, but found this from CommonsWare:
"When you inflate the layout, use inflate(R.layout.whatever, parent, false), where parent is the ListView."
Works but only when you set the height of the row to a specific value (ie you can't use wrap_content).
Baseline directive would do it, but ImageView simply does not support baseline alignment as of today. You can work around this by creating a subclass of ImageView, override the getBaseline() method and return the height of the image.

Categories

Resources