抽屉效果重写

//  这是主界面的内容,可以拖动主界面实现效果
//  MainViewController.m
//  WangYiDrawer
//
//  Created by xiaoyao on 15/2/9.
//  Copyright (c) 2015年 lijien. All rights reserved.
//

#import "MainViewController.h"
#import "LeftViewController.h"
#import "RightViewController.h"
#import <QuartzCore/QuartzCore.h>

#define kEndX frame.origin.x // 手势结束的x
#define kLeftViewWidth _leftView.frame.size.width // 左部view的宽度
#define kRightViewWidth _rightView.frame.size.width // 右部view的宽度

@interface MainViewController ()<LeftViewControllerDelegate> {
  CGFloat _startX;                             // 手势刚开始触发时的起点
  LeftViewController *_leftViewController;     // 左部视图控制器
  RightViewController *_rightViewController;   // 右边视图控制器
  NSMutableDictionary *_columnViewControllers; // 记录下所有已经实例化的控制器对象防止重复创建
  UIView *_mainView;
}
@end

@implementation MainViewController

- (void)viewDidLoad {
  [super viewDidLoad];

  _mainView.frame = self.view.bounds;
  [self.view addSubview:_mainView];

  _titleButton.backgroundColor = [UIColor clearColor];
  _columnViewControllers = [[NSMutableDictionary alloc] init];

  // 将左侧视图控制器的视图添加到左侧view上
  _leftViewController = [[LeftViewController alloc] init];
  _leftViewController.view.frame = _leftView.frame;
  _leftViewController.delegate = self;
  [_leftView addSubview:_leftViewController.view];

  // 将右侧视图控制器的视图添加到左侧view上
  _rightViewController = [[RightViewController alloc] init];
  _rightViewController.view.frame = _rightView.frame;
  [_rightView addSubview:_rightViewController.view];

  UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGesture:)];
  [self.view addGestureRecognizer:pan];

 // 首次加载的时候就应该显示新闻的内容
  [self firstLoading];
}

// 隐藏状态栏
- (BOOL)prefersStatusBarHidden {
  return YES;
}

- (void)firstLoading {
  Column *column = [Column columnName:@"新闻" imgName:@"news.png" className:@"NewsViewController"];
  [self leftTableViewRowClicked:column];
}

- (void)panGesture:(UIPanGestureRecognizer *)pan {
  // 如果状态是刚刚开始拽就记录下当前的起始x
  if(UIGestureRecognizerStateBegan == pan.state) {
    _startX = self.view.frame.origin.x;
  }

  // 计算出平移拖动的距离
  CGPoint delta = [pan translationInView:self.view];
  CGRect frame = _mainView.frame;

  kEndX = _startX + delta.x;
  // 限制拖动范围
  if (kEndX >= kLeftViewWidth) {
    kEndX = kLeftViewWidth;
  }

  if (kEndX <= - kRightViewWidth) {
    kEndX = - kRightViewWidth;
  }

  // 由于leftView 和 rightView 是重合的所以必须要隐藏一个
  if (kEndX > 0) {
    _rightView.hidden = YES;
    _leftView.hidden = NO;
  } else {
    _rightView.hidden = NO;
    _leftView.hidden = YES;
  }

  if (UIGestureRecognizerStateEnded == pan.state) {
    if (_startX == 0 && delta.x > 0) {
      kEndX = kLeftViewWidth;
    } else if (_startX == 0 && delta.x < 0) {
      kEndX = - kRightViewWidth;
    } else if (_startX == kLeftViewWidth && delta.x < 0) {
      kEndX = 0;
    } else if (_startX == -kRightViewWidth && delta.x > 0) {
      kEndX = 0;
    }
  }

  // 最后重新设置mainView frame
  [UIView animateWithDuration:0.2 animations:^{
    _mainView.frame = frame;
  }];

  // 给mianView添加阴影图层
  [self addShadowForMianViewWithEndX:kEndX];
}

- (void)addShadowForMianViewWithEndX:(CGFloat)endX {
  _mainView.layer.shadowColor = [UIColor blackColor].CGColor;
  _mainView.layer.shadowOpacity = 0.5;
  if (endX > 0) {
    _mainView.layer.shadowOffset = CGSizeMake(-5, 0);
  } else {
    _mainView.layer.shadowOffset = CGSizeMake(5, 0);
  }
}

#pragma mark - leftViewDelegate
- (void)leftTableViewRowClicked:(Column *)rowSelected {
  Column *column = (Column *)rowSelected;
  // 1,关闭左边的控制=======================
  // 调用抽取出来的公共代码,设置mainView的x,参数是endX
  [self setmainViewX:0];
  // 2,更改标题按钮上面的文字
  _titleButton.titleLabel.text = column.columnName;

  // 根据栏目数据模型中的类名,实例化对应栏目的控制器,并且将其设置为导航控制器的根控制器,最后将导航控制器的view添加到mainView中,目的是方便设置导航条,以及,各控制器的跳转

  // 2,从缓存字典中取,如果子控制器字典有曾经创建过的子控制器,直接取出来用
  UIViewController *columnVC = _columnViewControllers[column.columnClassName];
  // 如果子控制器字典中没有保存过该栏目的控制器,才要创建子控制器
  if (columnVC == nil) {
    Class c = NSClassFromString(column.columnClassName);
    columnVC = [[c alloc]init];
    // 并且一定要将其放到 子控制器字典里面,存起来
    [_columnViewControllers setObject:columnVC forKey:column.columnClassName];
  }

  // 4,移除contentView中的正在显示的旧的子view
  if (_contentView.subviews.count > 0) {
    UIView *oldView = [_contentView subviews][0];
    [oldView removeFromSuperview];
  }

  // 5,最后将子控制器的view添加到contentView中,显示
  columnVC.view.frame = _contentView.bounds;
  [self.contentView addSubview:columnVC.view];
  NSLog(@"%@",self.contentView);
  // 在添加到mainView之前 ,先得到mainView导航控制器的子控制器,并将其移除(如果有的话)
}

// 抽取出来的公共代码,设置mainView的x,参数是endX
- (void)setmainViewX:(CGFloat)endX
{
  CGRect frame = _mainView.frame;
  frame.origin.x = endX;
  [UIView animateWithDuration:0.2 animations:^{
    _mainView.frame = frame;
  }];

}
@end
/**************** 左侧表格设定代理 *******/
//
//  LeftViewController.m
//  WangYiDrawer
//
//  Created by xiaoyao on 15/2/9.
//  Copyright (c) 2015年 lijien. All rights reserved.
//

#import "LeftViewController.h"

@interface LeftViewController () {
  NSArray *_classNameArray;
  UITableView *_tableView;
}
@end

@implementation LeftViewController

- (void)viewDidLoad {
  [super viewDidLoad];

  _tableView = [[UITableView alloc] initWithFrame:self.view.bounds];
  [self.view addSubview:_tableView];

  NSArray *titleArray = @[@"新闻", @"图片", @"跟帖"];
  NSArray *picArray = @[@"news.png", @"pic.png", @"comment.png"];

  Column *newsColumn = [Column columnName:titleArray[0] imgName:picArray[0] className:@"NewsViewController"];
  Column *picColumn = [Column columnName:titleArray[1] imgName:picArray[1] className:@"PicViewController"];
  Column *commentColumn = [Column columnName:titleArray[2] imgName:picArray[2] className:@"CommentViewController"];

  // 将创建的控制器对象添加到数组中管理
 //_className = [NSArray arrayWithObjects:newsColumn, picColumn, commentColumn, nil];
  _classNameArray = @[newsColumn, picColumn, commentColumn];
}

#pragma mark - UITableViewDelegate
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
  return _classNameArray.count;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
  return 40;
}

#pragma mark - UITableViewDataSource
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
  static NSString *cellIde = @"cellIde";
  UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIde];

  if (cell == nil) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIde];
  }

  if (indexPath.row < _classNameArray.count) {
    Column *column = [_classNameArray objectAtIndexedSubscript:indexPath.row];
    cell.textLabel.text = column.columnName;
    cell.imageView.image = [UIImage imageNamed:column.columnImgName];
  }
  return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
  // 取消每一行的高亮状态
  [tableView deselectRowAtIndexPath:indexPath animated:YES];

  Column *column = nil;
  if (indexPath.row < _classNameArray.count) {
    column = [_classNameArray objectAtIndexedSubscript:indexPath.row];
  }
  if ([self.delegate respondsToSelector:@selector(leftTableViewRowClicked:)]) {
    [self.delegate leftTableViewRowClicked:column];
  }
}
@end

时间: 2024-10-05 18:01:10

抽屉效果重写的相关文章

网易新闻侧滑抽屉效果(利用父子控制器实现)

一:类似于网易的抽屉效果,启动有广告,进入主界面后,点击左上角按钮,侧滑左抽屉,点击右上角,侧滑出右抽屉.点击左抽屉按钮,对视图进行切换 . 二代码: 1:启动图展示广告界面实现:先吧启动图控制器作为窗口的根视图控制器,展示完广告消失后,再切换窗口的根视图控制器为主控制器.其中窗口指的是项目中的主窗口也就是keyWindow,主窗口主要负责接收一些键盘事件,文本框输入事件,若是键盘文本框,textView或是textfield不能输入,则考虑是不是当前窗口是否是主窗口 @interface HM

iOS LeftMenu抽屉效果与ScrollView共存时的手势冲突

公司有个项目,需要做左侧滑动,首页是ScrollView嵌套TableView.首页是一个ScrollView,所以当contentOffset是0.0的时候,无法直接滑动出抽屉效果,用户体验感非常差.思考了一下还是手势的问题. 于是将ScrollView单独分了出来,重写了 - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer方法 在左滑动的时候return NO即可. #import "My

Android侧滑抽屉效果实现

1.先看效果图 2.说明 2.1目前市场上面很多软件都流行这种抽屉小果的实现,就我而言,这种设计是比较容易搭建框架的,而且UI效果也是非常不错的. 3 文章引用 3.1.Android 抽屉效果的导航菜单实现 3.2Android官方终于支持 Navigation Drawer(导航抽屉)模式 4.库的引用 4.1首先, DrawerLayout这个类是在Support Library里的,需要加上android-support-v4.jar这个包. 4.2然后程序中用时在前面导入import

实现侧边抽屉效果-YRSideViewController

在项目当中经常用到类似抽屉效果的页面转换,下面是简单的视图切换. 1,首先声明SideViewController,用来装所有要在屏幕中显示的控制器. 2,为SideViewController添加属性和方法,每个属性的作用都有注释.代码如下: // SliderViewController.h //普通动画的block typedef void(^RootViewMoveBlock) (UIView *rootView,CGRect orhinFrame,CGFloat xoffeset);

Android---62---DrawerLayout实现抽屉效果

如何实现android中的抽屉效果? 1.创建xml文件 其根视图是<android.support.v4.widget.DrawerLayout/> 这个xml分为两部分,一部分是主要内容的视图,一部分是抽屉的视图. 主要内容视图一般是FrameLayout,一定要是DrawerLayout的第一个视图,其高度和父视图的高度匹配. 抽屉视图一般是ListView,在写抽屉视图的时候要注意 1.宽度一般要小于320dp 2.android:layout_gravity属性是确定抽屉的位置 当该

利用DrawerLayout实现简单的抽屉效果

前言,本篇文章是最基础的利用DrawerLayout实现抽屉效果,我也是尽量精简到了最高效的代码,后面我会贴出其他比较复杂的功能. 先看效果图 标题栏中的文字,会根据点击item的不同,而显示不同的样式. 直接上代码. 下面是activity_main的代码 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.andr

第三方抽屉效果

1.  抽屉效果的基本原理应用了父子视图的层级,视图的位置改变,动画,手势操作等主要知识点.熟练掌握基础知识并灵活运用,即可实现该效果. > 父子视图的层级: 在指定层级上插入子视图 [view insertSubView: atIndex:] > 视图位置的改变: 通过视图的frame,center属性调整 > 动画:可使用UIView或CALayer的动画,这里主要使用了UIView的动画方法 [UIView animateWithDuration:……. ] > 手势操作:主

ios开发抽屉效果的封装使用

#import "DragerViewController.h" #define screenW [UIScreen mainScreen].bounds.size.width @interface DragerViewController () /** <#注释#> */ @property (nonatomic, weak) UIView *leftV; @property (nonatomic, weak) UIView *rightV; @property (non

动画的抽屉效果

添加三个View // // ViewController.m // UISenior17_抽屉效果 // // Created by lanou3g on 16/5/27. // Copyright © 2016年 张明杰. All rights reserved. // #import "ViewController.h" //frame #define XMGkeyPath(objc, keyPath) @(((void)objc.keyPath, #keyPath)) //获取