安卓带圆角CardView的共享元素转场出现闪烁卡顿问题求助
我之前也碰到过一模一样的问题,CardView的圆角和共享元素转场搭配时确实容易出现这类渲染冲突,给你几个经过验证的解决方案,你可以逐个尝试:
1. 让共享ImageView与CardView保持一致的圆角
转场的核心共享元素是你的AppCompatImageView(party_image),而非外层的CardView。这意味着CardView的圆角不会自动作用于内部的ImageView,转场时就会出现「直角图片→圆角CardView」的视觉跳变,看起来像是闪烁卡顿。
你可以通过两种方式解决:
方式一:给ImageView添加圆角背景并开启裁剪
在你的CardView布局里,给party_image添加以下属性:<android.support.v7.widget.AppCompatImageView android:id="@+id/party_image" android:layout_width="@dimen/_170sdp" android:layout_height="@dimen/_14" android:clipToOutline="true" android:background="@drawable/rounded_corner_14dp" />然后创建对应的圆角drawable文件
rounded_corner_14dp.xml:<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <corners android:radius="14dp" /> <!-- 和CardView的cardCornerRadius保持一致 --> <solid android:color="@color/White" /> </shape>方式二:用Glide加载时直接设置圆角变换
如果你用Glide加载图片,可以直接在加载时给图片添加圆角,这样图片本身就是圆角的,转场时不会有跳变:Glide.with(this) .load(imageUrl) .transform(new RoundedCorners(14)) // 数值对应CardView的圆角大小 .listener(new RequestListener<Drawable>() { @Override public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) { supportStartPostponedEnterTransition(); return false; } @Override public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) { supportStartPostponedEnterTransition(); return false; } }) .into(chat_image);
2. 调整硬件加速或自定义共享元素过渡
部分场景下,CardView的硬件加速会和共享元素转场的渲染逻辑冲突,导致闪烁。你可以尝试:
禁用CardView的硬件加速(谨慎使用,可能影响其他性能):
在CardView布局里添加:android:hardwareAccelerated="false"自定义共享元素过渡:
在FeedFragment的onCreateView方法中,设置自定义的ChangeBounds过渡,开启overlay模式:@TargetApi(Build.VERSION_CODES.LOLLIPOP) @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // ... 其他原有代码 ... if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { ChangeBounds transition = new ChangeBounds(); transition.setReparentWithOverlay(true); setSharedElementEnterTransition(transition); setSharedElementReturnTransition(transition); } return view; }
3. 确认过渡延迟逻辑的正确性
你已经用了supportPostponeEnterTransition()来等待图片加载完成后再启动转场,这部分思路是对的,但可以调整下代码顺序,确保ImageView的transitionName已经设置完成后再延迟过渡:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_chat); chat_image = (AppCompatImageView)findViewById(R.id.chat_image); Bundle extras = getIntent().getExtras(); Feed_Data_Provider feedItem = extras.getParcelable(FeedFragment.EXTRA_FEED_ITEM); int imageUrl = feedItem.getClub_image(); // 先设置transitionName if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { String imageTransitionName = extras.getString(FeedFragment.EXTRA_FEED_IMAGE_TRANSITION_NAME); if (imageTransitionName != null) { chat_image.setTransitionName(imageTransitionName); } } // 再延迟过渡 supportPostponeEnterTransition(); Glide.with(this) .load(imageUrl) .listener(new RequestListener<Drawable>() { @Override public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) { supportStartPostponedEnterTransition(); return false; } @Override public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) { supportStartPostponedEnterTransition(); return false; } }) .into(chat_image); }
建议先尝试第一种方案,这是最直接解决视觉跳变的方式,大部分情况下都能解决卡顿闪烁问题。
内容的提问来源于stack exchange,提问作者cooldev

