2

I am rendering a View into a Bitmap. I need a balloon with a pointer at the top or at the bottom, based on if it fits on the screen. For that I use a RelativeLayout, because I need the pointers to be partially over the balloon:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    >

    <LinearLayout android:id="@+id/balloon_body"
        android:layout_width="@dimen/pins_details_balloon_width"
        android:layout_height="wrap_content"
        android:layout_marginTop="-1dp"
        android:layout_marginBottom="-1dp"
        android:layout_below="@+id/pointer_top"
        android:orientation="vertical"
        >

        <TextView android:id="@android:id/title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="4dp"
            />

        <TextView android:id="@android:id/text1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="4dp"
            />

    </LinearLayout>

    <ImageView android:id="@id/pointer_top"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />

    <ImageView android:id="@+id/pointer_bottom"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/balloon_body"
        />

</RelativeLayout>

I inflate this view and then I want to measure and layout it, so I can render it into a bitmap:

view.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT));
//view.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT));
view.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
//view.measure(View.MeasureSpec.makeMeasureSpec(3000, View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(3000, View.MeasureSpec.AT_MOST));
view.layout(0, 0, s_View.getMeasuredWidth(), s_View.getMeasuredHeight());

This code crashes on the view.measure(...) with the Circular dependencies cannot exist in RelativeLayout error. I tried different LayoutParams (without setLayoutParams(...) the measure(...) crashes with a null pointer exception), different View.MeasureSpec-s but no success. If I remove the android:layout_below="@id/balloon_body" in the last ImageView, it works, but the bottom pointer is at the top.

I cannot use a LinearLayout, because I need those pointers to be above the body of the balloon, where with LinearLayout the top pointer will be below it. Where is the problem and how can I achieve what I want?

shelll
  • 3,234
  • 3
  • 33
  • 67

4 Answers4

2

The problem is caused because there is a circular reference in the layout parameters.

For example, when view B is layout_below view A, view A can't reference view B anymore in it's below, alignRight etc. This can also exist between multiple views: A references B references C. In that scenario C can't reference A because of a circular dependency.

For more info, go to: Circular dependencies cannot exist in RelativeLayout, android?

Hope it Helps!

Shreshth Kharbanda
  • 1,777
  • 14
  • 24
0

Try this.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>

 <ImageView android:id="@id/pointer_top"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    />
<LinearLayout android:id="@+id/balloon_body"
    android:layout_width="@dimen/pins_details_balloon_width"
    android:layout_height="wrap_content"
    android:layout_marginTop="-1dp"
    android:layout_marginBottom="-1dp"
    android:layout_below="@+id/pointer_top"
    android:orientation="vertical"
    >

    <TextView android:id="@android:id/title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="4dp"
        />

    <TextView android:id="@android:id/text1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="4dp"
        />

</LinearLayout>
<ImageView android:id="@+id/pointer_bottom"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@id/balloon_body"
    />

Pankaj Singh
  • 2,241
  • 2
  • 16
  • 16
  • You should consider swapping ` – karllindmark Jan 04 '13 at 12:42
  • @Pankaj Singh That will make the same problem as a `LinearLayout`, that the top pointer will be below the balloon and not above it. – shelll Jan 04 '13 at 12:48
  • @shelll replace above ImageView to this – Pankaj Singh Jan 04 '13 at 12:50
  • Both of the `ImageView`s must be below the ` – shelll Jan 04 '13 at 12:53
  • @shell above xml is fine bcoz i have seen the LinearLayout is in middle of both imageview – Pankaj Singh Jan 04 '13 at 12:57
  • Yes it is vertically between the imageviews. But it has negative top and bottom margins, so the imageviews overlap it. If I re-order the elements in the XML, like you propose, then the first imageview will not overlap the linearlayout, but the linear layout will overlap the imageview. Its because the order of the elements in the XML defines their Z-order. – shelll Jan 04 '13 at 13:01
0

if you are using circle shape background (drawable shape) in your relative layout it will throw that error

remove that shape or change layout

saigopi.me
  • 14,011
  • 2
  • 83
  • 54
0

Circular dependencies mean two consecutive views depending on each other in terms of position.

For example:

 <android.support.v4.view.ViewPager
    android:id="@+id/viewPager"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@+id/tabs"
    android:layout_above="@id/orderpaylayout"
    />

<Button
    android:id="@+id/orderbutton"
    android:layout_width="match_parent"
    android:layout_height="60dp"
    android:layout_margin="20dp"
    android:layout_centerInParent="true"
    android:background="@drawable/orderbuttonstyle"
    android:text="@string/order"
    android:textSize="16sp"
    android:textStyle="bold"
    android:visibility="gone" />

<Button
    android:id="@+id/paybutton"
    android:layout_width="match_parent"
    android:layout_height="60dp"
    android:layout_centerInParent="true"
    android:text="@string/Pay"
    android:textColor="#ffffff"
    android:textSize="16sp"
    android:visibility="gone"
    android:layout_below="@id/viewPager
    android:textStyle="bold"
    android:layout_margin="20dp"
    android:background="@drawable/paybuttonstyle"
    />

In the above XML, there are three views. First View ViewPager is depending on order button as layout_above = orderButton. Once the top view or bottom view depends on other views, reverse/backward dependency cannot occur i.e., two views cannot depend on each other simultaneously.

The Correct XML code for the above wrong example is:

 <android.support.v4.view.ViewPager
    android:id="@+id/viewPager"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@+id/tabs"
    android:layout_above="@id/orderpaylayout"
    />

<RelativeLayout
    android:id="@+id/orderpaylayout"
    android:layout_width="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_height="wrap_content">

<Button
    android:id="@+id/orderbutton"
    android:layout_width="match_parent"
    android:layout_height="60dp"
    android:layout_margin="20dp"
    android:layout_centerInParent="true"
    android:background="@drawable/orderbuttonstyle"
    android:text="@string/order"
    android:textSize="16sp"
    android:textStyle="bold"
    android:visibility="gone" />

<Button
    android:id="@+id/paybutton"
    android:layout_width="match_parent"
    android:layout_height="60dp"
    android:layout_centerInParent="true"
    android:text="@string/Pay"
    android:textColor="#ffffff"
    android:textSize="16sp"
    android:visibility="gone"
    android:textStyle="bold"
    android:layout_margin="20dp"
    android:background="@drawable/paybuttonstyle"
    />
</RelativeLayout>

Hope, this example will help you. If u consider this as correct one, upvote for others benefits or if it is wrong or doesn't work, put your comments.

Pradeep
  • 798
  • 1
  • 7
  • 18