Ios development-Implementation of QQ slide navigation bar in the new version

Source: Internet
Author: User

Ios development-Implementation of QQ slide navigation bar in the new version

The new version of QQ has made a lot of updates on the UI. one of the cool effects is its slide navigation bar. Although this kind of UI has been imitated, it seems that the user experience of this design is not good. But I still like this effect very much, so I went to the Internet to learn it. Here we record its implementation.

 

1. Effect display:

 

 

II. Implementation ideas

 

Relationship diagram:

As shown in, the main idea is as follows:

1. SliderNavigation has three subviews: leftView, rightView, and mainView. The switching between the three views is implemented when the Left and Right slides.

2. In fact, only the preceding three views are enough, but three other attributes are added: leftVC, rightVC, and mainVC. The purpose of this operation is to simplify the operation. At the same time, mainVC also records the tasks of the displayed view, so that all views can be pulled out of the navigation bar by sliding left and right. In this way, each sub-view displays the view of the corresponding controller, that is, [leftView addSubview: leftVC. view];. Others are similar.

3. When sliding to the left, adjust the view hierarchy. Because sliding to the left shows the right view, adjust the leftView to the bottom layer and move the mainView with your fingers, in this way, the rightView under mainView is displayed.

4. With the above three points, you can add an animation to each link to achieve the desired effect.

 

Iii. Interface Definition

The. h file defines some attributes that can be customized by the outside world.

First, three controllers

 

// The left and right controllers and the master controllers @ property (strong, nonatomic) UIViewController * leftController; @ property (strong, nonatomic) UIViewController * rightController; @ property (strong, nonatomic) UIViewController * mainController;

Second, there are some related settings of the left and right views, such as judgment points, cheap volume, animation time, and whether the view can be pulled out.

 

 

// Offset (positive) @ property (assign, nonatomic) CGFloat leftOffsetX; @ property (assign, nonatomic) CGFloat rightOffsetX; // The X value (positive value) of the judgment point during the pull process of the left and right views @ property (assign, nonatomic) CGFloat leftJudgeX; @ property (assign, nonatomic) CGFloat rightJudegX; // The time used to pull the left and right views @ property (assign, nonatomic) NSTimeInterval leftOpenDuration; @ property (assign, nonatomic) NSTimeInterval rightOpenDuration; // The time used to reclaim the left and right views @ property (assign, nonatomic) NSTimeInterval leftCloseDuration; @ property (assign, nonatomic) NSTimeInterval rightCloseDuration; // scale-down ratio of the left and right views after being pulled out (0 to 1) @ property (assign, nonatomic) CGFloat rightScale; @ property (assign, nonatomic) CGFloat leftScale; // whether the left and right views can be pulled out @ property (assign, nonatomic) BOOL canShowRight; @ property (assign, nonatomic) BOOL canShowLeft;

As I mentioned earlier, mainVC needs to write down the main views that have already been presented and add them to the dictionary. This will facilitate the presentation next time. In addition, assign a value to mainVC for the Controller corresponding to each view to be displayed, so that the navigation bar can be pulled from left and right in all interfaces. What does it mean? The root of the sliderNavigation class is our encapsulated sliderNavigation class. Its hierarchy still exists, but it only changes the value of mainVC. In this way, the user experience is that although the main interface has changed, however, you can still pull the Left and Right navigation bars.

 

Therefore, we set a dictionary to save the Controller that has already been displayed.

 

// Records the Controller @ property (strong, nonatomic) NSMutableDictionary * controllersDict that is used as the master controller to display the master view;

The following are several public method declarations. The Manager class is used as a Singleton, which exposes the functions of displaying the left and right views for button control, then, you can display the custom class as the main interface.

 

 

// Single Instance + (id) sharedInstance; // display the left and right views-(void) showLeftView;-(void) showRightView; // display the main view of the custom class, parameters: custom class name-(void) showContentViewWithModel :( NSString *) className;

 

Iv. Specific implementation

 

First, define some constants.

 

// Create the dynamic effect of the rebound. When the navigation bar is called through the button, the static const CGFloat kOpenSpringDamping = 0.65f; static const CGFloat kOpenSpringVelocity = 0.10f; // define a constant to indicate pulling direction typedef NS_ENUM (NSUInteger, sliderMoveDirection) {slidermovedireleft = 0, slidermovedireright ,};

Next, let's focus on the key code or methods, and the rest of the ideas.

 

 

You can assign default values to the variables declared in the interface in the initialization method. You can use these default values when they are not assigned values.

First, we initialize the three subviews as the screen size and add them to the subviews of sliderNavigation. Note the order of adding: we want the primary view to be at the top, so the first two views are random, the master view must be added at the end.

 

-(Void) _ initSubviews {_ rightView = [[UIView alloc] initWithFrame: self. view. bounds]; [self. view insertSubview: _ rightView atIndex: 0]; _ leftView = [[UIView alloc] initWithFrame: self. view. bounds]; [self. view insertSubview: _ leftView atIndex: 1]; // The main view to be added (that is, to the top of the display) _ mainView = [[UIView alloc] initWithFrame: self. view. bounds]; [self. view insertSubview: _ mainView aboveSubview: _ leftView];}

Then we initialize the Left and Right controllers and add the Left and Right controller views to the left and right views respectively.

 

When the above public method is implemented to "display the main view of a custom class", the input parameter is the class name and uses it as the key to retrieve the controller from the dictionary, if not, create a new controller for this class and add it to the dictionary. If the current master view already has a view, remove it. Add the view of the custom class to mainView and assign values accordingly.

Of course, do not forget to close the left navigation bar (because the displayed class may be clicked out through the left navigation bar)

 

-(Void) showContentViewWithModel :( NSString *) className {[self _ closeSliderNavigation]; UIViewController * controller = [self. controllersDict objectForKey: className]; if (controller = nil) {Class c = NSClassFromString (className); controller = [[c alloc] init]; [self. controllersDict setObject: controller forKey: className];} // if a view is displayed, cancel if (_ mainView. subviews. count> 0) {[_ mainView. subviews firstObject] removeFromSuperview];} controller. view. frame = _ mainView. frame; [_ mainView addSubview: controller. view]; self. mainController = controller ;}

The next step is the animation. The animation used here is to change the size and position of the view and use transform. The method for obtaining the transform is extracted separately, and concat is used to connect the size transformation matrix and the position transformation matrix. Then you can change the transform of the main view in the animation block. Of course, you can also set the shadow effect. It should be noted that the view should be adjusted to the bottom layer based on the sliding direction.

 

 

CGAffineTransform concat = [self _ transformWithMoveDirection: slidermovedireleft]; [self. view sendSubviewToBack: _ leftView]; // tune another view to the bottom [self _ configureViewShadowWithDirection: slidermovedireleft]; // set the shadow [UIView animateWithDuration: self. rightOpenDuration delay: 0 usingSpringWithDamping: kOpenSpringDamping // initialSpringVelocity: kOpenSpringVelocity options: UIViewAnimationOptionCurveLinear animations: ^ {_ mainView. transform = concat;} completion: ^ (BOOL finished) {_ showingLeft = NO; _ showingRight = YES; self. mainController. view. userInteractionEnabled = NO; _ tapGesture. enabled = YES;}];

Similarities in the other direction

 

 

The most important thing is the sliding gesture operation, which is also troublesome. But the idea is clear: Get the offset, calculate the corresponding transformation matrix in the sliding time, and set it. At the end of the sliding, adjust the animation based on the relationship between the position and the judgment point.

For example, when the Sliding Process is pulled to the right:

 

CGFloat translateX = [recognizer translationInView: _ mainView]. x; translateX + = currentOffsetX; float scale = 0; // pull to the right to display the Left view if (translateX> 0) {if (self. canShowLeft = NO | self. leftController = nil) {return;} // place the right view to the bottom to display the Left view [self. view sendSubviewToBack: _ rightView]; [self _ configureViewShadowWithDirection: SliderMoveDirectionRight]; if (_ mainView. frame. origin. x <self. leftOffsetX) {sca Le = 1-(_ mainView. frame. origin. x/self. leftOffsetX) * (1-self. leftScale);} else {scale = self. leftScale ;}} else if (translateX <0 ){......}

Ten-scale computing is a headache. The requirement here is that the scale change from the first to the last is 1.0 to self. leftScale, so we can use the mathematical knowledge to introduce this formula. The code above omits the code pulled to the left.

 

The pull end state is similar to the left-and right-pull animation.

 

        CGFloat translateX = [recognizer translationInView:_mainView].x;        translateX += currentOffsetX;                if (translateX > self.leftJudgeX) {            if (self.canShowLeft == NO || self.leftController == nil) {                return;            }                        CGAffineTransform trans = [self _transformWithMoveDirection:SliderMoveDirectionRight];            [UIView beginAnimations:nil context:nil];            _mainView.transform = trans;            [UIView commitAnimations];                        _showingLeft = YES;            _showingRight = NO;            self.mainController.view.userInteractionEnabled = NO;            _tapGesture.enabled = YES;                    } else if (translateX < -self.rightJudgeX) {……}

 

 

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.