The articles
Multipeer Connectivity is a simple sandbox file browser
Implementation effect
The main functions are as follows
-
Push view, the breadcrumb navigation bar automatically increases the corresponding view Item
-
Click the corresponding breadcrumb navigation bar Item to jump to the corresponding text of Item
-
When the breadcrumb navigation bar item’s content width is larger than the current screen width, the breadcrumb navigation bar starts sliding mode and automatically moves to the last item, ensuring that the current view corresponds to the last item of the breadcrumb navigation bar
-
Breadcrumb navigation bar Turns off slide mode when the content width of the item is less than or equal to the current screen width
The demo looks like this
The implementation process
The implementation is mainly divided into two parts, one is breadcrumb navigation controller, one is breadcrumb navigation bar.
Breadcrumb navigation controller
The current version of UINavigationController does not handle the sideslip return function, so the UINavigationController sideslip return function is temporarily disabled
Breadcrumb navigation bar added
In order to facilitate the management of the controller on and off the stack, we need to inherit the UINavigationController provided by the system
@interface AMBreadCrumbNavController : UINavigationController
@end
Copy the code
As shown in the figure below, if you use the system-provided UINavigationController, there is a built-in NavigationBar. So we need to hide the built-in NavigationBa and add our own breadcrumb navigation bar.
After adding it to the navigation bar, we need to tell the custom breadcrumb navigation bar, the controller stack in the current navigation controller, and add the passed root view controller to the controller stack. It is then managed by the custom breadcrumb navigation bar.
And the deal method of breadcrumb navigation bar to the current navigation controller AMBreadCrumbNavController implementation.
The implementation code is as follows:
- (instancetype)initWithRootViewController:(UIViewController *)rootViewController {
// The navigation bar is already initialized in super
if (self = [super initWithRootViewController:rootViewController]) {
// Make the navigation bar opaque
self.navigationBar.translucent = NO;
// Set the root view
self.rootViewController = rootViewController;
// Add a breadcrumb navigation bar to cover the system's own navigation bar
[self breadCrumbNav];
// Initialize the root view controller navigation bar
self.breadCrumbBar.controllers = @[self.rootViewController];
// Set the breadcrumb navigation agent
self.breadCrumbBar.delegate = self;
// Hide the built-in navigation bar
[self setNavigationBarHidden:YES];
}
return self;
}
Copy the code
I’ve changed the breadcrumb navigation method to UIViewController+AMBreadCrumbNav. The goal is to add breadcrumb navigation to other types of controllers in the future, not just UINavigationController design.
@interface UIViewController (AMBreadCrumbNav)
/// Breadcrumb navigation bar the entire navigation bar view
@property(strong.nonatomic) UIView* breadCrumbView;
/// Breadcrumb function bar
@property(strong.nonatomic) AMBreadCrumbNavBar* breadCrumbBar;
/// Expand the right view
@property(strong.nonatomic) UIView* rightView;
/// Add a custom control to the expanded view on the right
// **@param** item
- (void) addRightItem:(UIView*) item;
///// Expansion button on the right
//@property(strong,nonatomic) UIButton* selectButton;
- (void) breadCrumbNav;
@end
Copy the code
Controller out and onto the stack
Next we are going to implement the methods of the navigation controller’s stack controller and the stack controller.
Controller loading
The pushViewController of UINavigationController is simply overwritten and passed the latest controller array to the breadcrumb navigation bar to update the contents of the navigation bar.
The implementation code is as follows
- (void) pushViewController:(UIViewController *)viewController animated:(BOOL)animated {
// Close sideslip and return
if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)])
self.interactivePopGestureRecognizer.enabled = NO;
/ / first into the stack
[super pushViewController:viewController animated:animated];
// Update the breadcrumb navigation bar
self.breadCrumbBar.controllers = self.viewControllers;
}
Copy the code
Controller out of stack
Because the slide back function of the navigation controller is disabled, and there is no corresponding push button on the navigation bar. So I want to make the controller go off the stack, just click the controller’s button on the breadcrumb navigation bar, and switch to the specified controller.
So here we need to implement the breadcrumb navigator delegate method. So we get the controller that we’re currently clicking on in the breadcrumb navigation bar, so we want to switch to the controller.
Once we get the controller we want to switch to, we need to remove all controllers after this controller from the stack, leaving only the controller we want to switch to and the controller before it
For example, when we click B on controller D, the clickViewController agent returns to us the controller B that we want to switch to. In this case, we need to push C and D off the stack, leaving only A and B on the stack.
- (void)clickViewController:(UIViewController *)viewController{
if ([self.viewControllers containsObject:viewController]) {
if ([self.visibleViewController isEqual:viewController]) {
return;
}
[self popToViewController:viewController animated:YES];
// Check whether the current element at the bottom of the ViewControllers stack is the root view, because if it is A cross-page jump, such as a-b-c-d, d-C jump, self. ViewControllers are root view A, but d-B jump, Self. viewControllers the bottom element of the stack is not the root view A
if(! [self.viewControllers.firstObject isEqual:self.rootViewController]) {
// Remove the bottom element of the stack that is not the root view
[self.viewControllers.firstObject removeFromParentViewController];
}
// Update the breadcrumb navigation bar
self.breadCrumbBar.controllers = self.viewControllers; }}Copy the code
Breadcrumb navigation bar
The breadcrumb navigation bar is internally implemented by a UICollectionView, and each controller corresponds to an item in the CollectionView.
Item is divided into text area and expansion area
- The text area mainly displays the text that the current controller wants to display in the breadcrumb navigation bar.
- The expansion area is mainly used to add the breadcrumb navigation bar segmentation symbol to the non-last item when the number of items is greater than 2. Here we use a simple > symbol to replace, later can be replaced according to their own needs into animation or pictures.
Of course, the width of each item is calculated by the text to be displayed plus the width of the extension area. That is, the width of the item is equal to the width of the text area when there is no need to display the expanded area (the item has only one or the last item).
Item displays data retrieval
We here by getting bread crumbs navigation controller (AMBreadCrumbNavController) controller in the stack (controllers), pass it to AMBreadCrumbNavBar
@interface AMBreadCrumbNavBar : UIView
// save the controller pushed by the system navigation controller
@property(strong.nonatomic) NSArray<UIViewController*>* controllers;
@property(weak.nonatomic) id<AMBreadCrumbBarDelegate> delegate;
@end
Copy the code
So we can get controllers, all the controllers in the stack, and then we can get the title that we want to display based on the navigationItem property in our controller UIViewController. It is then handed over to the AMBreadCrumbNavCell to display.
/// AMBreadCrumbNavCell
- (void)setController:(UIViewController *)controller{
_controller = controller;
NSLog(@" The title is %@",controller.navigationItem.title);
self.titleLabel.text = controller.navigationItem.title;
}
Copy the code
Automatically slides to the end
Set the breadcrumb navigation bar to automatically slide to the end of the CollectionView when the current screen width cannot display the entire contents of the CollectionView
The implementation principle is very simple, using the CollectionView scrollToItemAtIndexPath method
This method does not fire when the specified item is visible, but scrolls automatically to the specified item when it is not visible.
So we just need to get the first controller, the last one that needs to appear item, and let the CollectionView scroll to it when the AMBreadCrumbNavBar loads the data. When the last item is not visible, it automatically rolls to the last item.
The implementation code is as follows
- (void)setControllers:(NSArray<UIViewController *> *)controllers{
_controllers = controllers;
[self.collectionView reloadData];
// If the navigation bar cannot show all cells, the collectionView slides to the end automatically.
[self.collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForRow:controllers.count- 1 inSection:0] atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:YES];
}
Copy the code
Note that when scrollToItemAtIndexPath specifies the scroll, the CollectionView must be refreshed before the scroll is specified.
The project address
If you have any problems, please send them to me. I will try my best to solve them
The project will continue to be improved.
AMBreadcrumbs