首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

didSelect执行不等待didDeSelect动画结束

didSelectdidDeselect 是 iOS 开发中用于处理用户交互的方法,通常与 UITableViewUICollectionView 的单元格选择相关。didSelect 在用户选择一个单元格时调用,而 didDeselect 在用户取消选择同一个单元格时调用。

基础概念

  • didSelect: 当用户点击某个单元格时触发。
  • didDeselect: 当用户再次点击同一个单元格或选择其他单元格时触发。

问题描述

didSelect 执行不等待 didDeselect 动画结束,这可能导致用户体验上的问题,比如动画被跳过或者视觉上的不一致。

原因分析

  1. 异步执行: didSelectdidDeselect 方法的执行是异步的,这意味着一旦 didSelect 被调用,它不会等待 didDeselect 的动画完成就继续执行后续代码。
  2. 默认行为: UITableViewUICollectionView 的默认行为是在选择或取消选择单元格时立即更新界面,而不是等待动画完成。

解决方案

为了确保 didSelectdidDeselect 动画结束后再执行,可以使用以下方法:

使用 UIView 的动画块

didSelect 方法中启动一个动画,并在动画完成的回调中执行需要的操作。

代码语言:txt
复制
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    let cell = tableView.cellForRow(at: indexPath)
    UIView.animate(withDuration: 0.3, animations: {
        // 执行选中动画
        cell?.backgroundColor = .blue
    }) { _ in
        // 动画完成后的操作
        print("didSelect animation completed")
    }
}

func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
    let cell = tableView.cellForRow(at: indexPath)
    UIView.animate(withDuration: 0.3, animations: {
        // 执行取消选中动画
        cell?.backgroundColor = .white
    }) { _ in
        // 动画完成后的操作
        print("didDeselect animation completed")
    }
}

使用 DispatchGroup

DispatchGroup 可以用来等待一组异步任务的完成。

代码语言:txt
复制
var dispatchGroup = DispatchGroup()

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    dispatchGroup.enter()
    let cell = tableView.cellForRow(at: indexPath)
    UIView.animate(withDuration: 0.3, animations: {
        // 执行选中动画
        cell?.backgroundColor = .blue
    }) { _ in
        dispatchGroup.leave()
    }
    
    dispatchGroup.notify(queue: .main) {
        // 动画完成后的操作
        print("didSelect animation completed")
    }
}

func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
    dispatchGroup.enter()
    let cell = tableView.cellForRow(at: indexPath)
    UIView.animate(withDuration: 0.3, animations: {
        // 执行取消选中动画
        cell?.backgroundColor = .white
    }) { _ in
        dispatchGroup.leave()
    }
    
    dispatchGroup.notify(queue: .main) {
        // 动画完成后的操作
        print("didDeselect animation completed")
    }
}

应用场景

这种方法适用于任何需要在动画完成后执行特定操作的场景,特别是在用户交互频繁的应用中,如列表选择、视图切换等。

通过上述方法,可以确保 didSelectdidDeselect 动画结束后再执行,从而提升用户体验和应用的一致性。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

iOS小经验:UITableView&UICollectionView设置单元格的默认选中状态

void)deselectRowAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated; 注意的是: 上述代码强制设置某单元格选中或者不选中那一刻...deselectItemAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated; 注意的是: 类似的,上述代码强制设置某单元格选中或者不选中那一刻...手动执行代理 上述两张方案的区别在于,设置选中状态完后,屏幕点击其它cell时,一个执行原cell的didDeselect方法,一个不执行。...相同点在于,手动设置选中的时候,都是不会执行didSelect方法的。...如果你真的想在改变选中状态的时候执行didSelect代理,那么可以手动执行: NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection

3.6K50
  • ScaleAnimation 缩放动画效果

    X坐标上的伸缩尺寸 float toX 动画结束时 X坐标上的伸缩尺寸 float fromY 动画起始时Y坐标上的伸缩尺寸 float toY 动画结束时Y坐标上的伸缩尺寸 int pivotXType...常用方法 */ //animation.setRepeatCount(int repeatCount);//设置重复次数 //animation.setFillAfter(boolean);//动画执行完后是否停留在执行完的状态...//animation.setStartOffset(long startOffset);//执行前的等待时间 start.setOnClickListener(new OnClickListener...(); } }); cancel.setOnClickListener(new OnClickListener() { public void onClick(View v) { /** 结束动画...本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

    1.4K20

    android scaleanimation动画,Android 动画之ScaleAnimation应用详解「建议收藏」

    , float pivotXValue, int pivotYType, float pivotYValue) 参数说明: float fromX 动画起始时 X坐标上的伸缩尺寸 float toX 动画结束时...X坐标上的伸缩尺寸 float fromY 动画起始时Y坐标上的伸缩尺寸 float toY 动画结束时Y坐标上的伸缩尺寸 int pivotXType 动画在X轴相对于物件位置类型 float pivotXValue...** 常用方法 */ //animation.setRepeatCount(int repeatCount);//设置重复次数 //animation.setFillAfter(boolean);//动画执行完后是否停留在执行完的状态...//animation.setStartOffset(long startOffset);//执行前的等待时间 start.setOnClickListener(new OnClickListener...本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

    38320

    彻底了解CSS3帧动画

    ease-in 函数,动画结束时的行为类似于 ease-out 函数; step-start 表示定时函数 steps(1, start),动画会立刻跳转到结束状态,并一直停留在结束状态直到动画结束;...例如下面的例子,a1,a3 动画的运动函数都将是 linear,而 a2 动画的运动函数是 step-start,a2 动画会立刻跳转到结束状态,并一直停留在结束状态直到动画结束。...现在有个需求,当 a1 执行完毕后再 再执行 a2 动画,a2 执行完毕后,执行 a3 动画。...,然后立刻跳转到结束状态 */ /* 因此第一张图片会等待大约 2.5s 时间,然后立即跳到第二张图片 */ /* 第二张图片也会等待大约 2.5s 时间,然后立即跳到第三张,以此类推...*/ /* 如果使用 start 方式,那么图片会先立即跳转,然后等待大约 2.5s,这样第一张图片就预览不上了 */ animation-timing-function: steps(

    98620

    HarmonyNext动画大全03-帧动画

    设置为0时不播放,设置为-1时无限次播放。说明: 设置为除-1外其他负数视为无效取值,无效取值动画默认播放1次。 begin number 动画插值起点。默认值:0。...ease 缓入缓出 动画开始和结束时速度较低 ease-in 缓入 动画开始时速度较低 ease-out 缓出 动画结束时速度较低 ease-in-out 缓入缓出 动画开始和结束时速度较低 fast-out-slow-in...none 正常 forwards 动画执行完毕时,画面停留在最后一帧 backwards 在延迟等待时间呢,画面跳转到第一帧,也就是 begin的值 both 等于同时设置了 forwards 和 backwards...direction 动画播放方向 如当重复执行4次动画时,动画的方向可以设置为 alternate A-B B-A A-B B-A iterations 动画执行次数,-1 为无限 begin...以相反的顺序播放动画 其他事件 onFrame 帧变化事件 onFinish 动画完成事件 onCancel 动画取消事件 onRepeat 动画重复执行时触发的事件

    6600

    【iOS开发】iOS 动画详解

    ,动画对layer都没有影响,动画结束后,layer会恢复到之前的状态 kCAFillModeForwards 当动画结束后,layer会一直保持着动画最后的状态 kCAFillModeBackwards...在动画开始前,只需要将动画加入了一个layer,layer便立即进入动画的初始状态并等待动画开始。...kCAFillModeBoth 这个其实就是上面两个的合成,动画加入后开始之前,layer便处于动画初始状态,动画结束后layer保持动画最后的状态 CAPropertyAnimation...keyTimes 指定到达每个关键帧的时间,与values对应,不设置就是平分。 timingFunctions 指定到达每一帧的速度,度values对应,可以不设置。...(动画可以是,基本动画、关键帧动画等其他动画)里面存放的动画可以不设置时间和重复次数,统一在CAAnimationGrop对象中设置。

    1.6K60

    CSS3 动画属性

    , 其实这些值都是一个中间值,如果要控制得更细一些,比如说要第一个时间段执行什么动作,第二个时间段执行什么动作(换到Flash制作动画中来说,就是第一帧要执行什么动作,第二帧执行什么动作), 这样用transition...如果没有加上,这个@keyframes是无效的,不起任何作用。因为@keyframes的单位只接受百分比值。...该属性的基本语法右所示: animation- delay:[,]* 换句话说, animation- delay 属性用于定义在浏览开始 执行动画之前等待的时间。...其默认值为none,表示动画将按预期进行和结束,在动画完成其最后一帧时,动画会反转到初始帧处。当其取值为forwards时,动画在结束后继续应用最后关键帧的位置。...简单地理解就是告诉动画在第一个关键帧上等待动画开始,或者在动画结束时停在最后一个关键帧上而不回到动画第一帧 上, 或者同时具有这两个效果。

    1.2K20

    animation动画实践

    这里有两种方法处理: 默认设置动画元素的opacity为0,再给lte9的重置为1 默认不处理,给modern的设置opacity为0,这里采用第二种,给高级浏览器动画元素设置opacity为0 缩放动画...就可以通过设置动画时间为2.4s,而关键帧的设置可以在50%的时候就到达运动结束的位置,也就是50%-100%这段时间其实就是空出来的间隔时间。...刚进入的时候是fade in动画,滚动进入第二层的时候是缩小动画,往回滚是放大动画 抓住最终结束状态,并设置为默认的css,这里最终结束状态有两个,一个是第一层的时候大小为原始大小,一个是第二层的时候大小为一半大小...见上面的in和out,注意正向和反向动画得把动画分别绑定在两个不同的class,而默认的class只负责设置为正向动画结束后停留的位置。...1s后执行,所以如果不特殊处理,就意味着在opacity:0.5;的时候,会持续1s等待。

    1.4K01

    在 View 上使用挂起函数 | 实战

    滑动结束 // 使用之前的方法展开该条目 recyclerView.expandItem(nextEpisodeToWatch.id) } 我们可以发现,这里需要很多等待异步操作完成的代码...为了在回调中使用断言判断是否执行了某些操作,您的测试必须包含所有的动画类型。本文并未真正涉及测试,但是使用协程可以让其更加简单。...我们的 awaitTransitionComplete() 方法如下定义: /** * 等待过渡动画结束,目的是让指定 [transitionId] 的动画执行完成 * * @param transitionId...需要等待执行完成的过渡动画集 * @param timeout 过渡动画执行的超时时间,默认 5s */ suspend fun MultiListenerMotionLayout.awaitTransitionComplete...如注释中所说,由于 SmoothScroller 真正开始执行的时间是动画的下一帧,所以我们等待一帧后再判断滑动状态。

    1.4K30

    Lodash 防抖和节流是如何实现的

    () // window.requestAnimationFrame() 告诉浏览器希望执行动画并请求浏览器在下一次重绘之前调用指定的函数来更新动画,差不多 16ms 执行一次 const useRAF...定时结束后无非两种情况,一种是执行传入函数 func,另一种就是不执行。对于第一种需要判断下是否需要执行传入函数 func,需要的时候执行最后一次回调。...// 定时器回调函数,表示定时结束后的操作 function timerExpired() { const time = Date.now() // 1、是否需要执行 // 执行事件结束后的那次回调...,接下来我们看一下执行传入函数 func 的逻辑,分为执行刚开始的那次回调 leadingEdge,执行结束后的那次回调 trailingEdge,正常执行 func 函数 invokeFunc,以及判断是否应该执行...invokeFunc(time) : result } trailingEdge 这里就是执行事件结束后的回调了,这里做的事情很简单,就是执行 func 函数,以及清空参数。

    1.9K40

    在 View 上使用挂起函数

    最常见的用法有以下几项: AnimatorListener 获取动画结束相关的事件 RecyclerView.OnScrollListener 获取滑动状态变更事件 View.OnLayoutChangeListener...其中 View.doOnPreDraw()方法是我最喜欢的一个,该方法对等待下一次绘制被执行进行了极大的精简。...等待 Animator 执行完成 我们再来看一个例子来加深理解,这次是等待 Animator 执行结束: suspend fun Animator.awaitEnd() = suspendCancellableCoroutine...{ // 如果协程仍处于活跃状态 if (endedSuccessfully) { // 并且动画正常结束...我们通过 onAnimationCancel() 回调来监听动画被取消的事件,通过调用协程的 cancel() 方法来取消挂起的协程。 这就是使用挂起函数等待方法执行来封装回调的基本使用了。

    2.4K30

    setTimeout和requestAnimationFrame

    任务队列 单线程就意味着,所有任务都要排队执行,前一个任务结束,才会执行后一个任务。如果一个任务需要执行,但此时JavaScript引擎正在执行其他任务,那么这个任务就需要放到一个队列中进行等待。...setTimeout setTimeout的运行机制:执行该语句时,设置一个定时器,定时时间置为多设置的延时,当计数结束后,将传入的函数加入任务队列,之后的执行就交给任务队列负责。...该程序执行后才设置定时器,再有250ms后,指定的代码才被添加到队列中等待执行。...如图所示,尽管在255ms处添加了定时器代码,但这时候还不能执行,因为onclick事件处理程序仍在运行。定时器代码最早能执行的时机是在300ms处,即onclick事件处理程序结束之后。...而且,它可以保证在下一次定时器代码执行之前,至少要等待指定的间隔,避免了连续的运行。

    1.8K20
    领券