I just started using SpriteBuilder and was wondering if something like “autolayout” (in a basic form) was possible for the apps? You see I have made this simple layout ( http://cl.ly/Szs3 ) containing a header (blue-ish) and body (red).
Now what I want is that the header has a fixed height (it has 100% percent width, so that goes wel) and the red block “fills” the rest of the screen. So when the device is a taller device more content at once can be shown.
Is this possible? And if so, how could I acchieve this.
Yes there is such an option, yet the naming is a little bit different.
I uploaded my example project to this GitHub Repo: https://github.com/MakeGamesWithUs/Spritebuilder-Simple-Autosizing
Your top container needs a static height, and a relative position and a Y Anchor Point of 1. This way the top container always has a size of 100 points and is always positioned at the top of the screen:
Your bottom container needs a height inset of 100, this means your container will use the complete height of the parent container, except for 100 points at the top:
You can take a look at:
Auto Layout[About] Constraints
UIStackView
Related
I have two TextViews with dynamic content and thus dynamic widths I want to arrange next to each other horizontally using Android xml layouts.
If the sum of their intrinsic widths fits into the width of the container, they should each just take the space they need.
If the sum of their widths exceed the container's width, their widths should both be capped in certain ways.
Let's say our left view has a width of 400 and the right one has a width of 200. If the available space is 1000, then there should just be a space of 400 between them. But if there is only an available space of 500, then available space should be distributed:
corresponding to the intrinsic widths: 333, 167
or in a weighted way, for example 1 - 1: 250, 250
or spreading the left view maintaining a minimum width of 50 of the right view: 450, 50
All of these contraints seem to be easy to implement using a horizontal LinearLayout or a ConstraintLayout but it's actually hard to me to achieve both - allowing spreading in case of sufficient space an controlled reduction in case of insufficient space.
Basically, incorporation of WRAP_CONTENT breaks controlled reduction and not using WRAP_CONTENT breaks dynamic distribution of available space, as far as I found out yet.
Could you please provide a working solution?
PS: I don't want to use any custom or third party container view.
At the moment I'm playing a bit with the new ConstraintLayout and try to create the following layout:
(1) Headline: Type 24sp, Leading 32sp
(2) Subhead 1: Type 15sp, Leading 24sp
(3) 32sp line height
(4) 56dp padding between the top of button and the center of copy
(5) 24dp vertical padding
My problem now is that I do not know how I should handle the sizes which refer to the center of the second TextView. We do not have a constraint for the center (or baseline) to bottom or something like this. Also I'm not able to set a space between two views which are connected between the baseline points. So how should I create this layout with the ConstraintLayout?
Can someone please give me a sample layout from the picture above?
We only allow baseline to baseline, without margin for now. We might revisit this in the future, but as of ConstraintLayout alpha 7 you cannot do this. The only option is to align with top / bottom.
You could also add a view with a layout height as a divider, then reference the bottom of the divider
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.
Background
To learn animations, I'm creating a Towers of Hanoi type of game. My main goal is to animate the movement of the block from one tower to another. I've got the following layout
|------RelativeLayout------|
|-Linear-|-Linear-|-Linear-|
|-Block1-|-----------------|
|-Block2-|-----------------|
|-Block3-|-----------------|
|--------------------------|
ID| Tower1 | Tower2 | Tower3 |
I've set the XML attribute android:clipChildren="false" on every ViewGroup.
For example, if I tried to animate the movement of Block1 from Tower1 to Tower2 using Block1.animate().setDuration(3000).translationX(1000). As the layout is right now, Block1 will animate within Tower1, but Block1 gets clipped the second it leaves Tower1.
I've played with changing the z-order by adding the blocks last in the XML file. It doesn't reliably work, though.
To ensure animations don't get clipped, I've decided to add a copy of the Block1 (named copyBlock) to the root RelativeLayout, position copyBlock on top of Block1, and animate it to the destination Tower2 (defined in coordinates)
To get the destination coordinates, I was planning on adding an invisible copyBlock to Tower2, then get the coordinates. This way, I can take advantage of the LinearLayout's layout functions to account for matters such as padding, gravity, etc. Otherwise, I'll have to get the position of Tower2, calculate the topmost block, adjust the coordinates of Block1 so that it'll be on top of the topmost block and centered.
But, I'm pretty sure this way is hacky, and there's a better way
Questions
How can I get the above destination coordinates without having to add an invisible view to the destination tower? Is there a way to ask for a "prelayout" without having to add View to the layout?
Do you have any explanations for why the animation gets clipped? Is there a better way to approach this rather than adding a new view to the root RelativeLayout ViewGroup?
Ok,
1- You can't overcome the clipping issue, because you are trying to move the child beyond the parent dimensions, unless you are moving within the same parent.
2- Use FrameLayout instead of RelativeLayout so you can control views margins correctly;
3- You can get the destination coordinates by knowing the height of the root layout and width, its seems the towers width are equal, so the (total width/3) will give the cell width then get the X coordinate, and the (total height - cell height ) will give the Y coordinate of the tower ( assuming you have the tower hight)
The property android:layout_gravity="clip_vertical|horizontal" does the following as mentioned in the SDK documentation:
Additional option that can be set to
have the top and/or bottom edges of
the child clipped to its container's
bounds. The clip will be based on the
vertical gravity: a top gravity will
clip the bottom edge, a bottom gravity
will clip the top edge, and neither
will clip both edges.
But I can't see anything of this in my applications,
so what is the purpose of this property exactly ?
thanks
Short version:
clip_horizontal and clip_vertical apply to the measurements of the view itself, before any contents (such as the image in a BitmapDrawable) are rendered.
Long version:
I've run into some similar confusion over clip_horizontal and clip_vertical. (In my case, it was related to android:gravity for a BitmapDrawable, but it's similar enough to be applicable.)
From the documentation I thought that something like android:gravity="top|left|clip_vertical" on a bitmap would cause the image's top left corner to be positioned at the view's top left corner, and that, if the bitmap was taller than the view, it would be "clipped" at the bottom edge of the view. In other words, show only as much of the bitmap that the view is tall enough to reveal; do not stretch the bitmap, but instead only show whatever will fit, letting the rest extend below the bottom edge.
However, the opposite happened: when I set clip_vertical, a large bitmap was squished vertically to fit within the height of the view.
After examining the applyDisplay() method in platform/frameworks/core/java/android/view/Gravity.java, I realized my mistake:
It isn't the bitmap image that was going to be clipped, but the view -- the actual size of the container the image is ultimately rendered into.
Setting clip_vertical in my case didn't mean "clip the image at the bottom edge," it meant "clip the BitmapDrawable's view itself so its height matches the height of its parent container"...which then caused the image to be "squished" as it filled that shorter height.
So, the important thing to remember with android:gravity and android:layout_gravity is that clip_horizontal and clip_vertical apply to the measurements of the view itself, before any contents (such as my BitmapDrawable) are rendered.
Maybe there is no effect because horizontal is not defined in the android:layout_gravity. clip_vertical is just an additional property that is used in addition to a base property.
Flag to clip the edges of the object to its container along the horizontal axis.
check this