android - RelativeLayout is taking fullscreen for wrap_content

android - RelativeLayout is taking fullscreen for wrap_content

Sveinn Erland Author: Sveinn Erland Date: 2022-08-16
android - RelativeLayout is taking fullscreen for wrap_content

All you need to know about android - RelativeLayout is taking fullscreen for wrap_content , in addintion to android - FrameLayout vs RelativeLayout for overlays , android - match_parent property for children in a RelativeLayout , android - Background image for wrap_content , video processing - Taking photo every 66 milliseconds on Android phone for colour analysis (Heart Rate Monitor)

  1. android - RelativeLayout is taking fullscreen for wrap_content
  2. Question:

    Why does FOOBARZ get layed out all the way at the bottom when no elements are layout_height="fill_parent" in other words, all elements are wrap_content for height? enter image description here

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content">
        <TextView
            android:id="@+id/feed_u"
            android:layout_width="50dip"
            android:layout_height="50dip"
            android:layout_marginLeft="5dip"
            android:scaleType="centerCrop"
            android:drawableTop="@android:drawable/presence_online"
            android:text="U" />
        <RelativeLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_toRightOf="@id/feed_u">
            <ImageView
                android:id="@+id/feed_h"
                android:layout_alignParentRight="true"
                android:layout_alignParentTop="true"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@android:drawable/btn_minus" />
            <ImageView
                android:id="@+id/feed_ha"
                android:layout_toLeftOf="@id/feed_h"
                android:layout_alignParentRight="true"
                android:layout_alignParentTop="true"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@android:drawable/btn_plus" />
            <TextView
                android:id="@+id/feed_t"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Title">
            </TextView>
            <TextView
                android:id="@+id/feed_a"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Band"
                android:layout_below="@id/feed_t">
            </TextView>
            <TextView
                android:id="@+id/feed_s"
                android:layout_below="@id/feed_a"
                android:text="S"
                android:layout_height="wrap_content"
                android:layout_width="wrap_content">
            </TextView>
            <TextView
                android:id="@+id/feed_tm"
                android:layout_alignParentBottom="true"
                android:layout_alignParentRight="true"
                android:text="FOOBARZ"
                android:layout_height="wrap_content"
                android:layout_width="wrap_content">
            </TextView>
    
        </RelativeLayout>
    </RelativeLayout>
    


    Solution 1:

    From the RelativeLayout doc:

    Class Overview

    A Layout where the positions of the children can be described in relation to each other or to the parent.

    Note that you cannot have a circular dependency between the size of the RelativeLayout and the position of its children. For example, you cannot have a RelativeLayout whose height is set to WRAP_CONTENT and a child set to ALIGN_PARENT_BOTTOM

    Class documentation

    Which is exactly your case. RelativeLayout can not do that.

    Solution 2:

    For those looking for a solution to this, like I did, you can use FrameLayout instead of RelativeLayout.

    Then you can set the gravity the intended object to bottom right as below

    <TextView
        android:layout_gravity="bottom|right"
        android:text="FOOBARZ"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content">
    </TextView>
    

    Solution 3:

    You have set the RelativeLayout to "wrap_content" and the TextView to android:layout_alignParentBottom="true", so it automatically tries to stretch the RelativeLayout to the bottom. Don't use such dependencies with Relative Layout, as it can count as "circular dependencies".

    From the docs for RelativeLayout:

    Note that you cannot have a circular dependency between the size of the RelativeLayout and the position of its children. For example, you cannot have a RelativeLayout whose height is set to WRAP_CONTENT and a child set to ALIGN_PARENT_BOTTOM.

    Try to align your TextView to something other than the parent RelativeLayout, but watch out for this problem as well:
    Circular dependencies, need some help with exact code

    Alternatively, try to add more sophisticated inner layouts.

  3. android - FrameLayout vs RelativeLayout for overlays
  4. Question:

    I need to implement an overlay (translucent) screen for my app, something similar to Showcase View

    My guess was to use FrameLayout for this usecase, because it is used to stack items on top of each other. But I was surprised to see that the above library uses RelativeLayout.

    My question is when to use FrameLayout then, if not in cases like this? What are the disadvantages if I go the FrameLayout way?


    Solution 1:

    A common rule of thumb when choosing layouts is to select the combination that results in the smallest number of nested layout views.

    Specific to your question, RelativeLayout is larger and more capable than the much simpler FrameLayout. So for simple layouts, the latter is probably more efficient. But if using RelativeLayout and it's added positioning options allows you to implement your GUI in a smaller number of layout views, then that would likely be a better choice.

    Here's a page that discusses some trade-offs and demonstrates some helpful tools to use when designing your layouts. It mostly talks about RelativeLayout and LinearLayout, but is also apropos to your choice between RelativeLayout and Framelayout. Just keep in mind that FrameLayout is an even simpler layout.

    Edit (2017): For even more complicated layouts, you may be able to avoid nested layouts by using ConstraintLayout.

  5. android - match_parent property for children in a RelativeLayout
  6. Question:

    In short, is it possible to tell a child in a RelativeLayout to always match the height of that RelativeLayout regardless of how other children in that same RelativeLayout behave? In short, that's it. Details below.

    What I'm trying to achieve is a ListView row with at least three views, and one of those views would be kind of a stripe at the right side of the list entry (the red view below). The problem I'm having is that there is a TextView at the left side, and depeding on how much text I have, the stripe won't fill the whole layout. This is very clearly explained by images below.

    ListView item layout:

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">
    
    <View
            android:id="@+id/bottom_line"
            android:layout_width="match_parent"
            android:layout_height="5dp"
            android:layout_alignParentBottom="true"
            android:background="#fc0" />
    
    <!-- Why match_parent does not work in view below? -->
    <View
            android:id="@+id/stripe"
            android:layout_width="80dp"
            android:layout_height="wrap_content"
            android:minHeight="50dp"
            android:layout_alignParentRight="true"
            android:layout_alignParentTop="true"
            android:layout_alignParentBottom="true"
            android:background="#f00" />
    
    <TextView
            android:id="@+id/text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_toLeftOf="@id/stripe"
            android:text="This is a very long line, meant to completely break the match_parent property of the box at right"
            style="?android:textAppearanceLarge"/>
    
    </RelativeLayout>
    

    Result:

    RelativeLayout with child not filling the whole layout vertically

    Setting stripe and root height to match_parent makes no difference. I did it.

    Repeating the question, I want the red stripe to always fill the parent vertically. You can see stripe is not aligning to the top of root.

    A note: the above example is the simplest, self-contained example I can think of. It's just a ListActivity with an anonymous ArrayAdapter populated by a static String array. The relevant code in onCreate is at most 8 lines, so no worries there. It's really the layout. Besides, I have this working with nested LinearLayouts already, but I'm trying to reduce the depth of my layout structure a bit, if possible. LinearLayout works fine, as expected.


    Solution 1:

    I had the same requirement and my solution was to align the top of the red stripe to the parent's top, and the bottom of the stripe to the bottom of the text view on the left. The height in this case becomes irrelevant. You can either use wrap_content or match_parent.

    Solution 2:

    Solution 3:

    Try this:

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content">
    
        <View
            android:id="@+id/stripe"
            android:layout_width="80dp"
            android:layout_height="match_parent"
            android:layout_alignBottom="@id/text"
            android:layout_alignParentRight="true"
            android:layout_alignTop="@id/text"
            android:background="#f00"
            android:minHeight="50dp"/>
    
        <TextView
            android:id="@+id/text"
            style="?android:textAppearanceLarge"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_toLeftOf="@id/stripe"
            android:text="This is a very long line, meant to completely break the match_parent property of the box at right"/>
    
        <View
            android:id="@+id/bottom_line"
            android:layout_width="match_parent"
            android:layout_height="5dp"
            android:layout_below="@id/text"
            android:background="#fc0"/>
    
    </RelativeLayout>
    

    The align top and bottom of the red view is the same as textview now.

  7. android - Background image for wrap_content
  8. Question:

    I created a custom background image and wanted to use it as the background for a layout that has height of wrap_content. However, the total height of the contents of within that layout are much less than the height of the background image.

    When I set it as the background in XML via android:background="@drawable/image", I noticed that it displays the entire height of the image, although the height of the actual contents are much shorter.

    Is there a way to stop this from happening?

    Thanks.


    Solution 1:

    I had a similar problem and was using a 9patch. The full 9 patch image was showing as a background even though the content it was attached to wasn't that big (was using wrap_content). I'm not sure why Android chose to show the full image instead of scaling the background to fit the content.

    However, I fixed the problem by scaling down my background image. By that I mean preserving the corners but scaling down the vertical and horizontal portions. See the attached images of the background frame I had before and the result of the resize effort.

    alt text alt text

    Solution 2:

    I also faced this problem. If you set the background's resource is too small, you might have problems with aspect ratio. The solution I found was to divide the background's image in three parts: top, middle and bottom. Each of these images are backgrounds of three different Layouts/ImageViews. The middle part is the one that holds the "wrap_content" property:

    Top: bg_top

    Middle: bg_middle

    Bottom: enter image description here

    As the content's size increase, the borders will keep unaffected and the middle will increase as well (as will the whole "box"). Of course, this is a solution for a case that the partition of your background's image makes sense.

    Solution 3:

    You can convert your background image to 9-patch drawable or use XML bitmap to alter behavior of your image when it is greater then the container. See this page for more info about both.

  9. video processing - Taking photo every 66 milliseconds on Android phone for colour analysis (Heart Rate Monitor)
  10. Question:

    I'm doing a final year project at university which involves making a medical application for Android, as a practice I have to make a heart rate monitor app.

    I have worked out that the best way to do this is to look for colour changes in your blood when holding the camera against your finger with the flash switched on.

    This is where the problems come into play, is it possible to take a photo every 66 milliseconds on the camera, then compare each pair of photos for any intensity changes in order to count a heart beat? or am I better off recording a video and analysing each frame looking for a change.

    Heck is it even possible to just look at the video preview and compare each frame.

    The questions I need answering for this problem are neatly listed below

    • What is the best method for this, taking photos, recording video or looking at the live preview.

    • Is there any posts or pages I can visit on the internet where people have attempted similar things

    • Anyone got a basic method I should do to get two images that I can compare within the time frame.

    • Lastly If I do take the basic take a picture every 66 milliseconds approach, what can I do to ensure the picture is taken at the correct time intervals


    Solution 1:

    What is the best method for this, taking photos, recording video or looking at the live preview.

    I would think that live preview would be the right answer. Taking photos is not -- they will not happen anywhere near that quickly. Recording video and post-processing it would be possible, but I fail to see how this will be applicable for a real-time heart monitor.

    Is there any posts or pages I can visit on the internet where people have attempted similar things

    You can examine the Barcode Scanner source code, which uses the live preview to scan for barcodes.

    Lastly If I do take the basic take a picture every 66 milliseconds approach, what can I do to ensure the picture is taken at the correct time intervals

    Android is not a hard RTOS. AFAIK it will be impossible for you to precisely time things to be 66 milliseconds.