中山大学数据科学与计算机学院本科生实验报告
(2019年秋季学期)
课程名称 | 手机平台应用开发 | 任课老师 | 郑贵锋 |
---|---|---|---|
年级 | 2019级 | 专业(方向) | 软件工程计应方向 |
学号 | 17343123 | 姓名 | 吴宗原 |
电话 | 15013029107 | 1120902512@qq.com | |
开始日期 | 2019.12 | 完成日期 | 2020.01 |
一、实验题目
期末项目——![xxx](https://i-blog.csdnimg.cn/blog_migrate/b148b8b972f46573cdd85f5dd02c33b5.png)
二、实现内容
本人负责的应用的实现部分:
1.个人信息页面的UI优化
2.导航栏控制的三个页面的手势滑动(左右滑动切换页面)的功能
3.底部导航栏的实现(点击底部导航栏切换不同页面)
4.整合代码,协助完成测试
三、实验结果
(1)实验截图
(2)实验步骤以及关键代码
个人信息界面的UI
个人信息界面有以下组件:一个旋转的个人头像、一个Segmented控件引导的ViewController子界面,子界面中有个人的详细信息以及一个退出登录的Cell。
1.旋转头像的实现函数(UIButton *)rotate360DegreeWithImageView:(UIButton *)imageView
-(UIButton *)rotate360DegreeWithImageView:(UIButton *)imageView{
CABasicAnimation *animation = [ CABasicAnimation animationWithKeyPath: @"transform" ];
animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DIdentity];
//围绕Z轴旋转,垂直与屏幕
animation.toValue = [ NSValue valueWithCATransform3D:CATransform3DMakeRotation(M_PI/2.0, 0.0, 0.0, 1.0) ];
animation.duration = 3;
//旋转效果累计,先转180度,接着再旋转180度,从而实现360旋转
animation.cumulative = YES;
animation.repeatCount = MAXFLOAT;
CGRect imageRrect = CGRectMake(0, 0,imageView.imageView.frame.size.width, imageView.imageView.frame.size.height);
UIGraphicsBeginImageContext(imageRrect.size);
//在图片边缘添加一个像素的透明区域,去图片锯齿
[imageView.currentImage drawInRect:CGRectMake(1,1,imageView.imageView.frame.size.width-2,imageView.imageView.frame.size.height-2)];
[imageView setImage: UIGraphicsGetImageFromCurrentImageContext() forState:UIControlStateNormal];
UIGraphicsEndImageContext();
[imageView.layer addAnimation:animation forKey:nil];
return imageView;
}
2.子界面的信息 (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
NSString *cellID=@"ProfileViewCell";
ProfileViewCell *cell= [tableView cellForRowAtIndexPath:indexPath];
if(nil==cell){
cell=[[ProfileViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];
}
cell.backgroundColor=[UIColor clearColor];
cell.textLabel.backgroundColor=[UIColor clearColor];
if(indexPath.row==4)
cell.textLabel.text=@"退出登录";
else cell.textLabel.text=_details[indexPath.row+1];
cell.textLabel.textAlignment=NSTextAlignmentCenter;
//UIImageView *IconView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"背景1.jpeg"]];
cell.imageView.image=[UIImage imageNamed:dataList[indexPath.row]];
/*
cell.detailTextLabel.text = details[indexPath.row];
cell.detailTextLabel.textColor=[UIColor blackColor];
cell.textLabel.textAlignment = NSTextAlignmentLeft;
*/
cell.layer.masksToBounds = NO;
cell.layer.cornerRadius = 8.0;
return cell;
}
3.毛玻璃效果
UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
UIVisualEffectView *visualView = [[UIVisualEffectView alloc]initWithEffect:blurEffect];
visualView.frame = CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height);;
[self.view addSubview:visualView];
底部导航栏的相关函数,包括滑动动画的实现以及自定义导航栏。
1.滑动动画相关
@interface TransitionController()
@property (nonatomic, weak) id<UIViewControllerContextTransitioning> transitionContext;
@property (nonatomic, strong, readonly) UIPanGestureRecognizer *gestureRecognizer;
@property (nonatomic, readwrite) CGPoint initialTranslationInContainerView;
@end
@implementation TransitionController
- (instancetype)initWithGestureRecognizer:(UIPanGestureRecognizer *)gestureRecognizer{
self = [super init];
if (self){
_gestureRecognizer = gestureRecognizer;
[_gestureRecognizer addTarget:self action:@selector(gestureRecognizeDidUpdate:)];
}
return self;
}
- (instancetype)init{
@throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"Use -initWithGestureRecognizer:" userInfo:nil];
}
- (void)dealloc{
[self.gestureRecognizer removeTarget:self action:@selector(gestureRecognizeDidUpdate:)];
}
- (void)startInteractiveTransition:(id<UIViewControllerContextTransitioning>)transitionContext{
self.transitionContext = transitionContext;
self.initialTranslationInContainerView = [self.gestureRecognizer translationInView:transitionContext.containerView];
[super startInteractiveTransition:transitionContext];
}
- (CGFloat)percentForGesture:(UIPanGestureRecognizer *)gesture{
UIView *transitionContainerView = self.transitionContext.containerView;
CGPoint translation = [gesture translationInView:gesture.view.superview];
if ((translation.x > 0.f && self.initialTranslationInContainerView.x < 0.f) ||
(translation.x < 0.f && self.initialTranslationInContainerView.x > 0.f)){
return -1.f;
}
return fabs(translation.x)/CGRectGetWidth(transitionContainerView.bounds);
}
- (void)gestureRecognizeDidUpdate:(UIScreenEdgePanGestureRecognizer *)gestureRecognizer{
switch (gestureRecognizer.state) {
case UIGestureRecognizerStateBegan:
break;
case UIGestureRecognizerStateChanged:
if ([self percentForGesture:gestureRecognizer] < 0.f) {
[self cancelInteractiveTransition];
[self.gestureRecognizer removeTarget:self action:@selector(gestureRecognizeDidUpdate:)];
}
else {
[self updateInteractiveTransition:[self percentForGesture:gestureRecognizer]];
}
break;
case UIGestureRecognizerStateEnded:
if ([self percentForGesture:gestureRecognizer] >= 0.4f){
[self finishInteractiveTransition];
}
else{
[self cancelInteractiveTransition];
}
break;
default:
[self cancelInteractiveTransition];
break;
}
}
@end
@implementation TransitionAnimation
- (instancetype)initWithTargetEdge:(UIRectEdge)targetEdge{
self = [self init];
if (self) {
_targetEdge = targetEdge;
}
return self;
}
- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext{
return 0.35;
}
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext{
UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
UIView *fromView = [transitionContext viewForKey:UITransitionContextFromViewKey];
UIView *toView = [transitionContext viewForKey:UITransitionContextToViewKey];
CGRect fromFrame = [transitionContext initialFrameForViewController:fromViewController];
CGRect toFrame = [transitionContext finalFrameForViewController:toViewController];
CGVector offset;
if (self.targetEdge == UIRectEdgeLeft){
offset = CGVectorMake(-1.f, 0.f);
}
else if (self.targetEdge == UIRectEdgeRight){
offset = CGVectorMake(1.f, 0.f);
}
else{
NSAssert(NO, @"targetEdge must be one of UIRectEdgeLeft, or UIRectEdgeRight.");
}
fromView.frame = fromFrame;
toView.frame = CGRectOffset(toFrame,
toFrame.size.width * offset.dx * -1,
toFrame.size.height * offset.dy * -1);
[transitionContext.containerView addSubview:toView];
NSTimeInterval transitionDuration = [self transitionDuration:transitionContext];
[UIView animateWithDuration:transitionDuration animations:^{
fromView.frame = CGRectOffset(fromFrame,
fromFrame.size.width * offset.dx,
fromFrame.size.height * offset.dy);
toView.frame = toFrame;
} completion:^(BOOL finished) {
[transitionContext completeTransition:![transitionContext transitionWasCancelled]];
}];
}
@end
2.自定义TabBarViewController
@interface TabBarViewController ()<UITabBarControllerDelegate>
@property(nonatomic, strong)UIPanGestureRecognizer *panGestureRecognizer;
@end
@implementation TabBarViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.delegate = self;
self.selectedIndex = 0;
[self.view addGestureRecognizer:self.panGestureRecognizer];
NSArray<UIColor *> *colors = @[[UIColor orangeColor], [UIColor redColor], [UIColor blueColor], [UIColor yellowColor], [UIColor purpleColor]];
NSMutableArray *vcs = [[NSMutableArray alloc] init];
for (UIColor *color in colors) {
ViewController *vc = [[ViewController alloc]init];
vc.view.backgroundColor = color;
[vcs addObject:vc];
}
self.viewControllers = vcs;
for (int i = 0; i < self.tabBar.items.count; i ++) {
NSDictionary *dic = @{NSForegroundColorAttributeName: [UIColor colorWithRed:0.451 green:0.553 blue:0.584 alpha:1.00]};
NSDictionary *selecteddic = @{NSForegroundColorAttributeName: [UIColor colorWithRed:0.384 green:0.808 blue:0.663 alpha:1.00]};
UITabBarItem *item = [self.tabBar.items objectAtIndex:i];
[item setTitleTextAttributes:dic forState:UIControlStateNormal];
[item setTitleTextAttributes:selecteddic forState:UIControlStateSelected];
switch (i) {
case 0:
item.title = @"壹";
break;
case 1:
item.title = @"贰";
break;
case 2:
item.title = @"叁";
break;
case 3:
item.title = @"肆";
break;
case 4:
item.title = @"伍";
break;
default:
break;
}
}
}
- (UIPanGestureRecognizer *)panGestureRecognizer{
if (_panGestureRecognizer == nil){
_panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGestureRecognizer:)];
}
return _panGestureRecognizer;
}
- (void)panGestureRecognizer:(UIPanGestureRecognizer *)pan{
if (self.transitionCoordinator) {
return;
}
if (pan.state == UIGestureRecognizerStateBegan || pan.state == UIGestureRecognizerStateChanged){
[self beginInteractiveTransitionIfPossible:pan];
}
}
- (void)beginInteractiveTransitionIfPossible:(UIPanGestureRecognizer *)sender{
CGPoint translation = [sender translationInView:self.view];
if (translation.x > 0.f && self.selectedIndex > 0) {
self.selectedIndex --;
}
else if (translation.x < 0.f && self.selectedIndex + 1 < self.viewControllers.count) {
self.selectedIndex ++;
}
}
- (id<UIViewControllerAnimatedTransitioning>)tabBarController:(UITabBarController *)tabBarController animationControllerForTransitionFromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC{
NSArray *viewControllers = tabBarController.viewControllers;
if ([viewControllers indexOfObject:toVC] > [viewControllers indexOfObject:fromVC]) {
return [[TransitionAnimation alloc] initWithTargetEdge:UIRectEdgeLeft];
}
else {
return [[TransitionAnimation alloc] initWithTargetEdge:UIRectEdgeRight];
}
}
- (id<UIViewControllerInteractiveTransitioning>)tabBarController:(UITabBarController *)tabBarController interactionControllerForAnimationController:(id<UIViewControllerAnimatedTransitioning>)animationController{
if (self.panGestureRecognizer.state == UIGestureRecognizerStateBegan || self.panGestureRecognizer.state == UIGestureRecognizerStateChanged) {
return [[TransitionController alloc] initWithGestureRecognizer:self.panGestureRecognizer];
}
else {
return nil;
}
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
@end
四、个人总结与个人贡献评分
个人感觉自己在这次项目中的贡献不算太多,完成过程还是比较快的,完成的部分主要是一些前端的内容,包括TabBar和个人信息的界面,后端的内容并没有涉及。但是还是感觉巩固了很多学习到的东西,包括如何从服务器返回的json包中提取出想要的信息,一些自定义动画、自定义组件的实现等内容。完成之后也是整合了其他同学的代码,协助写完后端的同学测试了通信的有效性,录制了视频。
个人贡献评分:85
五、实验思考及感想
这次的项目认识到了一个软件开发的过程中需要的知识还是很多的,包括UI设计、前后端开发、软件测试等多个方面,一个人是没办法面面俱到的,同时体现了多人开发时协作交流的重要性。这次项目还是尽可能把这学期学到的很多Objective-c的知识用上去了,也去了解了前后端交互的一些调用以及整个流程,总的来说还是获益匪浅。