Is it possible to keep a view on top of a another view while Core Animation is running on it?
I am sliding views in and out from the top and bottom. Currently, the view that is sliding out slides over the top of every other view that is currently visible, I'd like to know if I can make a view stay on top of the animation effects.
Here is an example of one of the animations I have now:
CATransition *push = [CATransition animation];
push.type = kCATransitionPush;
push.subtype = kCATransitionFromTop;
[self.grid.layer addAnimation:push forKey:kCATransition];
// Changes to the view here
[CATransaction commit];
The view I want to keep visible does not overlap the original position of the view that is sliding out.
This is an ASCII diagram of the layout of the screen:
+------------------------------+
| View I want to keep on top |
|------------------------------|
| |
|------------------------------|
| View that will slide up |
| ^ ^ ^ ^ ^ ^ |
| |
| |
| |
| |
| |
| |
+------------------------------+
After a bunch of playing around, I've realised that CoreAnimation respects the natural stacking order of UIViews. This means that if a view was added after the one being animated, it will be placed on top and the animation will happen behind it.
To alter the stacking order of the views, I can use the following messages:
- (void)bringSubviewToFront:(UIView *)view;
- (void)sendSubviewToBack:(UIView *)view;
The stacking order functions and behaviours of UIViews are detailed in other questions and answers.
Related
stackView
+------------+ +
| topView | height: 50 |
+------------+ |
| | |
| | | total height: 300
| bottomView | height: 250 |
| | |
| | |
+------------+ +
I would like to layout two views (topView and bottomView) in a UIStackView (stackView) with these conditions:
stackView has a height (let’s say 300)
topView’s and bottomView’s intrinsic content height is the same (let’s say 50)
topView’s should be rendered with its intrinsic content height (up to stackView’s height) (so 50)
bottomView should take the remaining space (so 250)
if topView’s intrinsic content height changes (let’s say to 100) the distribution should be 100/200
None of the distribution modes of UIStackView can cover this.
Setting a constraint with a constant wouldn’t help here, as the intrinsic content height of topView might change.
So I need some Auto Layout features here. I tried setting different content compression resistance priorities and content hugging priorities. Without success, I still feel like they could be a solution (if I knew how to use them correctly).
It doesn’t seem like a complex problem, I can’t find the right Auto Layout API for this. Any hints?
You should set:
vertical content hugging priority of top view to be more than bottom view
alignment of stack view to fill
distribution of stack view to fill
You should add a width constraint as well, if the top and bottom views do not have intrinsic width.
Demo:
I have a UIView containing:
UIButton: (contentMode = Aspect Fit)
UILabel:(numberOfLines = 0, lineBreakMode = byWordWrapping, contentMode = Aspect Fill)
UISwitch: ()
I would like the width and number of lines of the UILabel to adapt to the content of the localized text of UIButton and UILabel.
How should I proceed ?
Behavior expected:
____________________________________________________________________
| | | |
| UIButton | UILabel | UISwitch |
| | | | |
_________________________________v__________________________________
Fred
You will have to give it the required constraints in order to make it fit as you like. You need to provide more details, in order for me to tell you about the constraints you would want. With current information assuming that your button and switch have fixed widths, and are pinned at leading and trailing of superview end respectively. then go through a check of following constraints
(1) give leading constraint of your label equal to trailing constraint of button
(2) give trailing constraint of your label equal to leading constraint of switch
(3) give top and bottom constraint of your button equal to top and bottom constraint of label
(4) give top and bottom constraint of your switch equal to top and bottom constraint of label
Finally, provide a constraint for the y position of your label, and you are good to go.
Another potential solution is using a horizontal stack view, which will save a lot of these constraints.
Here is what I tried... but the size of my button is not as small as possible (I expext it to fit the text)
So, I have added these constraints
NSLayoutConstraint.activate([
resetButton.leadingAnchor.constraint(equalTo: bottomView.leadingAnchor),
resetButton.trailingAnchor.constraint(equalTo: rawLabel.leadingAnchor),
rawLabel.trailingAnchor.constraint(equalTo: directSwitch.leadingAnchor),
directSwitch.trailingAnchor.constraint(equalTo: bottomView.trailingAnchor),
resetButton.topAnchor.constraint(greaterThanOrEqualTo: bottomView.topAnchor),
rawLabel.topAnchor.constraint(equalTo: bottomView.topAnchor),
directSwitch.topAnchor.constraint(greaterThanOrEqualTo: bottomView.topAnchor),
resetButton.bottomAnchor.constraint(lessThanOrEqualTo: bottomView.bottomAnchor),
rawLabel.bottomAnchor.constraint(equalTo: bottomView.bottomAnchor),
directSwitch.bottomAnchor.constraint(lessThanOrEqualTo: bottomView.bottomAnchor),
resetButton.centerYAnchor.constraint(equalTo: bottomView.centerYAnchor),
rawLabel.centerYAnchor.constraint(equalTo: bottomView.centerYAnchor),
directSwitch.centerYAnchor.constraint(equalTo: bottomView.centerYAnchor)
])
and this viewWillAppear func
override func viewWillAppear(_ animated: Bool) {
resetButton.sizeToFit()
rawLabel.numberOfLines = 0
rawLabel.lineBreakMode = .byWordWrapping
rawLabel.preferredMaxLayoutWidth = bottomView.frame.width - resetButton.frame.width - directSwitch.frame.width
}
I have a scrollview with 5 image views of width 88.
I want the scrollview to scroll to each image view (Not Paging)
and
I want to make an infinite scrollview in iPhone which means the when it scroll to last item it will display a first item next to it..
I have been trying by offset but it stops when move it by offset and also I have used apple street scroller which does not allow me to stop each element in center(just like Picker view)..
First of all, I recommend to use a UITableView so you can maintain the memory usage low. An approach that I had used successfully in a project is the following:
1. List item
Duplicate the content of your cells, I mean if you have 5 items in this way:
| 1 | 2 | 3 | 4 | 5 |
You should add the same (In a table view with reusable engine that's not a big deal) at the end of the table in order to look like this:
| 1 | 2 | 3 | 4 | 5 | 1 | 2 | 3 | 4 | 5 |
2. modify the scrollViewDidScroll with the following:
-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if (scrollView == _yourScrollView) {
CGFloat currentOffsetX = scrollView.contentOffset.x;
CGFloat currentOffSetY = scrollView.contentOffset.y;
CGFloat contentHeight = scrollView.contentSize.height;
if (currentOffSetY < (contentHeight / 6.0f)) {
scrollView.contentOffset = CGPointMake(currentOffsetX,(currentOffSetY + (contentHeight/2)));
}
if (currentOffSetY > ((contentHeight * 4)/ 6.0f)) {
scrollView.contentOffset = CGPointMake(currentOffsetX,(currentOffSetY - (contentHeight/2)));
}
}
}
The code above move the scroll position at top if you almost reach the final of the scrolling; Or if you are almost on the top, moves you to the bottom...
3. That's it.
You can have a look at one of this two options:
If you are registered as a developer, watch the session Advanced ScrollView Techniques from WWDC 2011.
A great tutorial from http://mobiledevelopertips.com/user-interface/creating-circular-and-infinite-uiscrollviews.html
This caused me serious problems for a long time so I really feel your pain. I found this control which should solve your problem: http://www.cocoacontrols.com/platforms/ios/controls/infinitescrollview
I also considered inserting transitions and disabled scroll so it becomes like a slideshow but either way should work.
Here is a short explanation of solution I used to do it.
Lets say you have counter from 0 - 9, then, when you make transition 9 -> 0, you actually spoof another 0 (call it 0') after 9 (in scrollView), make animated transition to 0' and than make non-animated instant transition to 0 that stands on top of scrollView.
You can use iCarousel library for this.
https://github.com/nicklockwood/iCarousel
For anybody else looking for a solution, you can also try this library Infinite Scroll Picker at https://github.com/Seitk/InfiniteScrollPicker/ It's basically drag and drop. I'm using it on a project and it works great.
Implemented a simple infinity scroll in this mini project:
https://github.com/mcmatan/Infinity-tabBar-scroll-view/blob/master/README.md
I'm writing a Gtk+ menu bar following the instruction here.
When packing the bar onto a VBox with
// "FALSE, TRUE" and "FALSE, FALSE" actually makes no difference
gtk_box_pack_start(GTK_BOX(main_vbox), menu_bar,
TRUE, FALSE, 0);
the menu bar looks terrible, like this:
And when I changed to:
gtk_box_pack_start(GTK_BOX(main_vbox), menu_bar,
TRUE, TRUE, 0);
it looks like:
So, how to make the toolbar get a smaller space allocated?
If I understand your question correctly, you want to:
Get rid of the light gray padding around the menu bar.
Do the above without expanding the menu bar to fill the available space.
Therefore, the packing mode of your other widget (namely the button bar below your menu bar) comes into play (for clarity, I'll refer to them as button_hbox and menu_bar, respectively, since both can qualify as "toolbars").
Understanding the boolean layout arguments passed to gtk_box_pack_start() is paramount here:
The first one, expand, is TRUE if the widget should consume the empty space left in its container after layout is computed. Widgets packed this way compete equally for the remaining space.
The second one, fill, is TRUE if the widget should fill the layout space it consumes instead of being centered within it (there comes the light gray padding).
The idea is that you have one (or more, but let's stick to one for now) main widget in main_vbox, and that widget is packed with both expand and fill set to TRUE. The satellite widgets around it are packed with expand set to FALSE and fill set to TRUE. For instance:
+-------------------------------------------+
| Menu bar: expand = FALSE, fill = TRUE |
+-------------------------------------------+
| Toolbar: expand = FALSE, fill = TRUE |
+-------------------------------------------+ ^
| | |
| | | The height of this widget
| Main widget: expand = TRUE, fill = TRUE | | varies depending on the
| | | height of its container.
| | |
+-------------------------------------------+ v
| Status bar: expand = FALSE, fill = TRUE |
+-------------------------------------------+
In your case, since you don't want menu_bar to fill the available space, button_hbox should do so:
// Menu bar: satellite widget, expand = FALSE, fill = TRUE
gtk_box_pack_start(GTK_BOX(main_vbox), menu_bar, FALSE, TRUE, 0);
// Button bar: main widget, expand = TRUE, fill = TRUE
gtk_box_pack_start(GTK_BOX(main_vbox), button_hbox, TRUE, TRUE, 0);
I'm working on my first video game for the Android platform as a bit of a nights and weekends project.
It is coming along nicely, but I am very unhappy with the control sensativity.
In this game, you move an object left and right on the screen. On the bottom of the screen is a "touchpad" of sorts, which is where your finger should rest.
/-------------------------\
| |
| |
| |
| Game Area |
| |
| |
| |
| |
| |
/-------------------------\
| |
| Touch Area |
| |
\-------------------------/
I am currently using a state variable to hold "MOVING_LEFT, MOVING_RIGHT, NOT_MOVING" and am updating the location of the player object each frame based on that variable.
However, my code that reads the touchscreen input and sets this state variable is either too sensative, or too laggy, depending on how I tweak it:
public void doTouch (MotionEvent e) {
int action = e.getAction();
if (action == MotionEvent.ACTION_DOWN) {
this.mTouchX = (int)e.getX();
this.mTouchY = (int)e.getY();
}
else if (action == MotionEvent.ACTION_MOVE) {
if ((int)e.getX() >= this.mTouchX) {
this.mTouchX = (int)e.getX();
this.mTouchY = (int)e.getY();
if (this.TouchRect.contains(this.mTouchX, this.mTouchY)) {
this.mTouchDirection = MOVING_RIGHT;
}
}
else if ((int)e.getX() <= this.mTouchX) {
this.mTouchX = (int)e.getX();
this.mTouchY = (int)e.getY();
if (this.TouchRect.contains(this.mTouchX, this.mTouchY)) {
this.mTouchDirection = MOVING_LEFT;
}
}
else {
this.mTouchDirection = NOT_MOVING;
}
}
else if (action == MotionEvent.ACTION_UP) {
this.mTouchDirection = NOT_MOVING;
}
}
The idea is that when there is any movement, I check the previous location of the users finger and then figure out what direction to move the player.
This doesn't work very well, I figure there are some IPhone/Android developers on here who have figured out how to do good controls via a touchscreen and can give some advice.
You could try something similar to "drag rectangles" on Windows. When you hold down the mouse button on something, you don't start a drag operation until the mouse moves outside a small region around the mouse-down location. Reason being that it's very hard to keep the cursor on the same pixel while clicking.
So a first attempt could be (int)e.getX() >= this.mTouchX + DEAD_ZONE and similar for the other case, where DEAD_ZONE is a small integer.
This does not deal with turning around in the same stroke, however. You could deal with that by only turning left when the current position is at least DEAD_ZONE pixels to the left of the last position after turning right, and vice versa.
One obvious problem is that nowhere do you take account of the time since the last touch.
I would suggest you treat the players touch as an expression of desired movement on an analogue range from -x/+x and -y/+y, then perform the actual movement elsewhere based on time.
E.g.
objectPos += objectPos + (joyPos * timeDelta * maxSpeed);
So if the max-speed of your object is 10ms-1 and the players finger is at 0.5 on the control pad then the object would be moving 5 meters every second. If your game is running at 10fps then each frame the object would move 0.5 meters.
These figures are fictional, but hopefully demonstrate the need to separate control from movement and then factor in time.