Android: Change absolute position of a view programmatically - android

If you use an AbsoluteLayout (I know that it is deprecated, but it was the only way to solve my problem) you can give the childViews the tag android:layout_x and android:layout_y to set their absolute position within the AbsoluteLayout.
However I don't want to set these information in the xml, because I only know them at runtime. So how can I set these parameters at runtime programmatically? I don't see any method on the View like view.setLayoutX(int x) or something.
Here is my XML, which works fine, when I set the layout_x and layout_y values:
<?xml version="1.0" encoding="utf-8"?>
<AbsoluteLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/myLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:src="#drawable/myImageView"
android:layout_width="1298px"
android:layout_height="945px"
android:layout_x="0px"
android:layout_y="0px" />
<Button
android:id="#+id/myButton1"
android:text="23"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_x="50px"
android:layout_y="300px"
android:tag="23"/>
<Button
android:id="#+id/myButton2"
android:text="48"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_x="50px"
android:layout_y="300px"
android:tag="48"/>
</AbsoluteLayout>
In fact, I don't want to set any button within the xml anymore, but rather retrieve some information via remote and add buttons depending on that information.
Here is the part the code I'm using so in my onCreateMethod to add these buttons:
for (MyRemoteObject remoteObject: list) {
Button button = new Button(this);
button.setOnClickListener (listener);
button.setTag(remoteObject.id);
button.setText(remoteObject.id);
// button.setLayoutX(remoteObject.x) ????
// button.setLayoutY(remoteObject.y) ????
myLayout.addView(button);
}

Use the version of addView that takes LayoutParams:
LayoutParams params = mLayout.generateLayoutParams();
params.x = remoteObject.x;
params.y = remoteObject.y;
mLayout.addView(button, params);

In response to your comment on Mayra's answer, I had a similar issue with RelativeLayout instead of AbsoluteLayout. The solution was to use a similar method and cast it as your layout type. Something like this:
LayoutParams params = (android.widget.RelativeLayout.LayoutParams) this.generateDefaultLayoutParams();
params.height = 360;
params.width = 360;
params.addRule(CENTER_IN_PARENT);
this.addView(board, params);
It took me forever to figure this out so I wanted to post it here for someone else if they needed it.

I had just the same problem but found a somewhat different solution.
int width = 100, height = 50, x = 10, y = 20;
Button button = new Button(this);
AbsoluteLayout myLayout = (AbsoluteLayout)findViewById(R.id.myLayout);
myLayout.add(button, new AbsoluteLayout.LayoutParams(width, height, x, y));
And if you find out what to use for "fill_parent" (hint try -1) then you may use those constants for width and height.

I don't know why, but when moving top and left edges the Android keeps the right and bottom edges in same place. As I could not change the width and height properly (the image was disappearing), I've used this:
LayoutParams layoutParams=new LayoutParams(width, height);
layoutParams.leftMargin = newLeft;
layoutParams.topMargin = newTop;
imageView.setLayoutParams(layoutParams);
I don't know if it's the best way, but worked for me. I've tested it in 2.2+ and works fine!
You must import android.widget.LinearLayout.LayoutParams; because the default is ViewGroup's LayoutParams (by Davit T)

the above answers are right.but this one would be more perfect
AbsoluteLayout.LayoutParams layoutParams = new AbsoluteLayout.LayoutParams(AbsoluteLayout.LayoutParams.WRAP_CONTENT,AbsoluteLayout.LayoutParams.WRAP_CONTENT,DragLayer.int left_location,int top_location);
layout.addView(view,layoutParams)

Related

What's alternative to deprecated AbsoluteLayout in Android?

I have a Xamarin project. I develop for IOS,Android and UWP. In my application, I have my manual layout logic for UI Elements. In IOS, I can use the frame property in order to set where the view is going to be rendered. I can do the same in UWP by using Canvas as the container and Canvas.Left,Canvas.Top properties to set x,y locations and my code has the logic to do the layout. I am confused about how to achieve this in Android. AbsoluteLayout seemed to be a perfect match, but it's deprecated. Can I achieve this with some other Layout or should I create my custom ViewGroup class?
You can use a FrameLayout and position items in it using the top and left margin. In XML it would look something like:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<View
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginLeft="100dp"
android:layout_marginTop="100dp"
/>
</FrameLayout>
If you want to set it from code then you can use the LayoutParams:
FrameLayout.LayoutParams param = (FrameLayout.LayoutParams) view.getLayoutParams();
param.leftMargin = 100;
param.topMargin = 100;
param.height = 50;
param.width = 50;
view.setLayoutParams(param);
Note that the values in code are pixels not dp so you would have to convert. I'm not sure how this would convert to Xaramin but it gives you the idea.
Either way you'll have to consider what will happen when a user with an unusual device size uses your app. The reason Android doesn't have much use for absolute layouts is that there are so many different device sizes/densities that they are usually impractical.
You can use Relative Layout/ Frame Layout / Custom Layout. instead of Absolute Layout, As Absolute layout is harder to maintain is the reason its depreciated.

android TableLayout with LinearLayout as cells - layout_margin is ignored

I have TableLayout. As each cell in Table Layout I have LinearLayout with few elements inside a nice border.
LinearLayout definition:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="2dp"
android:layout_marginBottom="2dp"
android:orientation="vertical"
android:background="?border_empty"
android:layout_weight="1"
>
Unfortunately layout_marginLeft and layout_marginBottom seems to be ignored. :-( I've even tried to set very high values ex. 15 dp. How to set more space between cells (I would prefer to set it on left and on bottom if possible)?
I saw your question yesterday but I wanted to wait until today to answer, because now I'm facing exactly the same issue.
I've tried using this (being fila my TableRow):
final TableLayout.LayoutParams trParams = new TableLayout.LayoutParams(TableLayout.LayoutParams.MATCH_PARENT, TableLayout.LayoutParams.WRAP_CONTENT);
trParams.setMargins(10, 5, 10, 5);
fila.setLayoutParams(trParams);
But as you comment, both left and right margins seem to be ignored. I finally managed it through the TextView itself, this way (being tv my TextView):
final LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) tv.getLayoutParams();
lp.rightMargin = 10;
lp.leftMargin = 10;
This seems to work perfectly.

How to create button at run time on specified location inside frame layout android?

I am trying to create button at runtime.I am getting the coordinate and height,width of button from backend and I have to create button at same location on run time.I have used following code.
Button btn=new Button(getApplicationContext());
btn.setText("CLICK ME");
#SuppressWarnings("deprecation")
AbsoluteLayout.LayoutParams param = new AbsoluteLayout.LayoutParams( 121, 58, 50, 50);
btn.setLayoutParams(param);
mParentView.addView(btn);
My xml is
<FrameLayout
android:id="#+id/frameView"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<ViewFlipper
android:id="#+id/viewFlipper"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
</ViewFlipper>
<fragment
android:id="#+id/header_fragment"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
class="com.sdei.presentationapp.activity.PresentationModeTopBar"
tools:layout="#layout/presentation_top_bar" />
</FrameLayout>
here the parentview is framelayout.
I am able to create the button but the problem is it is created always at top left corner,no matter what coordinate we pass.Please help.
Thanks in advance.
You cannot set button at your desired position in framelayout only possible in absolute layout. but you can use margin with respect to your left and top which will work like your (x, y) coordinates.
// First create your button:
Button test_button = new Button(getApplicationContext());
test_button.setText("test");
// Then create layout params for you buttons.
FrameLayout.LayoutParams lp = new LayoutParams(100, 100); // Button width and button height.
lp.leftMargin = 200; // your X coordinate.
lp.topMargin = 300; // your Y coordinate.
// Then find layout and add button on it.
FrameLayout layout = (FrameLayout) findViewById(R.id.FrameLayout1);
layout.addView(test_button, lp);
Hope this can help you.
I have not compile this code, so change as per your layout.
LinearLayout ll = new LinearLayout(this);
fl .setOrientation(LinearLayout.VERTICAL);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
layoutParams.setMargins(30, 20, 30, 0);
Button okButton=new Button(this);
okButton.setId(ok_id)
okButton.setText("some text");
See one reference link here
The absolute layout class is deprecated, you are encouraged to use Frame Layout or Relative layout instead.
The reason of that is it won’t be compatible with all the android phones as they have different screen sizes and resolutions.
Absolute layout lays widgets by specifying their exact X and Y positions. In android the origin (0,0) coordinate is located at the top left of the screen. By default, if you define any control in absolute layout without defining it’s x,y coordinates, it will be placed in the origin point at (x,y)=(0,0);
Thus your defined position for AbsoluteLayout.LayoutParams is not working properly.
As you are using FrameLayout then you can try the following way-
// declare and initialize LayoutParams for the framelayout
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.WRAP_CONTENT,
FrameLayout.LayoutParams.WRAP_CONTENT);
// decide upon the positioning of the button //
// you will likely need to use the screen size to position the
// button anywhere other than the four corners
params.setMargins(.., .., .., ..);
// use static constants from the Gravity class
params.gravity = Gravity.CENTER_HORIZONTAL;
btn.setLayoutParams(params);
mParentView.addView(btn);

Trying to move an ImageView in a touch event via setLayoutParams, imageview is not moving

I've got a small ImageView inside of a fullscreen FrameLayout, and I'd like to set it such that when I touch the FrameLayout, the imageview moves to that position.
I've read all the other SO questions I can find about moving ImageView but I haven't seen why my solution is not working yet.
In a custom view which extends FrameLayout:
#Override
public boolean onInterceptTouchEvent(MotionEvent event){
if(event.getActionMasked() == MotionEvent.ACTION_DOWN){
ImageView iv = (ImageView) this.findViewById(R.id.draggedImage);
FrameLayout.LayoutParams params = (LayoutParams) iv.getLayoutParams();
params.leftMargin = (int) event.getX();
params.bottomMargin = (int) event.getY();
iv.setLayoutParams(params);
iv.invalidate();
invalidate();
}
return true;
}
I've changed the layoutparams margin to reflect the new touch position, and invalidated the imageview and framelayout (not sure which of these I should be doing), but the imageView doesn't budge (just sits always in the top left corner of the frame).
I've also verified that this method is being called when I touch the screen and the params is getting set with sane X and Y values.
My layout:
<CustomFrameLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<!-- some other unrelated views -->
<ImageView
android:id="#+id/draggedImage"
android:layout_width="100dp"
android:layout_height="100dp"
android:src="#drawable/pause" />
</CustomFrameLayout>
Edit:
Should have mentioned that I'm trying to target API level 10, so I can't use any of the Honeycomb view orientation goodness :(
Through trial and error and searching found that I was missing this call:
params.gravity = Gravity.LEFT | Gravity.BOTTOM;
Initially the gravity was just -1, so the margins had no effect, because it didn't know which side it was supposed to be basing the margins from. Adding a gravity gives it a side to anchor to so that it can be moved out by the amount in the margin.
Works perfectly now.
I believe that you want to set the top and left padding. See the following question which explains it better than I could. Difference between a View's Padding and Margin
I think that:
iv.setLayoutParams(params);
Is just Setting the params to iv´s layout which is the FrameLayout itself.
You might be able to set ImageView´s Position by iv.setX(); iv.setY();
I found Tim's solution of:
params.gravity = Gravity.LEFT | Gravity.BOTTOM;
to change a view's margin, only became necessary when running on devices with android level 10 or less!
The problem didn't show up on levels 14 or 17.
Adding the above code gave the desired behavior on all android levels... Thank you Tim.

How do you change the size of an ImageView?

I have setup my ImageView like the following:
<ImageView android:id="#+id/dl_image"
android:layout_width="60dp"
android:background="#drawable/pictureframe"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:adjustViewBounds="true"
android:scaleType="fitCenter"/>
Notice that layout_width is fixed to 60dp. Depending on the content that I acquired online, I want to resize this width to 90dp, or 120dp (while maintaining the aspect ratio of the image).
I tried using setLayoutParams, but passing LayoutParams(120, LayoutParams.WRAP_CONTENT) throws an exception. It doesn't seem to like it.
If possible, I am trying to avoid making another ImageView for larger sizes.
If you're working with an existing view it can be a lot of work creating a new set of LayoutParams from scratch. Instead - you can grab the view's existing LayoutParams, edit these, and then apply them to the view to update its LayoutParams using setLayoutParams()
ImageView imageView = findViewById(R.id.dl_image);
LayoutParams params = (LayoutParams) imageView.getLayoutParams();
params.width = 120;
// existing height is ok as is, no need to edit it
imageView.setLayoutParams(params);
Make sure you import the correct type of LayoutParams. For this case, as you commented, you can just use the LayoutParams of a ViewGroup. If you were setting parameters specific to a certain type of view (e.g. alignments in RelativeLayouts) you would have to import the LayoutParams of that type of view.
you can do it all like
ImageView imageView = findViewById(R.id.dl_image);
imageView.getLayoutParams().width = 120;

Categories

Resources