I have an app where I blur the navigationbar and tabbar. Here I use FXBlurView to easily do this. I have noticed that the blur keeps being refreshed even though the view doesn't change. This causes the battery to drain quicker than I would want.
Is there a way to quickly detect if the view has changed, without having to take a snapshot (which also is +-5ms each time)?
You can use UIScrollViewDelegate methods for scroll changes and easily set dynamic property to true/false
As another option you can change updateInterval to a bigger value to provide delayed refreshes.
Related
I am working on a view in which certain elements will be removed and re-added as accessible items depending on the state of the view. I have been able to successfully achieve the functionality I desire by setting AccessibilityElementsHidden to toggle the state.
However, I am finding that there is a brief pause (~1-2 seconds) between this field being set before the Accessibility Layout is updated, which can allow the user to highlight a deactivated accessibility element if they are moving at a reasonable pace. If they are focused on an item as it is being disabled it makes it difficult to re-orient oneself in the VoiceOver interface.
I have found methods to immediately update the display of the interface (by means of SetNeedsLayout() and LayoutIfNeeded() on the main thread) but unfortunately this does not trigger the Accessibility Layout update.
I have also tried using UIAccessibilityPostNotification.LayoutChanged but like the changing of the AccessibilityElementsHidden property, this also takes a moment to propagate to the view.
Can anyone provide some insight as to what I need to do to ensure the user cannot put themselves in a bad state before the Accessible Layout is applied?
I would like to write a class that applies an effect to a UIView, similar to UIVisualEffectView. I would also like this view to update live -- if the "target" view redraws itself, my view should as well. Obviously I can just redraw on every frame using a CADisplayLink or NSTimer, but I would prefer not to waste the user's battery unnecessarily.
I see that CALayer/UIView objects have a needsDisplay boolean object, but this seems to be something that the client sets, rather than the system exposing it, so it doesn't seem to be any help.
Is it possible to do this?
I'm using CPPickerView in my app to accomplish a horizontal UIPickerView, and it works great, but with large data sources (dozens of items) it scrolls very slowly which makes navigation before (especially considering a normal UIPickerView can go very fast through them).
I don't mean performance-wise, by the way, I mean the view decelerates very quickly, making traversal difficult.
It's just a subclass of UIScrollView with pagingEnabled set to YES. What can I do?
I looked in the source, and it seems CPPickerView is using a scroll view. Scroll views have a decelerationRate property. Play with that and see which value makes for the best result.
Don't fill CPPickerView with all data.
For example fill with first 20 items and if it reaches to the end add another 20.
Creator of CPPickerView here - I've recently updated CPPickerView to add an allowSlowDeceleration property, which should do what you're looking for. Check out the latest code on Github, or Cocoapods version 1.2.0.
For the purposes of documentation, here's how the solution works. Like you mentioned CPPickerView just a scrollview with pagingEnabled set to YES, so the solution I found was to disable paging when the user scrolls with enough velocity.
UIScrollViewDelegate has an optional method scrollViewWillEndDragging:withVelocity:targetContentOffset:, which is called when the user's finger is lifted after swiping/scrolling on the scrollview, and it's still called even when paging is enabled. Based on that value you can tell if the user was trying to scroll quickly through items, or just move one or two items.
I played around with the CPPickerViews in the Demo project, and found that a velocity of about 2.9f seems to be about the normal "fast swipe" threshold. So if the velocity is greater than this threshold (which I defined as kCPPickerDecelerationThreshold in CPPickerView.m) and allowSlowDeceleration is set to YES, CPPickerView now sets pagingEnabled to NO before the deceleration starts. This allows the picker to "coast" and decelerate like a normal scrollview.
It then catches the end of the deceleration, OR the user touching to stop the scroll, by the call to the scrollViewDidEndDecelerating: delegate method. The current item is determined (based on the offset of the scrollview), and then if the scrollview's pagingEnabled property is set to NO a call to the private method scrollToIndex:animated: is made with animation set to YES. This scrolls the CPPickerView to the current item, which necessary as it's unlikely the coasting scroll ended right on a page boundary.
Finally, when the animated scroll completes, the scrollViewDidEndScrollingAnimation: delegate method is called, at which point pagingEnabled is set back to YES.
If you find that you're having trouble getting it to recognize a "fast" swipe, try playing with the kCPPickerDecelerationThreshold value. In hindsight that maybe should be a customizable property, so perhaps I'll roll that into the next update.
As mentioned above you can use the decelerationRate property, setting it to UIScrollViewDecelerationRateNormal might help.
scrollView.decelerationRate = UIScrollViewDecelerationRateNormal;
If that still doesn't solve your problem you could also buffer your inputs into the scroll. See this:
Advanced scrollview techniques
I'm working on an iPad-App with ARC which have to display thousands of UIImageViews in a UIScrollView...
When I load them all at once (or more accurately in a queue with GCD), I run out of memory after a while of loading..
Now, I thought i have to use lazy-loading and load only those UIImages which are necessary and a kind of release those which are no longer visible, but I don't know if this is possible with ARC..
Anybody have an idea to do this, or a better idea to handle this case..?
Thanks, tonistair
Make something that implements UIScrollViewDelegate, and in its viewDidScroll method, calculate the currently visible rect from contentOffset and bounds. Then remove things that are no longer visible, and add things that have just become visible (or some other appropriate algorithm). ARC has nothing to do with this.
I am having trouble with assigning a UIControl subclass I made as a text field's inputView.
It shows - as expected - when the text field becomes firstResponder and hides when it resigns it firstResponder status.
However, the thing I am having trouble with is handling different orientations:
I set an autoresizingMask to the control's subviews so that there is a smooth transition when changing its width.
The thing is, they appear to be ignored as soon as I set it as the inputView.
When enabling the simulator slow-motion animations via triple-hitting shift, you can see very clearly that the view fades between the two states.
This is not what I want. Firstly it looks odd, and secondly this does not fit my needs.
Since the inputView contains a UIScrollView-like element, it would stop its deceleration animation during the fade.
Now my question is: Is there a way to prevent the fade from happening?
I would really like to use the inputView property since it saves me from writing lots of lines of code.
Also, is it possible to specify different heights for different orientations?
Here are two demo projects showing how it is and how I want it to be.
Thanks in advance.
You can create a method to your DatePicker class, that changes the geometry and layout of the view for different orientations and the implement the method
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
in your view controller and call the method on your view to align it.
Until today I have found no way to prevent them from fading.