I am new to android animation and i've been playing with animation in android.
But one thing i just don't get it?
how to set position in tag.
My question is what 50%p means?
Suppose I have a button at some place 1/3 of the top. now i want to move it to bottom of the layout.then move to left bottom then at the center of the layout.
the doc says
Float or percentage. Starting X/Y offset. Expressed either: in pixels relative to the normal position (such as "5"), in percentage relative to the element width (such as "5%"), or in percentage relative to the parent width (such as "5%p").
once see this doc. This will help you to solve your issue.
In Android, one used ScrollView as the root in an XML file, then include many other different kinds of views inside it, that allowed the scroll behavior.
How does Swift 2.1 and Xcode 7.1.1 do this, since the storyboard is not long enough to insert all the different kinds of views I want to put in, like I did in the XML code for Android?
I am thinking iOS with an Android brain :(
0 lines of code
Storyboard is long enough:
All you need to do is to create a freeform view, put all your content is that freeform view using top-to-bottom Autolayout constraints, and use that view as the content of your UIScrollView.
Tutorial
View Controller > Show the Attributes inspector > Size > Freeform
View Controller > Show the Size Inspector > Simulated Size > Freeform > width & height
Add a UIScrollView
Add 4 AutoLayout constraints, with top/left relative to superview, and bottom/right of superview relative to scrollview
Scroll.Top = Superview.Top Margin
Scroll.Leading = Superview.Leading
Bottom Layout Guide.Top = Scroll.Bottom
Scroll.Trailing = Superview.Trailing
Add a UIView as a subview to UIScrollView
Repeat 4 AutoLayout constraints, same rule: anchored top, superview relative to subview width/height
Content.Top = Scroll.Top
Content.Leading = Scroll.Leading
Scroll.Bottom = Content.Bottom
Content.Trailing = Scroll.Trailing
Add all subviews to that UIView. Ensure you can trace an AutoLayout chain of constraints all the way from top to bottom (and left to right) with again the same rule as 4. and 6. anchored top & superview.width and superview.height relative to content.
Vertical height of your content view is handled by 7. For the width, and in this example, I decided to go full width. Notice how the Content view's width is relative to the root view width:
Content.width = View.width
Methodology
Create a hierarchy of views using the following structure:
root UIView (the one owned by the UIViewController
UIScrollView scroller (must stretch with relationship to the root)
content UIView (which will dictate the scroller scroll bars & area)
everything else goes into the content view
Understand what dictates the size of the content
either hard sizes
either relationship to contained views (continuous constraints)
either relativity to superviews
Understand the the edge-to-edge AutoLayout constraint continuity rule
You should be able to follow a continuous set of constraints top-to-bottom or left-to-right for the directions that will define the size of en enclosing view
You do not need such continuity for merely locating elements ; in fact, continuity where you do not need it may create conflicts
to make the enclosure size relative to the enclosed views (what you are trying to achieve vertically in your example):
attach the fist top view to a rigid location
attach each view underneath to the object above it
attach the bottom of the enclosure to the bottom of the last object
► Find this solution on GitHub and additional details on Swift Recipes.
There is a scroll view for iOS also in the interface builder object library:
Start to finish here is how to make it work in storyboard.
1: go to you view controller and click on Attribute Inspector.
2: change Size to Freeform instead of Inferred.
3: Go to the main view on that storyboard, not your scrollview but
rather the top level view.
4: Click Size Inspector and set this view to your desired size. I
changed my height to 1000.
Now you will see that you storyboard has your view setup so you can
see the entire height of your scroll for easy design.
5: Drop on a scrollview and stretch it so it takes up the whole view.
You should now have a scrollview with size of 320,1000 sitting on a
view in your view controller.
Now we need to make it scroll and need to make it show content
correctly.
6: Click on your scrollview and click on Identity Inspector.
7: Add a User Defined runtime attribute with KeyPath of contentSize
then type of SIZE and put in your content size. For me it is (320,
1000).
Since we want to see our whole scroll view on the storyboard we
stretched it and it has a frame of 320,1000 but in order for this to
work in our app we need to change the frame down to what the visible
scrollview will be.
8: Add a runtime attribute with KeyPath frame with Type RECT and
0,0,320,416.
Now when we run our app we will have a visible scrollview has a frame
of 0,0,320, 416 and can scroll down to 1000. We are able to layout our
subviews and images and whatnot in Storyboard just the way we want
them to appear. Then our runtime attributes make sure to display it
properly. All of this without 1 line of code.
Is this what you were thinking of?
If you want the scroll view to change size I would recommend trying this:
You want to do is drop the scroll view onto the view controller and and add constraints.
I have never used a scroll view before, so this might not work.
I have a custom imageView and I change it's background drawable at runtime. Images don't have the same height and when a resource have higher height, the top margin does not update itself (if top margin is 2 dp and after I set another resource as background which is higher with 2 do, the top margin becomes 0 because layout hasn't updated). How to force layout to update itself at runtime and not schedule a layout pass in the future? I've tried with:
imageView.invalidate()
imageView.requestLayout()
imageView.forceLayout()
parent.updateViewLayout(imageView, layoutParams)
but none of these methods works. The layout is updated only after I switch device's orientation. Do you have any ideas how to force layout to be refreshed at runtime?
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);
In a few words, I want to scale view - in the same way that Android Market does it, when you click the "More" button, on the for examplae 'Description'.
I figure it out, that the Android Market has the layout of following structure :
<FrameLayout
android:id="#+id/artists_frame"
android:layout_width="fill_parent"
android:layout_height="64dip"
android:layout_below="#id/something1"
android:layout_above="#id/something2"
>
<!-- Some view there, which height >> 64dip -->
</FrameLayout>
So, I've tried various Animations / LayoutAnimations on the FrameLayout (via view.setAnimation(), view.setLayoutAnimation() and ScaleAnimation), but the effect is always the same : the view animates, but it's real layout_height after scaling is still the same (so the position of the other views, that depend on the given FrameLayout, remain the same).
After that, I've thought - I change in the loop the layout_height of the given FrameLayout:
layoutParams = view.getLayoutParams()
layoutParams.height = scaleTo;
layout.setLayoutParams(layoutParams);
I've it got animating, market-like view, but the cost (performance!!!) is way to high...
So, the question is : Is there any other, proper way to scale (change e.g. height from 50dip to 200dip) the given View / ViewGroup so that the position of the views below the animating view also changes?
As Chet Haase says in this blog post: http://android-developers.blogspot.com/2011/02/animation-in-honeycomb.html
"...Finally, the previous animations changed the visual appearance of the target objects... but they didn't actually change the objects themselves..."
Since what your need is only visual, instead of changing the view's LayoutParameters I would animate the view in the bottom as well with a translate using android:fillAfter for both.