Unable to make child view wider than parent in Android Layout - android

I'm moving a view after an animation completes(to slide out a menu from the left). However, I don't seem to be able to achieve the effect I'm looking for. What I'd like is for the view to extend to the right past the parent's bounds, like this:
but what's happening is actually this:
The view resets itself to stay within the bounds of the parent. Even if I set an absolute pixel value (by looking at the display's width, or even a randomly large value).
The reason I need to do this is detailed in this SO question about a view's actual position after an animation has completed:
TranslateAnimated ImageView not clickable after animation [Android]
any thoughts? Thanks!

So, here is a related question. It explains how to move a view out of the screen.

I had same problem and I found the solution. I hope it can be helpful.
You need to set fixed width if you want to achieve this effect. To find real width of the view you need to measure it.
So full solution is:
view.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
int height = view.getMeasuredHeight();
int width = view.getMeasuredWidth();
view.setLayoutParams(new LinearLayout.LayoutParams(width, height));
(Use LayoutParams of the type corresponding the type of the parent layout)

Related

specify a location of a view without using margin in relative layout

I am new to Android and currently having some issues with layout. Here is my problem:
View view = (View)findViewById(R.id.MiddleMan);
view.layout(240,358,240+view.getWidth(),358+view.getHeight());
width is 2 dp, height is match_parent. This view is inside a relative_layout, which is inside a linear_layout. This coordinates are relative to linear_layout
When I run, instead of being exactly at this coordinate, it keeps sticking to the right edge of the parent. Can anyone show me how I can deal with this problem, pls ? Appreciate a lot

Best practice for getting View dimensions, possibly before they are drawn to screen

I've seen a ton of different questions and answers to the problems people are having with retrieving height and width of views, particularly this thread.
The following are mentioned methods to retrieve View dimensions:
onWindowFocusChanged() in your activity
Subclassing the type of view you're using and overridding either onSizeChanged(), onLayout(), or onMeasure()
Using a ViewTreeObserver and addOnGlobalLayoutListener()
Each of them seem to work in some cases, while in other cases people say something doesn't work correctly. Since there isn't a setOnDimensionsKnown(OnDimensionsKnown odk) or similar method for the View class, which of these methods (or possibly one not mentioned) will give me the dimensions my view will eventually have, regardless if it's drawn yet, has wrap_content or fill_parent parameters, or it has explicit height and width set in px, dp, or similar?
EDIT: Perhaps a specific example would be helpful, I'm trying to make a PopupWindow wrap it's contents, and to be offset in the -x direction by the value of it's width. The problem is that the contents width, and thus the popupwindows width, are not measured until after I show the popup. So basically I can't think of a good way to measure the width it will be before it is drawn to screen.
My usual approach is to override whatever view class I need the dimensions of before it being drawn, and create my own setOnDimensionsKnown(OnDimensionsKnown odk) method and fire it with the width and height values that onMeasure is called with. This works it every case I've needed, but it doesn't seem very elegant to override every view class to do this.
I can post code to help explain the example more.
Good way of doing it is adding an OnGlobalLayoutListener() to the view, as stated in this answer (point 3 in your question, in my opinion that's the most reliable for any View). The way I do it for a PopupWindow is to inflate it's layout and then call measure on it:
popupView = getActivity().getLayoutInflater().inflate(R.layout.popup_layout, null);
popup = new PopupWindow(popupView, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, true);
popupView.measure(view.getMeasuredWidth(), view.getMeasuredHeight()); //the view is parent's layout (not sure if those are correct values, but it measures okay in my case)
and then just get the numbers by calling popupView.getMeasuredHeight() and .getMeasuredWitdh().
Your problem is probably long gone by now, but hopefully someone else will stumble upon this and find it helpful. :)

Android: Placing Views as required

I have an application where I have to place a set of ImageViews in different parts of the screen, each ImageView placed at a position by specifying the co-ordinates(x,y) Is this possible in android? If so, pls let me know how to do it.
It is possible but not recommended since it doesn't work well across resolutions/densities/aspect-ratios.
This is possible by setting the positions in their xml layout in an absolutelayout. Though, if you want to change the position of the imageview in your code dynamically you can only change the positions by setting their margins and padding to move them left/right and up/down. The following receives the layout params of the imageviews so that you can change the views' margins.
ImageView image;
MarginLayoutParams params = (MarginLayoutParams)image.getLayoutParams();
param.setMargins(int left, int top, int right, int bottom);

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);

Categories

Resources