封装了一个优雅的iOS全屏侧滑返回工具
思路
添加一个全屏返回手势,UIPangesturerecognizer,
1 手势开始
在手势开始响应的时候,将navigationController的delegate代理设置为工具类,在工具类中执行代理方法,- (nullable id )navigationController:(UINavigationController *)navigationController
和 - (nullable id )navigationController:(UINavigationController *)navigationController
都返回为侧滑工具对象,然后侧滑工具实现
- (NSTimeInterval)transitionDuration:(nullable id )transitionContext {
和 - (void)animateTransition:(id)transitionContext
方法 , 并实现 - (void)startInteractiveTransition:(id )transitionContext {
方法,
2 手势改变
计算滑动比例,我们以超过200就算1,根据translationInView 计算滑动比例
在手势的改变的状态下,
通过 UIView *toView = [self.transitionContext viewForKey:UITransitionContextToViewKey];
UIView *fromView = [self.transitionContext viewForKey:UITransitionContextFromViewKey];
UIView *containerView = self.transitionContext.containerView;
方法获取到要退回到的视图和来源视图,并修改frame,
达到两个视图移动的效果
3 手势结束,根据滑动距离和速度确定是完成返回还是取消返回
4 注意要添加弹簧动画,使交互效果更流畅优雅
效果图

代码如下
@interface LBTransitionManager : NSObject@property (nonatomic, weak) UINavigationController *navigationController;+ (instancetype)shareManager;- (UIPanGestureRecognizer *)addPanGestureRecognizerToViewControllerIfNeeded:(UIViewController *)viewController ;@end
//
// LBTransitionManager.m
// TEXT
//
// Created by mac on 2025/3/30.
//#import "LBTransitionManager.h"
#import <UIKit/UIKit.h>
#import "LBTransitionInteractivePopLinearAnimation.h"@interface LBTransitionManager () <UINavigationControllerDelegate,
UIViewControllerAnimatedTransitioning,
UIViewControllerInteractiveTransitioning>@property (nonatomic, strong) LBTransitionInteractivePopLinearAnimation *currentInteractiveAnimation;@property (nonatomic, weak) UIPanGestureRecognizer *currentPanGestureRecognizer;@property (nonatomic, strong) id <UIViewControllerContextTransitioning> transitionContext;@end@implementation LBTransitionManager+ (instancetype)shareManager
{static dispatch_once_t onceToken;static LBTransitionManager *shareManager = nil;dispatch_once(&onceToken, ^{shareManager = [[self alloc] init];});return shareManager;;
}- (UIPanGestureRecognizer *)addPanGestureRecognizerToViewControllerIfNeeded:(UIViewController *)viewController {UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];[viewController.view addGestureRecognizer:panGestureRecognizer];return panGestureRecognizer;
}#pragma mark - UINavigationControllerDelegate- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {}- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated {}- (nullable id <UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController *)navigationControllerinteractionControllerForAnimationController:(id <UIViewControllerAnimatedTransitioning>)animationController {return self;
}- (nullable id <UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationControlleranimationControllerForOperation:(UINavigationControllerOperation)operationfromViewController:(UIViewController *)fromVCtoViewController:(UIViewController *)toVC {return self;
}#pragma mark - UIViewControllerAnimationTransitioning- (NSTimeInterval)transitionDuration:(nullable id <UIViewControllerContextTransitioning>)transitionContext {NSTimeInterval transitionDuration = 0.4;if ([self.currentInteractiveAnimation respondsToSelector:@selector(transitionDuration)]) {transitionDuration = [self.currentInteractiveAnimation transitionDuration];}return transitionDuration;
}- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
}#pragma mark - UIViewControllerInteractiveTransitioning- (void)startInteractiveTransition:(id <UIViewControllerContextTransitioning>)transitionContext {NSLog(@"ttttttt startInteractiveTransition, current pan: %@", self.currentPanGestureRecognizer);[self updateViewsInteractionWithTransitionContext:transitionContext isEnabled:NO];id<LBTransitionAnimationProtocol> animation = [[LBTransitionInteractivePopLinearAnimation alloc] init];[animation prepareTransitionWithTransitionContext:transitionContext];if (self.currentPanGestureRecognizer == nil) {[animation finishTransitionIsCancel:YES completion:^(BOOL finished, BOOL isCancel, id<UIViewControllerContextTransitioning> _Nonnull transitionContext) {[self finishInteractiveTransitionWithTransitionContext:transitionContext isCancel:isCancel isAnimationFinished:finished];[self updateViewsInteractionWithTransitionContext:transitionContext isEnabled:YES];}];} else {self.currentInteractiveAnimation = animation;}
}#pragma mark - action- (void)handlePan:(id)sender {if (![sender isKindOfClass:[UIPanGestureRecognizer class]]) return;UIPanGestureRecognizer *panGestureRecognizer = sender;CGPoint velocity = [panGestureRecognizer velocityInView:panGestureRecognizer.view.superview];CGPoint translation = [panGestureRecognizer translationInView:panGestureRecognizer.view.superview];CGFloat percentComplete = [self percentCompleteWithTranslation:translation];UIResponder *nextResponder = panGestureRecognizer.view.nextResponder;switch (panGestureRecognizer.state) {case UIGestureRecognizerStateBegan: {NSLog(@"ttttttt pan pop state began");CGFloat velocityX = velocity.x;CGFloat velocityY = velocity.y;if (velocityX == 0.0) {panGestureRecognizer.enabled = NO;panGestureRecognizer.enabled = YES;return;}self.currentPanGestureRecognizer = panGestureRecognizer;UINavigationController *navigationController = self.navigationController;id<UINavigationControllerDelegate> navigationControllerDelegate = navigationController.delegate;navigationController.delegate = self;NSLog(@"LIVDetailTransitionManager navigationControllerDelegate: %@", navigationController.delegate);[navigationController popViewControllerAnimated:YES];navigationController.delegate = navigationControllerDelegate;}break;case UIGestureRecognizerStateChanged: {NSLog(@"这里的animation %@", self.currentInteractiveAnimation);BOOL finishInstantly = [self.currentInteractiveAnimation updateTransitionWithPercentComplete:percentComplete translation:translation];if (finishInstantly) {self.currentPanGestureRecognizer.state = UIGestureRecognizerStateEnded;}}break;case UIGestureRecognizerStateCancelled:case UIGestureRecognizerStateFailed: {NSLog(@"ttttttt pan pop state cancelled, failed, started: %@", self.currentInteractiveAnimation);self.currentPanGestureRecognizer = nil;[self.currentInteractiveAnimation finishTransitionIsCancel:YES completion:^(BOOL finished, BOOL isCancel, id<UIViewControllerContextTransitioning> transitionContext) {[self finishInteractiveTransitionWithTransitionContext:transitionContext isCancel:isCancel isAnimationFinished:finished];}];} break;case UIGestureRecognizerStateEnded: {BOOL isTransitionMadeProgress = percentComplete > 0.1;BOOL isPanRight = velocity.x > 0.0;BOOL shouldComplete = NO;shouldComplete = (isTransitionMadeProgress && isPanRight) || velocity.x > 100.0;NSLog(@"ttttttt pan pop state end: %d, %d, %d, %@", isTransitionMadeProgress, isPanRight, shouldComplete, self.currentInteractiveAnimation);self.currentPanGestureRecognizer = nil;__weak typeof(self) weakSelf = self;[self.currentInteractiveAnimation finishTransitionIsCancel:!shouldComplete completion:^(BOOL finished, BOOL isCancel, id<UIViewControllerContextTransitioning> transitionContext) {[self finishInteractiveTransitionWithTransitionContext:transitionContext isCancel:isCancel isAnimationFinished:finished];[self updateViewsInteractionWithTransitionContext:transitionContext isEnabled:YES];}];} break;default:break;}
}- (CGFloat)percentCompleteWithTranslation:(CGPoint)translation {CGFloat translationX = translation.x;CGFloat translationXRangeMin = 0.0;CGFloat translationXRangeMax = 200.0;if (translationX < translationXRangeMin) {return 0.0;} else if (translationX > translationXRangeMax) {return 1.0;} else {return (translationX - translationXRangeMin) / (translationXRangeMax - translationXRangeMin);}
}- (void)finishInteractiveTransitionWithTransitionContext:(id<UIViewControllerContextTransitioning>)transitionContext isCancel:(BOOL)isCancel isAnimationFinished:(BOOL)isAnimationFinished {NSLog(@"ttttttt finish interactive transition: %d, %d", isCancel, isAnimationFinished);id<LBTransitionAnimationProtocol> currentInteractiveAnimation = self.currentInteractiveAnimation;self.currentInteractiveAnimation = nil;if (isCancel) {[transitionContext cancelInteractiveTransition];} else {[transitionContext finishInteractiveTransition];}[transitionContext completeTransition:!isCancel];
}- (void)updateViewsInteractionWithTransitionContext:(id<UIViewControllerContextTransitioning>)transitionContext isEnabled:(BOOL)isEnabled {UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];fromViewController.view.userInteractionEnabled = isEnabled;toViewController.view.userInteractionEnabled = isEnabled;
}@end
//
// LBTransitionInteractivePopAnimation.h
// TEXT
//
// Created by mac on 2025/3/30.//#import <Foundation/Foundation.h>
#import "LBTransitionAnimationProtocol.h"NS_ASSUME_NONNULL_BEGIN@interface LBTransitionInteractivePopLinearAnimation : NSObject <LBTransitionAnimationProtocol>@endNS_ASSUME_NONNULL_END
//
// LBTransitionInteractivePopAnimation.m
// TEXT
//
// Created by mac on 2025/3/30.
//#import "LBTransitionInteractivePopLinearAnimation.h"
#import <UIKit/UIKit.h>
#import "UIView+LBFrame.h"@interface LBTransitionInteractivePopLinearAnimation ()@property (strong, nonatomic) id<UIViewControllerContextTransitioning> transitionContext;@property (strong, nonatomic) UIView *containerView;@property (strong, nonatomic) UIView *animationContainerView;@end@implementation LBTransitionInteractivePopLinearAnimation- (instancetype)init{self = [super init];if (self == nil) return nil;return self;
}#pragma mark - Transition- (NSTimeInterval)transitionDuration {return 0.4;
}- (void)prepareTransitionWithTransitionContext:(id<UIViewControllerContextTransitioning>)transitionContext {self.transitionContext = transitionContext;UIView *containerView = transitionContext.containerView;containerView.backgroundColor = UIColor.clearColor;self.containerView = containerView;UIView *toView = [transitionContext viewForKey:UITransitionContextToViewKey];toView.frame = containerView.bounds;toView.x = -(containerView.width / 4.0);[self.containerView addSubview:toView];UIView *fromView = [transitionContext viewForKey:UITransitionContextFromViewKey];fromView.frame = containerView.bounds;[self.containerView addSubview:fromView];
}- (BOOL)updateTransitionWithPercentComplete:(CGFloat)percentComplete translation:(CGPoint)translation {UIView *toView = [self.transitionContext viewForKey:UITransitionContextToViewKey];UIView *fromView = [self.transitionContext viewForKey:UITransitionContextFromViewKey];UIView *containerView = self.transitionContext.containerView;CGFloat toViewInitialX = containerView.x - (containerView.width / 4.0);CGFloat toViewMaxX = containerView.x;CGFloat fromViewInitialX = containerView.x;CGFloat fromViewMaxX = containerView.width;toView.x = containerView.x - (containerView.width / 4.0) + translation.x * 0.25;fromView.x = containerView.x + translation.x;if (toView.x < toViewInitialX) {toView.x = toViewInitialX;}if (toView.x > toViewMaxX) {toView.x = toViewMaxX;}if (fromView.x < fromViewInitialX) {fromView.x = fromViewInitialX;}if (fromView.x > fromViewMaxX) {fromView.x = fromViewMaxX;}[self.transitionContext updateInteractiveTransition:percentComplete];return NO;
}- (void)finishTransitionIsCancel:(BOOL)isCancel completion:(LIVDetailTransitionAnimationCompletion)completion {UIView *toView = [self.transitionContext viewForKey:UITransitionContextToViewKey];UIView *fromView = [self.transitionContext viewForKey:UITransitionContextFromViewKey];UIView *containerView = self.transitionContext.containerView;CGFloat toViewInitialX = containerView.x - (containerView.width / 4.0);CGFloat toViewMaxX = containerView.x;CGFloat fromViewInitialX = containerView.x;CGFloat fromViewMaxX = containerView.width;[UIView animateWithDuration:[self transitionDuration] delay:0.0 usingSpringWithDamping:1.0 initialSpringVelocity:0.0 options:UIViewAnimationOptionLayoutSubviews | UIViewAnimationOptionCurveLinear animations:^{if (isCancel) {toView.x = toViewInitialX;fromView.x = fromViewInitialX;} else {toView.x = toViewMaxX;fromView.x = fromViewMaxX;}} completion:^(BOOL finished) {NSLog(@"interactive pop linear animation completion: %d, %d", finished, isCancel);if (completion != nil) {completion(finished, isCancel, self.transitionContext);}}];
}@end
//
// LBTransitionAnimationProtocol.h
// TEXT
//
// Created by mac on 2025/3/30.
//#ifndef LBTransitionAnimationProtocol_h
#define LBTransitionAnimationProtocol_h
#import <UIKit/UIKit.h>typedef void(^LIVDetailTransitionAnimationCompletion)(BOOL finished, BOOL isCancel, id<UIViewControllerContextTransitioning> transitionContext);@protocol LBTransitionAnimationProtocol <NSObject>- (void)prepareTransitionWithTransitionContext:(id<UIViewControllerContextTransitioning>)transitionContext;
- (BOOL)updateTransitionWithPercentComplete:(CGFloat)percentComplete translation:(CGPoint)translation; // 更新当前动画进度,返回 YES 代表需要马上结束转场
- (void)finishTransitionIsCancel:(BOOL)isCancel completion:(LIVDetailTransitionAnimationCompletion)completion;- (NSTimeInterval)transitionDuration;@end#endif /* LBTransitionAnimationProtocol_h */相关文章:
封装了一个优雅的iOS全屏侧滑返回工具
思路 添加一个全屏返回手势,UIPangesturerecognizer, 1 手势开始 在手势开始响应的时候,将navigationController的delegate代理设置为工具类,在工具类中执行代理方法,- (nullable id )navigationController:(UINavigationControll…...
HCIP-6 DHCP
HCIP-6 DHCP DHCP(Dynamic Host Configuration Protocol,动态主机配置协议) 手工配置网络参数存在的问题 灵活性差 容易出错 IP地址资源利用率低 工作量大 人员素质要求高 DHCP服务器按照如下次序为客户端选择IP地址: ①DHCP服务器的数…...
OpenCV图像拼接(8)用于实现并查集(也称为不相交集合)数据结构类cv::detail::DisjointSets
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 cv::detail::DisjointSets 类是OpenCV库中用于实现不相交集合(也称为并查集)数据结构的类。该数据结构常用于处理动态连接…...
opencv图像处理之指纹验证
一、简介 在当今数字化时代,生物识别技术作为一种安全、便捷的身份验证方式,正广泛应用于各个领域。指纹识别作为生物识别技术中的佼佼者,因其独特性和稳定性,成为了众多应用场景的首选。今天,我们就来深入探讨如何利…...
记一道CTF题—PHP双MD5加密+”SALT“弱碰撞绕过
通过分析源代码并找到绕过限制的方法,从而获取到flag! 部分源码: <?php $name_POST[username]; $passencode(_POST[password]); $admin_user "admin"; $admin_pw get_hash("0e260265122865008095838959784793");…...
Text2SQL推理类大模型本地部署的解决方案
大家好,我是herosunly。985院校硕士毕业,现担任算法工程师一职,获得CSDN博客之星第一名,热衷于大模型算法的研究与应用。曾担任百度千帆大模型比赛、BPAA算法大赛评委,编写微软OpenAI考试认证指导手册。曾获得多项AI顶级比赛的Top名次,其中包括阿里云、科大讯飞比赛第一名…...
机器学习的一百个概念(3)上采样
前言 本文隶属于专栏《机器学习的一百个概念》,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢! 本专栏目录结构和参考文献请见[《机器学习的一百个概念》 ima 知识库 知识库广场搜索&…...
Electron应用生命周期全解析:从启动到退出的精准掌控
一、Electron生命周期的核心特征 1.1 双进程架构的生命周期差异 Electron应用的生命周期管理具有明显的双进程特征: 主进程生命周期:贯穿应用启动到退出的完整周期渲染进程生命周期:与浏览器标签页相似但具备扩展能力进程间联动周期&#…...
AI渗透测试:网络安全的“黑魔法”还是“白魔法”?
引言:AI渗透测试,安全圈的“新魔法师” 想象一下,你是个网络安全新手,手里攥着一堆工具,正准备硬着头皮上阵。这时,AI蹦出来,拍着胸脯说:“别慌,我3秒扫完漏洞࿰…...
分秒计数器设计
一、在VsCode中写代码 目录 一、在VsCode中写代码 二、在Quartus中创建工程与仿真 1、建立工程项目文件md_counter 2、打开项目文件,创建三个目录 3、打开文件trl,创建md_counter.v文件 4、打开文件tb,创建md_counter_tb.v文件 5、用VsCod…...
Flink介绍——发展历史
引入 我们整个大数据处理里面的计算模式主要可以分为以下四种: 批量计算(batch computing) MapReduce Hive Spark Flink pig流式计算(stream computing) Storm SparkStreaming/StructuredStreaming Flink Samza交互计…...
12. STL的原理
目录 1. 容器、迭代器、算法 什么是迭代器? 迭代器的作用? 迭代器的类型? 迭代器失效 迭代器的实现细节: 2. 适配器 什么是适配器? 适配器种类: 3. 仿函数 什么是仿函数? 仿函数与算法和容器的…...
OSPFv3 的 LSA 详解
一、复习: OSPFv3 运行于 IPv6 协议上,所以是基于链路,而不是基于网段,它实现了拓扑和网络的分离。另外,支持一个链路上多个进程;支持泛洪范围标记和泛洪不识别的报文(ospfv2 的行为是丢弃&…...
python 原型链污染学习
复现SU的时候遇到一道python原型链污染的题,借此机会学一下参考: 【原型链污染】Python与Jshttps://blog.abdulrah33m.com/prototype-pollution-in-python/pydash原型链污染 文章目录 基础知识对父类的污染命令执行对子类的污染pydash原型链污染打污染的…...
Windows 图形显示驱动开发-WDDM 2.4功能-GPU 半虚拟化(十一)
注册表设置 GPU虚拟化标志 GpuVirtualizationFlags 注册表项用于设置半虚拟化 GPU 的行为。 密钥位于: DWORD HKLM\System\CurrentControlSet\Control\GraphicsDrivers\GpuVirtualizationFlags 定义了以下位: 位描述0x1 为所有硬件适配器强制设置…...
入栈操作-出栈操作
入栈操作 其 入栈操作 汇编代码流程解析如下: 出栈操作 其 出栈操作 汇编代码流程解析如下:...
C++ 多态:面向对象编程的核心概念(一)
文章目录 引言1. 多态的概念2. 多态的定义和实现2.1 实现多态的条件2.2 虚函数2.3 虚函数的重写/覆盖2.4 虚函数重写的一些其他问题2.5 override 和 final 关键字2.6 重载/重写/隐藏的对比 3. 纯虚函数和抽象类 引言 多态是面向对象编程的三大特性之一(封装、继承、…...
传统策略梯度方法的弊端与PPO的改进:稳定性与样本效率的提升
为什么传统策略梯度方法(如REINFORCE算法)在训练过程中存在不稳定性和样本效率低下的问题 1. 传统策略梯度方法的基本公式 传统策略梯度方法的目标是最大化累积奖励的期望值。具体来说,优化目标可以表示为: max θ J ( θ )…...
我的机器学习学习之路
学习python的初衷 • hi,今天给朋友们分享一下我是怎么从0基础开始学习机器学习的。 • 我是2023年9月开始下定决心要学python的,目的有两个,一是为了提升自己的技能和价值,二是将所学的知识应用到工作中去,提升工作…...
Spring Boot 的自动装配
Spring Boot 的自动装配(Auto Configuration)是其核心特性之一,通过智能化的条件判断和配置加载机制,极大简化了传统 Spring 应用的配置复杂度。其原理和实现过程可概括为以下几个关键点: 一、核心触发机制:…...
Python数据可视化-第3章-图表辅助元素的定制
教材 本书为《Python数据可视化》一书的配套内容,本章为第3章-图表辅助元素的定制 本章主要介绍了图表辅助元素的定制,包括认识常用的辅助元素、设置坐标轴的标签、设置刻度范围和刻度标签、添加标题和图例、显示网格、添加参考线和参考区域、添加注释文…...
`git commit --amend` 详解:修改提交记录的正确方式
文章目录 git commit --amend 详解:修改提交记录的正确方式1. 修改提交信息2. 补充遗漏的文件3. 结合 --amend 进行交互式修改4. 已推送提交的修改总结 git commit --amend 详解:修改提交记录的正确方式 git commit --amend 用于修改最近一次的提交&…...
Linux系统下C语言fork函数使用案例
一、fork函数的作用 生成一个子进程,异步执行某个任务; 二、子进程的作用 1、子进程能复制一份父进程的变量、函数; 2、子进程可以和父进程同时并发执行; 函数语法: pid_t fork() 说明:调用后返回一个进程…...
springboot实现异步导入Excel的注意点
springboot实现异步导入Excel 需求前言异步导入面临的问题实现异步如何导入大Excel文件避免OOM?异步操作后,如何通知导入结果?如何加快导入效率?将导入结果通知给用户后,如何避免重复通知? 优化点完结撒花&…...
Linux练习——有关硬盘、联网、软件包的管理
1、将你的虚拟机的网卡模式设置为nat模式,给虚拟机网卡配置三个主机位分别为100、200、168的ip地址 #使用nmtui打开文本图形界面配置网络 [rootrhcsa0306 ~]# nmtui #使用命令激活名为 ens160 的 NetworkManager 网络连接 [rootrhcsa0306 ~]# nmcli c up ens160 #通…...
论文阅读:GS-Blur: A 3D Scene-Based Dataset for Realistic Image Deblurring
今天介绍一篇 2024 NeurIPS 的文章,是关于真实世界去模糊任务的数据集构建的工作,论文作者来自韩国首尔大学 Abstract 要训练去模糊网络,拥有一个包含成对模糊图像和清晰图像的合适数据集至关重要。现有的数据集收集模糊图像的方式主要有两…...
经典动态规划问题:爬楼梯的多种解法详解
引言 今天我们要解决一个经典的算法问题——爬楼梯问题。这个问题看似简单,但蕴含了多种解法,从递归到动态规划,再到组合数学,每种方法都有其独特的思路和优化方式。本文将详细讲解四种解法,并通过代码和图解帮助大家…...
Kubernetes深度解析:云原生时代的容器编排引擎
一、背景与演进 1. 容器革命的必然产物 Kubernetes(K8s)诞生于2014年,是Google基于其内部Borg系统的开源实现。在传统单体应用向微服务架构转型的浪潮中,容器技术(如Docker)解决了应用打包和环境隔离问题…...
Cocos Creator Shader入门实战(七):RGB不同算法效果的实现,及渲染技术、宏定义、属性参数的延伸配置
引擎:3.8.5 您好,我是鹤九日! 回顾 上篇文章,讲解了Cocos Shader如何通过setProperty动态设置材质的属性,以及设置属性时候的一些注意事项,比如: 一、CCEffect部分properties参数的设定后&…...
leetcode102 二叉树的层次遍历 递归
(1) 找出重复的子问题。 层次遍历是每一层的节点从左到右的遍历,所以在遍历的时候我们可以先遍历左子树,再遍历右子树。 需要注意的是,在遍历左子树或者右子树的时候,涉及到向上或者向下遍历,为了让递归的过程中的同…...
