Alternative to AbsoluteLayout in Android? - android

If AbsoluteLayout is deprecated what can I use instead of it?
I've done an app that uses AbsoluteLayout but it doesn't work well with the different screen resolutions. I use because I can set the X and Y position of a button. Can I set the position of a button using another layout?

you can use RelativeLayouts as described here: Set the absolute position of a view

Use RelativeLayout and set left and right margins like
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
lp.leftMargin = x;
lp.topMargin = y;

Consider using FrameLayout. If you set your child gravity to TOP|LEFT then you can use leftMargin and topMargin as the positions. As a bonus you get a few other useful positioning mechanisms by changing the gravity.

I will suggest you guys if you want to have full control over the positions of your views on the screen just to extend ViewGroup and make your own implementation of AbsoluteLayout. The easiest solution will be to use one of the existing Layouts and play with margins, paddings, gravity and so on, but the control is not gonna be so powerful and can cost some problems on the diff device screens.

I would just use a relative layout and set it based off of the other items/edges of the screen. Otherwise your layout appears different on different devices.

Related

Android/XML: Is there a way to set images in specific places, rather than relative? Can they be set to scale properly when on a bigger device?

I have several images, that need to be in specific places, but remain separate images. For example, imagine I have an image of a face. The separate images would be the nose, the eyes, the lips, etc...
I need them in specific places on the face. The problem is two-fold:
1: I need to put them in specific locations. Relative layout doesn't seem to work super well. Unless I type the margin gaps in exactly.
2: The other issue is when I change to a different device, it screws up the positioning. If I manually enter in margins, when I move to a tablet, everything is screwed up again.
What is the best way to accomplish this?
You can create nested Linear layouts , include your components and use android:layout_weight in each of them .If you have high alignment constraints , create a separate layout for each component and accordingly use android:orientation in it. This way you won't have any positioning issues when you switch devices .
FYR
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
layoutParams.gravity = Gravity.LEFT|Gravity.TOP;
layoutParams.leftMargin = x;
layoutParams.topMargin = y;
imageView.setLayoutParams(layoutParams);

How can I dynamically set the position of view in Android?

How can I change the position of view through code? Like changing its X, Y position. Is it possible?
For anything below Honeycomb (API Level 11) you'll have to use setLayoutParams(...).
If you can limit your support to Honeycomb and up you can use the setX(...), setY(...), setLeft(...), setTop(...), etc.
Yes, you can dynamically set the position of the view in Android. Likewise, you have an ImageView in LinearLayout of your XML file. So you can set its position through LayoutParams.But make sure to take LayoutParams according to the layout taken in your XML file. There are different LayoutParams according to the layout taken.
Here is the code to set:
LayoutParams layoutParams=new LayoutParams(int width, int height);
layoutParams.setMargins(int left, int top, int right, int bottom);
imageView.setLayoutParams(layoutParams);
There are different valid answers already, but none seems to properly suggest which method(s) to use in which case, except for the corresponding API level restrictions:
If you can wait for a layout cycle and the parent view group supports MarginLayoutParams (or a subclass), set marginLeft / marginTop accordingly.
If you need to change the position immediately and persistently (e.g. for a PopupMenu anchor), additionally call layout(l, t, r, b) with the same coordinates. This preempts what the layout system will confirm later.
For immediate (temporary) changes (such as animations), use setX() / setY() instead. In cases where the parent size doesn't depend on WRAP_CHILDREN, it might be fine to use setX() / setY() exclusively.
Never use setLeft() / setRight() / setBottom() / setTop(), see below.
Background:
The mLeft / mTop / mBottom / mRight fields get filled from the corresponding LayoutParams in layout(). Layout is called implicitly and asynchronously by the Android view layout system. Thus, setting the MarginLayoutParams seems to be the safest and cleanest way to set the position permanently. However, the asynchronous layout lag might be a problem in some cases, e.g. when using a View to render a cursor, and it's supposed to be re-positioned and serve as a PopupMenu anchor at the same time. In this case, calling layout() worked fine for me.
The problems with setLeft() and setTop() are:
Calling them alone is not sufficient -- you also need to call setRight() and setBottom() to avoid stretching or shrinking the view.
The implementation of these methods looks relatively complex (= doing some work to account for the view size changes caused by each of them)
They seem to cause strange issues with input fields: EditText soft numeric keyboard sometimes does not allow digits
setX() and setY() work outside of the layout system, and the corresponding values are treated as an additional offset to the left / top / bottom / right values determined by the layout system, shifting the view accordingly. They seem to have been added for animations (where an immediate effect without going through a layout cycle is required).
There is a library called NineOldAndroids, which allows you to use the Honeycomb animation library all the way down to version one.
This means you can define left, right, translationX/Y with a slightly different interface.
Here is how it works:
ViewHelper.setTranslationX(view, 50f);
You just use the static methods from the ViewHelper class, pass the view and which ever value you want to set it to.
I would recommend using setTranslationX and setTranslationY. I'm only just getting started on this myself, but these seem to be the safest and preferred way of moving a view. I guess it depends a lot on what exactly you're trying to do, but this is working well for me for 2D animation.
You can try to use the following methods, if you're using HoneyComb Sdk(API Level 11).
view.setX(float x);
Parameter x is the visual x position of this view.
view.setY(float y);
Parameter y is the visual y position of this view.
I hope it will be helpful to you. :)
For support to all API levels you can use it like this:
ViewPropertyAnimator.animate(view).translationYBy(-yourY).translationXBy(-yourX).setDuration(0);
Set the left position of this view relative to its parent:
view.setLeft(int leftPosition);
Set the right position of this view relative to its parent:
view.setRight(int rightPosition);
Set the top position of this view relative to its parent:
view.setTop(int topPosition);
Set the bottom position of this view relative to its parent:
view.setBottom(int bottomPositon);
The above methods are used to set the position the view related to its parent.
Use LayoutParams.
If you are using a LinearLayout you have to import android.widget.LinearLayout.LayoutParams, else import the proper version of LayoutParams for the layout you're using, or it will cause a ClassCastException, then:
LayoutParams layoutParams = new LayoutParams(int width, int height);
layoutParams.setMargins(int left, int top, int right, int bottom);
imageView.setLayoutParams(layoutParams);
NB: Note that you can use also imageView.setLeft(int dim), BUT THIS WON'T set the position of the component, it will set only the position of the left border of the component, the rest will remain at the same position.
Use RelativeLayout, place your view in it, get RelativeLayout.LayoutParams object from your view and set margins as you need. Then call requestLayout() on your view. This is the only way I know.
In Kotlin you can do it as below;
view
.animate()
.x(50f)
.y(100f)
.duration = 500L
I found that #Stefan Haustein comes very close to my experience, but not sure 100%. My suggestion is:
setLeft() / setRight() / setBottom() / setTop() won't work sometimes.
If you want to set a position temporarily (e.g for doing animation, not affected a hierachy) when the view was added and shown, just use setX()/ setY() instead. (You might want search more in difference setLeft() and setX())
And note that X, Y seem to be absolute, and it was supported by AbsoluteLayout which now is deprecated. Thus, you feel X, Y is likely not supported any more. And yes, it is, but only partly. It means if your view is added, setX(), setY() will work perfectly; otherwise, when you try to add a view into view group layout (e.g FrameLayout, LinearLayout, RelativeLayout), you must set its LayoutParams with marginLeft, marginTop instead (setX(), setY() in this case won't work sometimes).
Set position of the view by marginLeft and marginTop is an unsynchronized process. So it needs a bit time to update hierarchy. If you use the view straight away after set margin for it, you might get a wrong value.
One thing to keep in mind with positioning is that each view has an index relative to its parent view. So if you have a linear layout with three subviews, the subviews will each have an index: 0, 1, 2 in the above case.
This allows you to add a view to the last position (or the end) in a parent view by doing something like this:
int childCount = parent.getChildCount();
parentView.addView(newView, childCount);
Alternatively you could replace a view using something like the following:
int childIndex = parentView.indexOfChild(childView);
childView.setVisibility(View.GONE);
parentView.addView(newView, childIndex);

How to set fixed size and position of a RelativeLayout?

Android implemented a default layout rule, like measure, layout, etc, I didn't find out there is a method to set such a fixed size. How to get rid of that default layout behavior?
Actually, in my case, every view is supposed to be relative to its parent, and will have a specified size., how could I do?
Thx
Not sure if I correctly understood your issue, but you can specify size of certain View (e.g. RelativeLayout, LinearLayout or certain control). In Properties of your layout view (Layout width, Layout height) you do not need to use only wrap_content or fill_parent. You are also allowed to type size like 40dip.
If you created your View dinamically, then you should set LayoutParams. For example, to define your element size and margins for RelativeLayout (similar for others) you should use something like:
RelativeLayout.LayoutParams adaptLayout = new RelativeLayout.LayoutParams(element_width, element_height);
adaptLayout.setMargins(marginLeft, marginTop, marginRight, marginBottom);
mLinearLayoutForm.setLayoutParams(adaptLayout);

Android - How to draw a letter at a specific point?

I want to fill the screen with a 100 different letters in random positions. On the iPhone I just created a bunch of UILabels set their x and y positions and then used animations to move them about.
On Android it doesn't look like I can add a TextView to my view and specify its X and Y. Is there a way to do this?
View gameView = findViewById(R.id.gameboard);
tv = new TextView(gameView.getContext());
tv.setText("A");
tv.setWidth(w); tv.setHeight(h);
// How to set the X and Y?
EDIT: The solution was to use AbsoluteLayout:
AbsoluteLayout al = (AbsoluteLayout)findViewById(R.id.gb_layout);
tv = new TextView(this);
AbsoluteLayout.LayoutParams params = new AbsoluteLayout.LayoutParams(
AbsoluteLayout.LayoutParams.WRAP_CONTENT,
AbsoluteLayout.LayoutParams.WRAP_CONTENT,10,10);
params.x = 50;
params.y = 50;
al.addView(tv, params);
and to move it base on MotionEvent me:
AbsoluteLayout.LayoutParams p = new AbsoluteLayout.LayoutParams(
AbsoluteLayout.LayoutParams.WRAP_CONTENT,
AbsoluteLayout.LayoutParams.WRAP_CONTENT,(int)me.getX(), (int)me.getY());
mTV.setLayoutParams (p);
I think you are making a game and for this you should look into SurfaceView here is an good example then
1...if you look into code there is onDraw method where you will get the width of screen and height
2...Now taking this width and height as seed for random generator get x and y position.
3...Iterate through point 2 100 times and you will get the desired result
You can use a FrameLayout for this. Set each TextView's background to transparent and add it to the FrameLayout. Make each TextView, and the FrameLayout, fill their parent. The FrameLayout places all its child views at (0,0). To move letters around, just change the top and left padding of the corresponding TextView.
In android positioning child views is the responsibility of the layout class.
You need to create a custom.layout and overide the onLayout method. In this method you can iterate through all the child views calling View.layout(left,top,right,bottom) on each child.
i found this example code whilst trawling the net :
https://gist.github.com/882650
You should also check out view.setTranslationX (and Y) which might be exactly what you need
I'm not entirely sure how you'd go about doing this in code, but you need to use an absolute layout as your root element. (edit: Do not use absolute layout, as it was pointed out that it is deprecated. The closest alternative seems to be RelativeLayout.)
The properties in the XML format for the absolute layout coordinates are layout_x and layout_y.
edit: A little research is saying you need to be using setLayoutParams, but my Eclipse IDE is not working properly, so unfortunately I can't test exactly what you're looking for.

How do I achieve square layout and buttons in main.xml?

I would like to have a layout with 5 times 5 buttons. Each of them should have the same width and height (they should be square). And I want the whole matrix to use the screen width (or height, depending on rotation).
I currently do it "by hand" in the Java code:
for (int y=0; y<5; y++) {
TableRow tr = new TableRow(this);
for (int x=0; x<5; x++) {
Button b = new Button (this);
...
tr.addView(b, 60, 60);
}
layout.addView(tr);
}
This can be improved by obtaining screen width first and then dividing by 5 to get rid of this literal 60. But I'm wondering how I can do this in the res/layout XML file?
How can I specify for the height to be the same as the width? (I can set the width to match_parent.)
You are best off just doing this as a custom layout manager. Subclass from ViewGroup and implement the desired layout code. It is quite simple to implement a custom layout manager if you are trying to do a general-purpose layout algorithm (which you aren't).
See for example the platform's AbsoluteLayout as an example of a simple layout manager: https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/widget/AbsoluteLayout.java
I've two ideas.
Both are pretty similar to suggestion from hackbod
Instead of implementing subclass from ViewGroup, you can create something like SquareButton extending Button or SquareTableLayout extending TableLayout.
Override constructor class, so that you will replace the width or height value with the smallest value of them both. I'm not sure, but i guess, you'll be able to use new Layouts in XML-Description.
Probably it's easier to create just a SquareTableLayout
Then just set width and height of all elements within TableLayout to 0dip and the weight of all of them to 1.
Assuming that you have NxN elements in your Table, they all will get then the same width and the same height because of the same weigth.
Use Tables... that way all the buttons are same width. you can change height accordingly
You'll want to check out a TableLayout.

Categories

Resources