Глючный переход общего элемента между recyclerview и viewpager

Привет, я сделал приложение, в котором я использую переход общего элемента для некоторой анимации между просмотром recyclerview, который находится во фрагменте, и просмотром ползунка, который находится в действии. Теперь проблема заключается в том, что, когда я применяю переход общего элемента и нажимаю recyclerview, он на мгновение мигает, и начинается подробное действие, но без анимации, и когда я нажимаю кнопку «Назад», происходит анимация общего элемента, но это тоже очень глючит. Под глюком я подразумеваю, когда я нажимаю назад, белый фон карты выскакивает, а затем поверх него появляется изображение. Для этого я видел несколько руководств на YouTube, а также искал в Google и нашел несколько связанных Итак, вопрос, но я до сих пор не могу понять, где я ошибаюсь, потому что я дал одинаковое имя перехода для обоих изображений. поэтому, пожалуйста, если кто-то может мне помочь здесь. Спасибо

Вот мой код для 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>

Вьюхолдер

 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;
    }

person cooldev    schedule 28.05.2018    source источник
comment
Если переход ввода не работает, это означает, что представления не готовы, когда происходит анимация, поэтому вам, вероятно, нужно отложить переход, также я бы предложил setTransitionName в onBindViewholder, а не в onClick. Второй причиной может быть конфликт имени перехода, вы сказали, что дали одно и то же имя обоим, измените его, чтобы они были разными.   -  person Suleyman    schedule 28.05.2018
comment
когда я использовал отложенный ввод перехода по кнопке clcik, он как бы зависает, и я дал то же имя, потому что в большинстве видео на YouTube они дали одно и то же имя   -  person cooldev    schedule 28.05.2018


Ответы (1)


Я публикую это как ответ, потому что он немного длинный. Вы правы, если вы хотите поделиться, например, одним изображением между Фрагментом и Действием, вам нужно указать одно и то же имя в обоих. Но в вашем случае у вас есть RecyclerView, который может иметь много элементов, и поэтому вам нужно указать уникальное имя перехода для каждого из них. Хорошее место для этого — onBindViewHolder, где вы можете установить имя перехода, добавив позицию, например:

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

Таким образом, вы будете уверены, что каждое имя перехода уникально и, следовательно, нет конфликта. Как вы уже знаете, вам нужно установить имя перехода в обоих местах, поэтому вам нужно будет передать позицию в ваш ViewPager. Кроме того, ознакомьтесь с этой статьей, она может вам помочь.

person Suleyman    schedule 28.05.2018
comment
Хорошо, это имеет смысл, и, как вы можете видеть в моем классе viewholder, я передаю позицию макета recyclerview, и он отправляет правильное изображение, поэтому для анимации я должен внести какие-либо изменения - person cooldev; 28.05.2018
comment
@cooldev Я так не думаю, просто убедитесь, что вы добавили позицию к имени перехода в обоих местах. - person Suleyman; 28.05.2018
comment
Привет, я установил имя перехода в onBindviewholder, но оно такое же, я также добавил позицию, но без разницы - person cooldev; 28.05.2018
comment
@cooldev, ты добавил это в обоих местах? во Фрагменте и в Активности? - person Suleyman; 28.05.2018
comment
Я добавляю позицию во фрагменте и в подробностях. Я получаю это изображение через намерение и устанавливаю его для просмотра. - person cooldev; 28.05.2018
comment
@cooldev Проверьте, совпадают ли позиции в Activity и Fragment, чтобы вы установили одно и то же имя перехода. А также я думаю, вам нужно включить windowContentTransitions, это объясняется в этой ссылке что я предоставил. - person Suleyman; 28.05.2018
comment
Хорошо, но я уже установил для windowContentTransition значение true, вы также можете проверить мой вопрос, и я думаю, что получаю ту же позицию, потому что я также получаю то же изображение в viewpager - person cooldev; 28.05.2018
comment
и туториал mikescamell - самый первый туториал, который я увидел - person cooldev; 28.05.2018
comment
@cooldev Я не заметил styles.xml. Важно убедиться, что имя перехода такое же, используя журналы или что-то еще, потому что это обычно проблема. Честно говоря, я не слишком уверен в переходе Fragment to Activity, у вас будет гораздо меньше головной боли с Fragment to Fragment или Activity to Activity. Я могу предложить этот пост, это может помочь. - person Suleyman; 28.05.2018
comment
@cooldev Я так не думаю, но это может быть связано с тем, что представления не готовы, когда переход готов, поэтому вам нужно отложить (обычно в onCreate), а затем запустить его, когда представления будут готовы, это объясняется здесь - person Suleyman; 28.05.2018
comment
Я пытался использовать отсрочку, но когда я нажимаю recyclerview, он несколько зависает, я не знаю, почему - person cooldev; 28.05.2018
comment
@cooldev Но вы должны вызвать его в нужном месте, и после того, как вы его вызовете, чтобы начать переход, вы должны позвонить startPostponedEnterTransition(), механика этого объясняется в статье. Например, в моем случае у меня есть переход Fragment to Fragment, я откладываю его в onCreate и запускаю в методе обратного вызова Glide, в вашем случае это будет обозреватель дерева, как описано в статье. - person Suleyman; 28.05.2018