【问题标题】:Glitchy shared element transition between recyclerview and viewpagerrecyclerview 和 viewpager 之间的错误共享元素转换
【发布时间】:2018-05-28 06:14:09
【问题描述】:

您好,我制作了一个应用程序,我在其中使用共享元素转换在片段中的 recyclerview 和处于活动状态的滑块 viewpager 之间进行一些动画。 现在的问题是,当我应用共享元素转换并单击 recyclerview 时,它会闪烁片刻,详细活动开始但没有动画,当我按下返回按钮时,共享元素动画会发生,但这太小故障了。 我所说的故障是指当我按下cardview的白色背景时弹出然后图像出现在它上面。 为此,我在 youtube 上看到了一些教程,并在 google 上进行了搜索,发现了一些相关的So question,但仍然无法弄清楚我哪里出了问题,因为我为两个图像视图提供了相同的转换名称。 所以请如果有人可以在这里帮助我。 谢谢

这是我的 recyclerview 和 styles.xml 代码

styles.xml

<resources xmlns:tools="http://schemas.android.com/tools">

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <item name="android:windowContentTransitions" tools:targetApi="lollipop">true</item>
        <item name="android:windowAllowEnterTransitionOverlap" tools:targetApi="lollipop">true</item>
        <item name="android:windowAllowReturnTransitionOverlap" tools:targetApi="lollipop">true</item>
        <item name="android:windowSharedElementEnterTransition" tools:targetApi="lollipop">@android:transition/move</item>
        <item name="android:windowSharedElementExitTransition" tools:targetApi="lollipop">@android:transition/move</item>
    </style>

</resources>

ViewHolder

 public class VH extends RecyclerView.ViewHolder implements View.OnClickListener{
        ImageView iv;
        TextView tv;
        HWRatioContainer ivc;
        Context context;
        int[] images;

        private AtomicBoolean enterTransitionStarted;
        public static final String EXTRA_TRANSITION_IMAGE = "image";

        CustomButton top_recycler_button;
        public VH(View itemView,Context context,int[] images) {
            super(itemView);
            iv = (ImageView) itemView.findViewById(R.id.iv);
            this.context = context;
            this.images = images;

            this.enterTransitionStarted = new AtomicBoolean();
            top_recycler_button = (CustomButton)itemView.findViewById(R.id.top_recycler_button);
            itemView.setOnClickListener(this);
            //tv = (TextView) itemView.findViewById(R.id.tv);
            ///ivc = (HWRatioContainer) itemView.findViewById(R.id.ivc);
           /*ivc.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                @Override
                public void onGlobalLayout() {
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                        ivc.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                    } else {
                        ivc.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                    }
                    ivc.setTranslationX(ivc.getWidth() >> 4);
                }
            });*/

        }

        @SuppressLint("RestrictedApi")
        @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
        @Override
        public void onClick(View view) {
            Intent intent = new Intent(context,DetailsActivity.class);
            intent.putExtra("slider_image",images[getAdapterPosition()]);
            iv.setTransitionName(context.getString(R.string.first_page_transition));
            ActivityOptionsCompat compat = ActivityOptionsCompat.makeSceneTransitionAnimation((MainActivity)context,iv,ViewCompat.getTransitionName(iv));
            context.startActivity(intent,compat.toBundle());
        }
    }

以及处于活动状态的viewpager适配器的代码

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    @NonNull
    @Override
    public Object instantiateItem(@NonNull ViewGroup container, int position) {
        layoutInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View view = layoutInflater.inflate(R.layout.custom_dots_layout,null);
        imageView = (ImageView)view.findViewById(R.id.detail_viewpager_image);
        //Intent intent  = new Intent();
        imageView.setImageResource(getImage());

        if(Build.VERSION.SDK_INT>Build.VERSION_CODES.LOLLIPOP){
            imageView.setTransitionName(context.getString(R.string.first_page_transition));

        }
        ViewPager viewPager1 = (ViewPager)container;
        viewPager1.addView(view,0);
        return view;
    }

【问题讨论】:

  • 如果进入转场不起作用,说明动画发生时视图还没有准备好,所以你可能需要推迟转场,我也建议@987654326中的setTransitionName @ 而不是onClick。第二个原因可能是转换名称冲突,你说你给两个都取了相同的名字,改变它,使它们不同。
  • 当我在按钮 clcik 上使用推迟进入转换时,它有点冻结,我给了相同的名字,因为在大多数 youtube tuts 中他们给了相同的名字

标签: java android user-interface animation shared-element-transition


【解决方案1】:

我将其发布为答案,因为它有点长。没错,例如,如果您想在 FragmentActivity 之间共享一张图片,则需要在两者中提供相同的名称。但在您的情况下,您有一个 RecyclerView 可以有许多元素,因此您需要为每个元素提供一个唯一的转换名称。一个好地方是onBindViewHolder,您可以在其中通过附加位置来设置过渡名称,例如:

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
    imageView.setTransitionName("YourTransitionName" + position);
    // other code
}

这样您就可以确定每个转换名称都是唯一的,因此不会发生冲突。正如您已经知道的那样,您需要在两个地方设置转换名称,因此您需要将位置传递给您的ViewPager。另外,请查看 this 文章,它可能会有所帮助。

【讨论】:

  • 好吧,这是有道理的,正如您在我的视图类中看到的那样,我正在传递 recyclerview 的布局位置,它会发送正确的图像,因此我应该对动画进行任何更改
  • @cooldev 我不这么认为,只要确保在两个地方都将位置附加到过渡名称。
  • 嗨,我在 onBindviewholder 中设置了 transitionname 仍然是一样的,我也附加了位置,但没有区别
  • @cooldev 你在这两个地方都附加了它?在 Fragment 和 Activity 中也是如此?
  • 我在片段和详细活动中附加位置,我通过意图获取该图像并将其设置为 viewpager
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-12
相关资源
最近更新 更多