iOS自定义UITableView实现不同系统下的左滑删除功能详解

前言

在我们的app开发当中,经常会用到UITableView 的左滑删除的功能,通常的话效果如下

但有时候系统现有的功能并不能完全满足我们的开发需求,这样就需要我们在其现有的功能基础上自定义我们所需要的功能了。下图是在项目中自定义的按钮(只是修改了按钮的frame而已)。

然后我就总结了一下根据不同的需求自定义不同的按钮。

一、系统默认左滑删除按钮

如果你对左滑删除按钮的要求不高,仅仅只是实现UITableView上cell的左滑删除功能,那在UITableView的代理方法中添加以下两种方法便可实现需求:

//使用系统默认的删除按钮
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
 if (editingStyle == UITableViewCellEditingStyleDelete){

 }
}
//自定义系统默认的删除按钮文字
- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath {
 return @"自定义按钮”;
}

效果如下所示:


系统自带

虽然这样能基本实现功能,但是我们发现右边的按钮和左边的黄色区域的高度并不一样。这是因为右边按钮是和UITableViewCell的高度一致,而左边的黄色区域只是一张图片而已,其高度设置和UITableViewCell的高度并不一致,才会导致这样的布局出现。如果我们想要删除按钮和左边图片一样的高度,那我们就需要自定义删除按钮的高度了。

二、自定义左滑删除按钮

如果我们想要实现不止一个自定义按钮的功能,那我们就需要在UITableView代理方法- (NSArray<UITableViewRowAction *> *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath {}中添加我们所需要的多个按钮了。如下是在不同的cell上添加一个或两个左滑按钮:

//自定义多个左滑菜单选项
- (NSArray<UITableViewRowAction *> *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath {
 UITableViewRowAction *deleteAction;
 deleteAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"删除" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath) {
 [tableView setEditing:NO animated:YES];//退出编辑模式,隐藏左滑菜单
 }];
 if (indexPath.row == 1) {//在不同的cell上添加不同的按钮
 UITableViewRowAction *shareAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"分享" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath) {
  [tableView setEditing:NO animated:YES];//退出编辑模式,隐藏左滑菜单
 }];
 shareAction.backgroundColor = [UIColor blueColor];
 return @[deleteAction,shareAction];
 }
 return @[deleteAction];
}

在上述代理方法中我们就可以实现在cell中添加一个或多个左滑按钮了,根据点击不同的按钮实现不同的响应方法便可。其中[tableView setEditing:NO animated:YES];方法可以在点击按钮之后退出编辑模式并隐藏左滑菜单。但如果我们想要修改按钮的其他属性如标题、背景颜色怎么办?点击进入UITableViewRowAction类中,我们会发现以下属性和方法:

@interface UITableViewRowAction : NSObject <NSCopying>

+ (instancetype)rowActionWithStyle:(UITableViewRowActionStyle)style title:(nullable NSString *)title handler:(void (^)(UITableViewRowAction *action, NSIndexPath *indexPath))handler;

@property (nonatomic, readonly) UITableViewRowActionStyle style;
@property (nonatomic, copy, nullable) NSString *title;
@property (nonatomic, copy, nullable) UIColor *backgroundColor; // default background color is dependent on style
@property (nonatomic, copy, nullable) UIVisualEffect* backgroundEffect;

@end

其中 @property (nonatomic, readonly) UITableViewRowActionStyle style;是指设置所添加按钮父视图的背景颜色以及按钮字体颜色:

typedef NS_ENUM(NSInteger, UITableViewRowActionStyle) {
 UITableViewRowActionStyleDefault = 0,//红底白字
 UITableViewRowActionStyleDestructive = UITableViewRowActionStyleDefault,
 UITableViewRowActionStyleNormal//灰底白字
} NS_ENUM_AVAILABLE_IOS(8_0) __TVOS_PROHIBITED;

@property (nonatomic, copy, nullable) UIVisualEffect* backgroundEffect;提供了一个背景模糊效果,有兴趣的可以自行研究一下。

上述的方法和属性只能满足我们的部分需求,如果我们想要改变按钮的大小或者设置带图片的按钮怎么办?那就需要我们在视图中找到我们所要修改的按钮,并设置它的各种属性。由于在iOS8-10和iOS11下自定义按钮处在不同的视图层次中,所以需要我们先了解UITableView上的视图层次。下图为对比:

左iOS10/右iOS11(Xcode9中)

从对比图中可以看出:

(1).iOS10下视图层次为:UITableView -> UITableViewCell -> UITableViewCellDeleteConfirmationView -> _UITableViewCellActionButton,我们所需自定义的按钮视图UITableViewCellDeleteConfirmationView(左图中红框处)是UITableViewCell的子视图。

(2).iOS11下视图层次为:在Xcode 8中编译为: UITableView -> UITableViewWrapperView -> UISwipeActionPullView -> UISwipeActionStandardButton;

在Xcode 9中编译为: UITableView -> UISwipeActionPullView -> UISwipeActionStandardButton。(iOS11中用Xcode 8和Xcode 9中编译有略微的差别),我们所需自定义的按钮视图UISwipeActionPullView(右图中红框处)是UITableView的子视图。

由于不同系统下的视图层次不一样,因此我们在项目中需要根据不同的代码去同时适配iOS8-10和iOS11。
在iOS8-10中( 以下均在Xcode 9中编译):

在该系统下由于我们所需自定义的按钮视图UITableViewCellDeleteConfirmationView是UITableViewCell的子视图,所以我们在自定义UITableViewCell子类中遍历它的subviews即可。代码如下:

- (void)layoutSubviews {
 /**自定义设置iOS8-10系统下的左滑删除按钮大小*/
 for (UIView * subView in self.subviews) {
 if ([subView isKindOfClass:NSClassFromString(@"UITableViewCellDeleteConfirmationView")]) {
  subView.backgroundColor = [UIColor clearColor];//去掉默认红色背景
  //设置按钮frame
  CGRect cRect = subView.frame;
  cRect.origin.y = self.contentView.frame.origin.y + 10;
  cRect.size.height = self.contentView.frame.size.height - 20;
  subView.frame = cRect;
  //自定义按钮的文字大小
  if (subView.subviews.count == 1 && self.indexPath.section == 0) {//表示有一个按钮
  UIButton * deleteButton = subView.subviews[0];
  deleteButton.titleLabel.font = [UIFont systemFontOfSize:20];
  }
  //自定义按钮的图片
  if (subView.subviews.count == 1 && self.indexPath.section == 1) {//表示有一个按钮
  UIButton * deleteButton = subView.subviews[0];
  [deleteButton setImage:[UIImage imageNamed:@"login_btn_message"] forState:UIControlStateNormal];
  [deleteButton setTitle:@"" forState:UIControlStateNormal];
  }
  //自定义按钮的文字图片
  if (subView.subviews.count >= 2 && self.indexPath.section == 0) {//表示有两个按钮
  UIButton * deleteButton = subView.subviews[1];
  UIButton * shareButton = subView.subviews[0];
  [deleteButton setTitle:@"" forState:UIControlStateNormal];
  [shareButton setTitle:@"" forState:UIControlStateNormal];
  [self setUpDeleteButton:deleteButton];
  [self setUpShareButton:shareButton];
  }
 }
 }
}

在iOS11中:

在该系统下由于我们所需自定义的按钮视图UISwipeActionPullView是UITableView的子视图,所以我们可以在控制器中自定义UITableView子类中遍历它的subviews即可(以下方法是写在UITableView的代理方法- (void)tableView:(UITableView *)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath中的,该代理方法每次会在开始左滑按钮前调用)。代码如下:

/**自定义设置iOS11系统下的左滑删除按钮大小*/
//开始编辑左滑删除
- (void)tableView:(UITableView *)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath {
 NSInteger section = indexPath.section;
 if (@available(iOS 11.0, *)) {
  for (UIView * subView in self.customTableView.subviews) {
   if ([subView isKindOfClass:NSClassFromString(@"UISwipeActionPullView")]) {
    subView.backgroundColor = [UIColor clearColor];//如果自定义只有一个按钮就要去掉按钮默认红色背景
    //设置按钮frame
    for (UIView * sonView in subView.subviews) {
     if ([sonView isKindOfClass:NSClassFromString(@"UISwipeActionStandardButton")]) {
      CGRect cRect = sonView.frame;
      cRect.origin.y = sonView.frame.origin.y + 10;
      cRect.size.height = sonView.frame.size.height - 20;
      sonView.frame = cRect;
     }
    }
    //自定义按钮的文字大小
    if (subView.subviews.count == 1 && section == 0) {//表示有一个按钮
     UIButton * deleteButton = subView.subviews[0];
     deleteButton.titleLabel.font = [UIFont systemFontOfSize:20];
    }
    //自定义按钮的图片
    if (subView.subviews.count == 1 && section == 1) {//表示有一个按钮
     UIButton * deleteButton = subView.subviews[0];
     [deleteButton setImage:[UIImage imageNamed:@"login_btn_message"] forState:UIControlStateNormal];;
    }
    //自定义按钮的文字图片
    if (subView.subviews.count >= 2 && section == 0) {//表示有两个按钮
     UIButton * deleteButton = subView.subviews[1];
     UIButton * shareButton = subView.subviews[0];
     [self setUpDeleteButton:deleteButton];
     [self setUpShareButton:shareButton];
    }
   }
  }
 }
}

如果我们想在左滑删除结束后实现一些功能,我们可以在UITableView中实现以下代理方法:

//结束编辑左滑删除
- (void)tableView:(UITableView *)tableView didEndEditingRowAtIndexPath:(NSIndexPath *)indexPath {

}
如果我们想分别设置UITableViewCell是否需要实现左滑功能,可以在下面代理方法中实现:

//判断是否显示左滑删除
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
 return YES;
}

在不同系统下分别添加以上代码即可实现我们所需要的自定义左滑删除按钮,效果图如下:

以上是我总结整理的在不同系统下的自定义UITableView左滑删除功能。

如有不足之处,欢迎指正交流,Demo地址:左滑删除 (本地下载)

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

时间: 2018-09-05

ios UITableView 自定义右滑删除的实现代码

公司有个奇葩需求.删除按钮带点圆角 不止如此,还有cell之间有间隔,cell圆角,cell左右有间隔.如下图!!!!! 内心奔溃的我想了想了很多方法.(获取系统自带按钮改圆角也试过,自定义手势也试过)最后决定全部自定义.个人感觉这样最合适.下面是效果图 今天有时间,稍微说下实现方式: 这个项目工程只是提供一种思路,应对场景是 需要自定义左滑删除按钮的样式. 因为项目本身并不是修改系统的左滑删除,而是自定义实现,所以任何样式都算使用. 下面先说下项目的结构类型 最底下自然是uitableview

详解ios中自定义cell,自定义UITableViewCell

通过继承UITableViewCell来自定义cell 1.创建一个空的项目.命名: 2.创建一个UITableViewController 并且同时创建xib: 3.设置AppDelegate.m中window的根控制器为刚刚创建的TableViewController: - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { s

iOS开发之UITableView左滑删除等自定义功能

前言 相信每位iOS开发者都知道UITableView的左滑删除功能非常的炫酷,有时候左滑需要的功能不止只有删除一个,有时候会有顶置之类的别的功能,这时候就需要我们自己定制左滑 示例代码 -(NSArray<UITableViewRowAction*>*)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewRowAction *rowActio

全面解析iOS应用中自定义UITableViewCell的方法

有时候我们需要自己定义UITableViewCell的风格,其实就是向行中添加子视图.添加子视图的方法主要有两种:使用代码以及从.xib文件加载.当然后一种方法比较直观. 一.基本用法 我们这次要自定义一个Cell,使得它像QQ好友列表的一行一样:左边是一张图片,图片的右边是三行标签: 当然,我们不会搞得这么复杂,只是有点意思就行. 1.运行Xcode 4.2,新建一个Single View Application,名称为Custom Cell: 2.将图片资源导入到工程.为此,我找了14张50

iOS App开发中使用及自定义UITableViewCell的教程

UITableView用来以表格的形式显示数据.关于UITableView,我们应该注意: (1)UITableView用来显示表格的可见部分,UITableViewCell用来显示表格的一行. (2)UITableView并不负责存储表格中的数据,而是仅仅存储足够的数据使得可以画出当前可见部分. (3)UITableView从UITableViewDelegate协议获取配置信息,从UITableViewDataSource协议获得数据信息. (4)所有的UITableView实现时实际上只有

iOS应用中UITableView左滑自定义选项及批量删除的实现

实现UITableView左滑自定义选项 当UITableView进入编辑模式,在进行左滑操作的cell的右边,默认会出现Delete按钮,如何自定义左滑出现的按钮呢? 只需要实现UITableView下面的这个代理方法. 复制代码 代码如下: - (NSArray<UITableViewRowAction *> *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath

实例讲解iOS应用开发中使用UITableView创建自定义表格

一.带索引目录的表视图 1.效果图 2.数据源 本想获取通讯录中得名字,但为了用模拟器调试方便,就写死了数据,所以也只写了部分字母,总之有那么点意思就成 复制代码 代码如下: @interface ViewController ()<UITableViewDataSource,UITableViewDelegate> {     NSArray *sectionTitles; // 每个分区的标题     NSArray *contentsArray; // 每行的内容 } /** @brie

iOS中UITableView Cell实现自定义单选功能

今天分享下cell的单选,自定义的,不是下图这种网上找到的打对勾的,我搜了好久,基本上都是打对勾的文章,就决定自己写一篇.基本上自己的app都会有一个风格吧,咱也不能一直用打对勾的方式去做(看起来是不是很low). 我们要实现的是下面的这种形式.瞬间好看了很多,高大上了很多是吧. 具体我来给大家介绍一下.我这种方法有可能不是很好,有大神来,欢迎多多交流. 首先在你自定义的cell里面加入一个UIImageView,因为你肯定要有选择和未选择两张图片的吧,所以这个UIImageView来切换图片.

IOS中UITableView滚动到指定位置

方法很简单: - (void)scrollToRowAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated 有些需要注意的地方: 如果在reloadData后需要立即获取tableview的cell.高度,或者需要滚动tableview,那么,直接在reloadData后执行代码是有可能出问题的. reloadDa

iOS中UITableview错位的问题怎么修复

问题描述: 问题1:当一个navigation导航进入到UITabBarController   TabBar里面有多个页面,页面下有tableView,当我进入Tableview的时候,上面两行table给挡住了,当我点击进去返回回来又没有可以看得见了,发现table向上的是44PT刚好是一个top bar 的位置.(但是从这个页面的父页面push到这个页面还是被挡住了,但是我从这个页面的子页面pop出来又不会被挡住) 问题2: 做UISearchBar,UISearchDisplayCont

vue中实现Monaco Editor自定义提示功能

这次接到一个需求,要在浏览器的 IDE 中支持自定义提示功能,如下所示: 可以看到,它可以根据用户输入的内容来一项一项排除,只显示完全匹配的那一项. 项目的框架是 Vue ,编辑器用的是 Monaco Editor . 什么是 Monaco Editor vscode 是我们经常在用的编辑器,它的前身是微软的一个叫 Monaco Workbench 的项目,而 Monaco Editor 就是从这个项目中成长出来的一个 web 编辑器,他们很大一部分的代码都是共用的,所以 Monaco Edit

详细整理iOS中UITableView的性能优化

一.介绍 iOS开发中,UITableView可能是平时我们打交道最多的UI控件之一,其重要性不言而喻.Android也是如此,Android中的ListView和UITableView是相同功能的一个控件,但是iOS的UITableView更为强大一点,原因就不说了,如果你学过Android就知道iOS中的UITableView使用起来是非常简单的,这也是峰哥喜欢iOS胜过Android的原因之一.今天研究的内容就是UITableView的优化. 开始之前,你能说出几种UITableView的

详解iOS开发中UITableview cell 顶部空白的多种设置方法

我知道没人会主动设置这个东西,但是大家一定都遇到过这个问题,下面总结下可能是哪些情况: 1, self.automaticallyAdjustsScrollViewInsets = NO; 这个应该是最常见而且不容易被发现的原因,起因是iOS7在Conttoller中新增了automaticallyAdjustsScrollViewInsets这个属性,当设置为YES时(默认YES),如果视图里面存在唯一一个UIScrollView或其子类View,那么它会自动设置相应的内边距,这样可以让scr

iOS中tableView cell分割线的一些设置技巧

前言 对于iOS的tableView的cell的分割线,一般我们很少使用不是系统默认的,但是有些项目要求还是要求我们去改变分割线的颜色或者外形以配合整个项目的色调.这个苹果公司早都为我们想到了. 一.关于分割线的位置. 分割线的位置就是指分割线相对于tableViewCell.如果我们要根据要求调节其位置,那么在iOS7.0版本以后,提供了一个方法如下: if ([self.tableView respondsToSelector:@selector(setSeparatorInset:)])

iOS中UITableView使用的常见问题总结

1.如何设置headerView以及其高度 tableView.tableHeaderView = myHeaderView let height = headerView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height var frame = headerView.frame frame.size.height = height headerView.frame = frame 2.去掉多余cell的分割线 s

iOS中实现动态区域裁剪图片功能实例

前言 相信大家应该都有所体会,裁剪图片功能在很多上传图片的场景里都需要用到,一方面应用服务器可能对图片的尺寸大小有限制,因而希望上传的图片都是符合规定的,另一方面,用户可能希望只上传图片中的部分内容,突出图片中关键的信息.而为了满足用户多种多样的裁剪需求,就需要裁剪图片时能支持由用户动态地改变裁剪范围.裁剪尺寸等. 动态裁剪图片的基本过程大致可以分为以下几步 显示图片与裁剪区域 支持移动和缩放图片 支持手势改变裁剪区域 进行图片裁剪并获得裁剪后的图片 显示图片与裁剪区域 显示图片 在裁剪图片之前