Android RecyclerView点击启动新Activity时无法显示水波纹效果
解决RecyclerView行点击启动Activity时水波纹不显示的问题
这个问题我之前也碰到过,核心原因就是Activity启动得太快,直接打断了水波纹的绘制和播放流程。下面给你几个实用的解决方案,按推荐程度排序:
方案三:改用Adapter内设置Item点击事件(最推荐)
其实你当前用RecyclerView.OnItemTouchListener实现点击监听的方式,绕开了系统原生的View点击事件处理逻辑。如果直接在Adapter的onBindViewHolder里给ItemView设置点击事件,系统会自动处理水波纹动画和点击回调的时序,完全不会出现动画被打断的情况。
修改你的Adapter代码:
@Override public void onBindViewHolder(@NonNull MyViewHolder holder, int position) { // 先绑定你的数据逻辑... // 直接给ItemView设置点击监听 holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 这里启动Activity,水波纹会完整播放 Intent intent = new Intent(v.getContext(), TargetActivity.class); v.getContext().startActivity(intent); } }); // 长按事件也可以在这里设置 holder.itemView.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { // 你的长按逻辑 return true; } }); }
之后就可以移除你之前写的RecyclerTouchListener了,这种方式完全贴合Android的设计规范,代码简洁还不容易出问题。
方案一:延迟启动Activity(简单直接)
如果一定要保留OnItemTouchListener的实现,最简单的办法就是给Activity启动加个小延迟,刚好等水波纹动画播放完成。水波纹的默认时长大概在200-300ms左右,设置300ms延迟基本能覆盖所有情况。
修改你的点击回调逻辑:
// 初始化RecyclerTouchListener时的回调 RecyclerClickListener clickListener = new RecyclerClickListener() { @Override public void onClick(View view, int position) { // 延迟300ms启动Activity view.postDelayed(new Runnable() { @Override public void run() { Intent intent = new Intent(MainActivity.this, TargetActivity.class); startActivity(intent); } }, 300); } @Override public void onLongClick(View view, int position) { // 长按逻辑保持不变 } };
这个方法的优点是代码改动极小,缺点是硬编码了延迟时间,如果用户修改了系统动画时长,可能会出现时序不匹配的情况,但日常使用完全足够。
方案二:监听水波纹动画结束(精准匹配)
如果想要完美匹配水波纹的动画时长,可以直接监听RippleDrawable的动画结束事件,等动画真正完成后再启动Activity。
修改点击回调逻辑:
RecyclerClickListener clickListener = new RecyclerClickListener() { @Override public void onClick(View view, int position) { Drawable background = view.getBackground(); // 只针对API 21及以上的RippleDrawable处理 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && background instanceof RippleDrawable) { RippleDrawable rippleDrawable = (RippleDrawable) background; // 先设置Drawable的Callback,否则动画监听可能不生效 rippleDrawable.setCallback(new Drawable.Callback() { @Override public void invalidateDrawable(@NonNull Drawable who) { view.invalidate(); } @Override public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) { view.scheduleDrawable(who, what, when); } @Override public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) { view.unscheduleDrawable(who, what); } }); // 添加动画结束监听 rippleDrawable.setOnAnimationEndListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(@NonNull Animator animation) {} @Override public void onAnimationEnd(@NonNull Animator animation) { // 动画结束后启动Activity Intent intent = new Intent(MainActivity.this, TargetActivity.class); startActivity(intent); // 记得移除监听器,避免内存泄漏 rippleDrawable.setOnAnimationEndListener(null); } @Override public void onAnimationCancel(@NonNull Animator animation) {} @Override public void onAnimationRepeat(@NonNull Animator animation) {} }); } else { // 兼容低版本或非RippleDrawable的情况,直接启动 Intent intent = new Intent(MainActivity.this, TargetActivity.class); startActivity(intent); } } @Override public void onLongClick(View view, int position) { // 长按逻辑不变 } };
这个方法能精准匹配动画时长,但代码相对复杂,还需要处理版本兼容,适合对交互体验要求极高的场景。
内容的提问来源于stack exchange,提问作者Dusan
相关产品推荐
相关产品推荐

