Reputation: 1698
I would like to reproduce the following UI in my Android app but I have few questions.
RelativeLayout
ImageView
My attempt:
<?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="fill_parent"
android:orientation="vertical" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/CircleCenter"
android:layout_marginTop="120dp"
android:background="@drawable/CircleCenter"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/CircleLeft"
android:background="@drawable/CircleLeft"
android:layout_alignTop="@+id/CircleCenter"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="false"
android:layout_marginLeft="-70dp"
android:layout_marginTop="-20dp" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/CircleRight"
android:background="@drawable/CircleRight"
android:layout_alignTop="@+id/CircleCenter"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="false"
android:layout_alignParentStart="false"
android:layout_marginRight="-70dp"
android:layout_marginTop="-20dp" />
</RelativeLayout>
Question
I think it's not so bad, but there is one problem: how to have auto negative margin (with something like: marginRight = -(ImageView width/2) ?
Thanks!
Upvotes: 0
Views: 588
Reputation: 1698
Solution #1 (based on @Andros)
We need to do that programmatically.
Note: You cannot use the width/height/getMeasuredWidth/getMeasuredHeight on a view before the system does not render it (typically from onCreate/onResume). So we need to use a ViewTreeObserver
(code here).
View this example (I use RoboGuice to simplify the code):
import roboguice.inject.ContentView;
import roboguice.inject.InjectView;
@ContentView(R.layout.activity_foo)
public class FooActivity extends Activity {
@InjectView(R.id.CircleLeft)
private ImageView circleLeft;
@InjectView(R.id.CircleCenter)
private ImageView circleCenter;
@InjectView(R.id.CircleRight)
private ImageView circleRight;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ViewTreeObserver vto = circleLeft.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
RelativeLayout.LayoutParams paramsLeft = (RelativeLayout.LayoutParams) circleLeft.getLayoutParams();
paramsLeft.setMargins(-circleLeft.getMeasuredWidth()/2, -40, 0, 0);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
circleLeft.getViewTreeObserver().removeOnGlobalLayoutListener(this);
} else {
circleLeft.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
}
});
}
}
It's not perfect because I have to create a new ViewTreeObserver for imageViewRight...
Maybe there is a more efficient way to do that?
Edit :
Solution #2
Instead of using ViewTreeObserver
we can use .post(new Runnable()
:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
cicleLeft.post(new Runnable() {
@Override
public void run() {
RelativeLayout.LayoutParams paramsLeft = (RelativeLayout.LayoutParams) cicleLeft.getLayoutParams();
paramsLeft.setMargins(-cicleLeft.getMeasuredWidth()/2, -40, 0, 0);
}
});
}
Upvotes: 0
Reputation: 4069
Programmatically :
RelativeLayout.LayoutParams paramsLeft = (RelativeLayout.LayoutParams) mCircleLeft.getLayoutParams();
paramsLeft.setMargins(mCircleLeft.getMeasuredWidth()/2, marginTop, 0, 0);
// do the same thing for the right image
EDIT : If getMeasuredWidth()
is == 0 when you are executing the code, add a ViewTreeObserver, he is going to tell you when the view is rendered :
ViewTreeObserver vto = mCircleLeft.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
// execute the previous code here
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
obs.removeOnGlobalLayoutListener(this);
} else {
obs.removeGlobalOnLayoutListener(this);
}
}
});
Upvotes: 1