Set the absolute position of a view

280,673

Solution 1

You can use RelativeLayout. Let's say you wanted a 30x40 ImageView at position (50,60) inside your layout. Somewhere in your activity:

// Some existing RelativeLayout from your layout xml
RelativeLayout rl = (RelativeLayout) findViewById(R.id.my_relative_layout);

ImageView iv = new ImageView(this);

RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(30, 40);
params.leftMargin = 50;
params.topMargin = 60;
rl.addView(iv, params);

More examples:

Places two 30x40 ImageViews (one yellow, one red) at (50,60) and (80,90), respectively:

RelativeLayout rl = (RelativeLayout) findViewById(R.id.my_relative_layout);
ImageView iv;
RelativeLayout.LayoutParams params;

iv = new ImageView(this);
iv.setBackgroundColor(Color.YELLOW);
params = new RelativeLayout.LayoutParams(30, 40);
params.leftMargin = 50;
params.topMargin = 60;
rl.addView(iv, params);

iv = new ImageView(this);
iv.setBackgroundColor(Color.RED);
params = new RelativeLayout.LayoutParams(30, 40);
params.leftMargin = 80;
params.topMargin = 90;
rl.addView(iv, params);

Places one 30x40 yellow ImageView at (50,60) and another 30x40 red ImageView <80,90> relative to the yellow ImageView:

RelativeLayout rl = (RelativeLayout) findViewById(R.id.my_relative_layout);
ImageView iv;
RelativeLayout.LayoutParams params;

int yellow_iv_id = 123; // Some arbitrary ID value.

iv = new ImageView(this);
iv.setId(yellow_iv_id);
iv.setBackgroundColor(Color.YELLOW);
params = new RelativeLayout.LayoutParams(30, 40);
params.leftMargin = 50;
params.topMargin = 60;
rl.addView(iv, params);

iv = new ImageView(this);
iv.setBackgroundColor(Color.RED);
params = new RelativeLayout.LayoutParams(30, 40);
params.leftMargin = 80;
params.topMargin = 90;

// This line defines how params.leftMargin and params.topMargin are interpreted.
// In this case, "<80,90>" means <80,90> to the right of the yellow ImageView.
params.addRule(RelativeLayout.RIGHT_OF, yellow_iv_id);

rl.addView(iv, params);

Solution 2

In general, you can add a View in a specific position using a FrameLayout as container by specifying the leftMargin and topMargin attributes.

The following example will place a 20x20px ImageView at position (100,200) using a FrameLayout as fullscreen container:

XML

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/root"
    android:background="#33AAFF"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
</FrameLayout>

Activity / Fragment / Custom view

//...
FrameLayout root = (FrameLayout)findViewById(R.id.root);
ImageView img = new ImageView(this);
img.setBackgroundColor(Color.RED);
//..load something inside the ImageView, we just set the background color

FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(20, 20);
params.leftMargin = 100;
params.topMargin  = 200;
root.addView(img, params);
//...

This will do the trick because margins can be used as absolute (X,Y) coordinates without a RelativeLayout:

enter image description here

Solution 3

Just to add to Andy Zhang's answer above, if you want to, you can give param to rl.addView, then make changes to it later, so:

params = new RelativeLayout.LayoutParams(30, 40);
params.leftMargin = 50;
params.topMargin = 60;
rl.addView(iv, params);

Could equally well be written as:

params = new RelativeLayout.LayoutParams(30, 40);
rl.addView(iv, params);
params.leftMargin = 50;
params.topMargin = 60;

So if you retain the params variable, you can change the layout of iv at any time after adding it to rl.

Solution 4

A more cleaner and dynamic way without hardcoding any pixel values in the code.

I wanted to position a dialog (which I inflate on the fly) exactly below a clicked button.

and solved it this way :

    // get the yoffset of the position where your View has to be placed 
    final int yoffset = < calculate the position of the view >

    // position using top margin
    if(myView.getLayoutParams() instanceof MarginLayoutParams) {
        ((MarginLayoutParams) myView.getLayoutParams()).topMargin = yOffset;
    }

However you have to make sure the parent layout of myView is an instance of RelativeLayout.

more complete code :

    // identify the button
    final Button clickedButton = <... code to find the button here ...>

    // inflate the dialog - the following style preserves xml layout params
    final View floatingDialog = 
        this.getLayoutInflater().inflate(R.layout.floating_dialog,
            this.floatingDialogContainer, false);

    this.floatingDialogContainer.addView(floatingDialog);

    // get the buttons position
    final int[] buttonPos = new int[2];
    clickedButton.getLocationOnScreen(buttonPos);        
    final int yOffset =  buttonPos[1] + clickedButton.getHeight();

    // position using top margin
    if(floatingDialog.getLayoutParams() instanceof MarginLayoutParams) {
        ((MarginLayoutParams) floatingDialog.getLayoutParams()).topMargin = yOffset;
    }

This way you can still expect the target view to adjust to any layout parameters set using layout XML files, instead of hardcoding those pixels/dps in your Java code.

Share:
280,673

Related videos on Youtube

Sephy
Author by

Sephy

Free s/Lance/Spirit Frontender with a touch of backend culture (Fullstack :D ? ) Enjoys playing with all the crazy stuff going about the web platform (React, React Native, new Web APIs, Angular, NodeJs ...)

Updated on January 25, 2020

Comments

  • Sephy
    Sephy over 4 years

    Is it possible to set the absolute position of a view in Android? (I know that there is an AbsoluteLayout, but it's deprecated...)

    For example, if I have a 240x320px screen, how could I add an ImageView which is 20x20px such that its center is at the position (100,100)?

    • Drew LeSueur
      Drew LeSueur over 11 years
      also see view.setTranslationX() or view.offsetLeftAndRight()
    • Manuel
      Manuel about 11 years
      I've just released a library that may have been of interest here. github.com/ManuelPeinado/ImageLayout
    • edthethird
      edthethird over 9 years
      This is so difficult because 99.9% of the time absolute positioning is a bad idea on android. If you are writing an app that will ONLY ever be run on one physical device, then this might work, but that is generally not a safe assumption to make. For example, do not upload this to google play. It works fine on iOS because there are only a handful of hardware devices, and you can build a custom storyboard for each one.
    • William Jockusch
      William Jockusch over 9 years
      @edthethird, In my cross-platform app, I get the screen size and base everything on that. I just switched over to the "obsolete" AbsoluteLayout, and it works fine.
    • edthethird
      edthethird over 9 years
      fair enough, but that's what a Relative Layout or LinearLayout will do for you automatically.
    • Paul McCarthy
      Paul McCarthy about 7 years
      Why was AbsoluteLayout deprecated? Surely the need to place widgets in exact positions for certain apps has not gone away!
  • Sephy
    Sephy almost 14 years
    I'll have a go at that tonight, that's a pretty nice idea, don't know why I didn't think about that. As I have several ImageView to put, wouldn't it be better to use a FrameLayout?
  • Sephy
    Sephy almost 14 years
    Indeed this seems to work, however, it's only working when a add one picture this way. if I try to add a 2nd one, the first one just vanishes...
  • Andy Zhang
    Andy Zhang almost 14 years
    The two images are just on top of each other. I will add some code to my solution above to explain.
  • Sephy
    Sephy almost 14 years
    Yeah indeed, i found that yesterday too by digging your solution on my own. I also try stuff with the FrameLayout. My actual issue is that I have 5 images with each a random (x,y) position, so I can't use RelativeLayout.RIGHT_OF or something like that. The strange thing is that i can get 3 images to be placed properly but 2 of them aren't working...I don't understand... I'll update my post with some screenshots tonight and some code.
  • Andy Zhang
    Andy Zhang over 13 years
    The above method pretty much does the same thing as absolute position. If you have any other concerns, I'd be happy to help!
  • Nathan
    Nathan almost 13 years
    Why would using this method be any better than using AbsoluteLayout? Just because AbsoluteLayout is deprecated?
  • G_S
    G_S almost 12 years
    loved this sample. Can you suggest me how can i set the x,y axis when i am having the image in the xml layout.(i am trying to resize the image and i need to set the image at some position)
  • Excrubulent
    Excrubulent almost 12 years
    I'm afraid I don't quite understand what you're asking. Are you trying to access the LayoutParams object associated with an object that has been positioned using the XML layout? I'm not sure how that's done. It might be worth setting up a new question to have this answered, if you can't find the answer elsewhere.
  • G_S
    G_S almost 12 years
    please have a look at this question stackoverflow.com/questions/12028404/…
  • KumailR
    KumailR over 10 years
    @sephy for your situation you can have your each view set to parentleft and parentTop = true, and by setting x, y position to leftmargin and topmargin respectively.
  • KumailR
    KumailR over 10 years
    absolute layout is deprecated as because of different screen sizes. but with some calculation we can use absolute values to check whether one view on right,left,top,bottom of other view but for width and height sounds complicated; this way we can implement absolute behavior using relativelayout.
  • Lisa Anne
    Lisa Anne over 8 years
    Brilliant! Worth the 500! +1