iOS自定義UITableView不同系統(tǒng)下的左滑刪除功能

在項(xiàng)目開發(fā)中我們往往會用到UITableView自帶的左滑刪除功能驻襟,但有時候系統(tǒng)現(xiàn)有的功能并不能完全滿足我們的開發(fā)需求,這樣就需要我們在其現(xiàn)有的功能基礎(chǔ)上自定義我們所需要的功能了抠藕。下圖是在項(xiàng)目中自定義的按鈕(只是修改了按鈕的frame而已)克婶。


然后我就總結(jié)了一下根據(jù)不同的需求自定義不同的按鈕获洲。

一磨取、系統(tǒng)默認(rèn)左滑刪除按鈕

如果你對左滑刪除按鈕的要求不高元潘,僅僅只是實(shí)現(xiàn)UITableView上cell的左滑刪除功能畔乙,那在UITableView的代理方法中添加以下兩種方法便可實(shí)現(xiàn)需求:

//使用系統(tǒng)默認(rèn)的刪除按鈕
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
    if (editingStyle == UITableViewCellEditingStyleDelete){

    }
}
//自定義系統(tǒng)默認(rèn)的刪除按鈕文字
- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath {
    return @"自定義按鈕”;
}

效果如下所示:


系統(tǒng)自帶

雖然這樣能基本實(shí)現(xiàn)功能,但是我們發(fā)現(xiàn)右邊的按鈕和左邊的黃色區(qū)域的高度并不一樣翩概。這是因?yàn)橛疫叞粹o是和UITableViewCell的高度一致牲距,而左邊的黃色區(qū)域只是一張圖片而已袖订,其高度設(shè)置和UITableViewCell的高度并不一致,才會導(dǎo)致這樣的布局出現(xiàn)嗅虏。如果我們想要刪除按鈕和左邊圖片一樣的高度洛姑,那我們就需要自定義刪除按鈕的高度了。

二皮服、自定義左滑刪除按鈕

如果我們想要實(shí)現(xiàn)不止一個自定義按鈕的功能楞艾,那我們就需要在UITableView代理方法- (NSArray<UITableViewRowAction *> *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath {}中添加我們所需要的多個按鈕了。如下是在不同的cell上添加一個或兩個左滑按鈕:

//自定義多個左滑菜單選項(xiàng)
- (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];
}

在上述代理方法中我們就可以實(shí)現(xiàn)在cell中添加一個或多個左滑按鈕了,根據(jù)點(diǎn)擊不同的按鈕實(shí)現(xiàn)不同的響應(yīng)方法便可择同。其中[tableView setEditing:NO animated:YES];方法可以在點(diǎn)擊按鈕之后退出編輯模式并隱藏左滑菜單两入。但如果我們想要修改按鈕的其他屬性如標(biāo)題、背景顏色怎么辦敲才?點(diǎn)擊進(jìn)入UITableViewRowAction類中裹纳,我們會發(fā)現(xiàn)以下屬性和方法:

@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;是指設(shè)置所添加按鈕父視圖的背景顏色以及按鈕字體顏色:

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

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

上述的方法和屬性只能滿足我們的部分需求剃氧,如果我們想要改變按鈕的大小或者設(shè)置帶圖片的按鈕怎么辦?那就需要我們在視圖中找到我們所要修改的按鈕阻星,并設(shè)置它的各種屬性朋鞍。由于在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的子視圖呛讲。

由于不同系統(tǒng)下的視圖層次不一樣禾怠,因此我們在項(xiàng)目中需要根據(jù)不同的代碼去同時適配iOS8-10和iOS11。

在iOS8-10中( 以下均在Xcode 9中編譯):

在該系統(tǒng)下由于我們所需自定義的按鈕視圖UITableViewCellDeleteConfirmationView是UITableViewCell的子視圖贝搁,所以我們在自定義UITableViewCell子類中遍歷它的subviews即可吗氏。代碼如下:

- (void)layoutSubviews {
    /**自定義設(shè)置iOS8-10系統(tǒng)下的左滑刪除按鈕大小*/
    for (UIView * subView in self.subviews) {
        if ([subView isKindOfClass:NSClassFromString(@"UITableViewCellDeleteConfirmationView")]) {
            subView.backgroundColor = [UIColor clearColor];//去掉默認(rèn)紅色背景
            //設(shè)置按鈕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中:

在該系統(tǒng)下由于我們所需自定義的按鈕視圖UISwipeActionPullView是UITableView的子視圖,所以我們可以在控制器中自定義UITableView子類中遍歷它的subviews即可(以下方法是寫在UITableView的代理方法- (void)tableView:(UITableView *)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath中的雷逆,該代理方法每次會在開始左滑按鈕前調(diào)用)弦讽。代碼如下:

/**自定義設(shè)置iOS11系統(tǒng)下的左滑刪除按鈕大小*/
//開始編輯左滑刪除
- (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];//如果自定義只有一個按鈕就要去掉按鈕默認(rèn)紅色背景
                //設(shè)置按鈕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];
                }
            }
        }
    }
}

如果我們想在左滑刪除結(jié)束后實(shí)現(xiàn)一些功能,我們可以在UITableView中實(shí)現(xiàn)以下代理方法:

//結(jié)束編輯左滑刪除
- (void)tableView:(UITableView *)tableView didEndEditingRowAtIndexPath:(NSIndexPath *)indexPath {

}

如果我們想分別設(shè)置UITableViewCell是否需要實(shí)現(xiàn)左滑功能,可以在下面代理方法中實(shí)現(xiàn):

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

在不同系統(tǒng)下分別添加以上代碼即可實(shí)現(xiàn)我們所需要的自定義左滑刪除按鈕往产,效果圖如下:

三被碗、設(shè)置左滑按鈕背景透明色(2024-02-21更新)

- (void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];
    // 設(shè)置刪除按鈕
    if (self.editingIndexPath){
        [self configSwipeButtons];
    }
}

// 設(shè)置左滑按鈕背景透明色
- (void)configSwipeButtons {
    if (@available(iOS 13.0, *)){
        // UITableView -> _UITableViewCellSwipeContainerView -> UISwipeActionPullView -> UISwipeActionStandardButton
        for (UIView *view1 in self.tableView.subviews){
            if ([view1 isKindOfClass:NSClassFromString(@"_UITableViewCellSwipeContainerView")]) {
                view1.backgroundColor = UIColor.clearColor;
                for (UIView *view2 in view1.subviews) {
                    if ([view2 isKindOfClass:NSClassFromString(@"UISwipeActionPullView")]) {
                        view2.backgroundColor = UIColor.clearColor;
                        for (UIView *view3 in view2.subviews) {
                            if ([view3 isKindOfClass:NSClassFromString(@"UISwipeActionStandardButton")]) {
                                view3.backgroundColor = UIColor.clearColor;
                                for (UIView *view4 in view3.subviews) {
                                    if ([view4 isKindOfClass:NSClassFromString(@"UIView")]) {
                                        view4.backgroundColor = UIColor.clearColor;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    } else if (@available(iOS 11.0, *)){
        // iOS 11層級 (Xcode 9編譯): UITableView -> UISwipeActionPullView
        for (UIView *view2 in self.tableView.subviews){
            if ([view2 isKindOfClass:NSClassFromString(@"UISwipeActionPullView")]){
                view2.backgroundColor = UIColor.clearColor;
                for (UIView *view3 in view2.subviews) {
                    if ([view3 isKindOfClass:NSClassFromString(@"UISwipeActionStandardButton")]) {
                        view3.backgroundColor = UIColor.clearColor;
                        for (UIView *view4 in view3.subviews) {
                            if ([view4 isKindOfClass:NSClassFromString(@"UIView")]) {
                                view4.backgroundColor = UIColor.clearColor;
                            }
                        }
                    }
                }
            }
        }
    }
}

以上是我總結(jié)整理的在不同系統(tǒng)下的自定義UITableView左滑刪除功能。

如有不足之處仿村,歡迎指正交流锐朴,Demo地址:左滑刪除

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市蔼囊,隨后出現(xiàn)的幾起案子焚志,更是在濱河造成了極大的恐慌,老刑警劉巖畏鼓,帶你破解...
    沈念sama閱讀 221,820評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件酱酬,死亡現(xiàn)場離奇詭異,居然都是意外死亡云矫,警方通過查閱死者的電腦和手機(jī)膳沽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來让禀,“玉大人挑社,你說我怎么就攤上這事《言担” “怎么了滔灶?”我有些...
    開封第一講書人閱讀 168,324評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長吼肥。 經(jīng)常有香客問我,道長麻车,這世上最難降的妖魔是什么缀皱? 我笑而不...
    開封第一講書人閱讀 59,714評論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮动猬,結(jié)果婚禮上啤斗,老公的妹妹穿的比我還像新娘。我一直安慰自己赁咙,他們只是感情好钮莲,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,724評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著彼水,像睡著了一般崔拥。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上凤覆,一...
    開封第一講書人閱讀 52,328評論 1 310
  • 那天链瓦,我揣著相機(jī)與錄音,去河邊找鬼。 笑死慈俯,一個胖子當(dāng)著我的面吹牛渤刃,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播贴膘,決...
    沈念sama閱讀 40,897評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼卖子,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了刑峡?” 一聲冷哼從身側(cè)響起洋闽,我...
    開封第一講書人閱讀 39,804評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎氛琢,沒想到半個月后喊递,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,345評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡阳似,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,431評論 3 340
  • 正文 我和宋清朗相戀三年骚勘,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片撮奏。...
    茶點(diǎn)故事閱讀 40,561評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡俏讹,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出畜吊,到底是詐尸還是另有隱情泽疆,我是刑警寧澤,帶...
    沈念sama閱讀 36,238評論 5 350
  • 正文 年R本政府宣布玲献,位于F島的核電站殉疼,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏捌年。R本人自食惡果不足惜瓢娜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,928評論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望礼预。 院中可真熱鬧眠砾,春花似錦、人聲如沸托酸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,417評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽励堡。三九已至谷丸,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間念秧,已是汗流浹背淤井。 一陣腳步聲響...
    開封第一講書人閱讀 33,528評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人币狠。 一個月前我還...
    沈念sama閱讀 48,983評論 3 376
  • 正文 我出身青樓游两,卻偏偏與公主長得像,于是被迫代替她去往敵國和親漩绵。 傳聞我的和親對象是個殘疾皇子贱案,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,573評論 2 359

推薦閱讀更多精彩內(nèi)容