1

В моем планшете планшета планшета есть сетка (RecyclerView) слева, содержащая сетку изображений, а вид сведений справа который отображает меньшую версию текущего выбранного изображения сетки, а также дополнительные текстовые представления, описывающие это изображение. Я пытаюсь выяснить, как обеспечить переход анимации с общим элементом, который будет скользить и масштабировать любое изображение с щелчком (в левом боковом фрагменте сетки) до его соответствующего местоположения в фрагменте представления деталей. Моему приложению нужен только переход «войти», потому что я не хочу, чтобы каждый выбор изображения записывался в задний стек.Как анимировать общий элемент ImageView из фрагмента ListView для фрагмента детализированного просмотра в макете макета/детали макета

Я попытался использовать стандартные общие вызовы поддержки элемент в моем OnItemClick(View view) обработчика следующим образом:

DetailFragment detailFragment = detailFragment.newInstance(mFragmentId); 

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 
    movieDetailFragment.setSharedElementEnterTransition(
      TransitionInflater.from(this).inflateTransition(
        R.transition.change_image_transform)); 
      view.setTransitionName(getString(
        R.string.image_transition_name)); 
} 

getSupportFragmentManager().beginTransaction() 
     .replace(R.id.detail_container, 
       detailFragment, 
       DETAIL_FRAGMENT_TAG) 
     .addSharedElement(view, getString(R.string.image_transition_name)) 
     .commit(); 

«Вид» переменная является ImageView, что пользователь нажал на вид сетки. Метод моего фрагмента подробно onCreate() также содержит запись

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 
    mImageView.setTransitionName(
      getString(R.string.image_transition_name)); 
} 

Я также использую следующий change_image_transform.xml перехода набор:

<transitionSet> 
    <changeImageTransform/> 
    <changeBounds/> 
</transitionSet> 

вместе с

<item name="android:windowContentTransitions">true</item> 
<item name="android:windowActivityTransitions">true</item> 
<item name="android:windowSharedElementEnterTransition"> 
    @transition/change_image_transform</item> 
<item name="android:windowSharedElementExitTransition"> 
    @transition/change_image_transform</item> 

Все эти настройки работают правильно для режима одиночной панели. Когда пользователь нажимает на изображение в активности вида сетки, фрагмент детали (в новом действии) заменяет вид сетки, и анимация отлично работает для сценариев ввода и возврата.

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

В моем поиске не было четкого ответа на эту проблему, кроме одной неопределенной рекомендации использовать простую пользовательскую анимацию. Я попробовал простой TranslateAnimation (без масштабирования) точно так же, как тест, но у этого были две проблемы: он не позволил бы изображению пересечь границу фрагмента сетки и имел нежелательный побочный эффект от фактического «перемещения» изображения временное пустое место - это мое представление сетки во время анимации). В конечном счете, желаемый эффект заключается в том, чтобы увидеть слайд и масштаб изображения от источника до места назначения, не вызывая стирание исходного изображения.

Любые предложения или рекомендации были бы весьма признательны.

ответ

1

Я решил, что самый простой способ получить общий переход элемента для работы между двумя фрагментами в режиме с двумя панелями - просто сделать анимацию самостоятельно. В моем решении я не заменяю фрагмент детали деталями выбранного изображения сетки; вместо этого я просто обновляю элементы управления компоновкой новыми данными из выбранного элемента сетки. Чтобы предотвратить изменение размера родительского линейного макета, когда целевой ImageView временно удаляется из детального представления и помещается в оверлей (для анимации), родитель ImageView вынужден иметь размер содержащегося дочернего элемента, а затем восстанавливается до его первоначальной ширины и высоты макета после анимация. Вот функция, которая выполняет анимацию в ответ на событие щелчка элемента сетки:

/** 
* Sets up and runs an animation that translates and scales the 
* selected poster in the grid view to the poster ImageView in the 
* detail fragment. 
* @param srcView 
* @param destView 
*/ 
private void runAnimation(final ImageView srcView, final ImageView destView) { 
    final ViewGroup destParentView = (ViewGroup)destView.getParent(); 

    // Set the destination image view's parent (FrameLayout) to 
    // keep the width and height of image view that will be 
    // temporarily re-parented during the animation. This will 
    // ensure that the enclosing LinearLayout will remain fixed 
    // in appearance during the animation. 
    final int parentLayoutWidth = destParentView.getLayoutParams().width; 
    final int parentLayoutHeight = destParentView.getLayoutParams().height; 
    destParentView.getLayoutParams().width = destParentView.getMeasuredWidth(); 
    destParentView.getLayoutParams().height = destParentView.getMeasuredHeight(); 

    // Scale the destination image to the size of 
    // the source image. The animation will restore 
    // the destination image scale when it is run. 
    // Note that the scale needs to be set before any 
    // translation so that the translation takes into 
    // account the change in scale. 
    float scaleX = (float)destView.getMeasuredWidth() 
      /(float)srcView.getMeasuredWidth(); 
    float scaleY = (float) destView.getMeasuredHeight() 
      /(float) srcView.getMeasuredHeight(); 

    destView.setScaleX(1f/scaleX); 
    destView.setScaleY(1f/scaleY); 

    // Now set translation on scaled image so that the 
    // destination image begins at the same position as 
    // the source image. The destination image translation 
    // will be returned to 0 during the animation. 
    int[] srcLocation = {0, 0}; 
    int[] dstLocation = {0, 0}; 
    srcView.getLocationOnScreen(srcLocation); 
    destView.getLocationOnScreen(dstLocation); 
    destView.setTranslationX(srcLocation[0] - dstLocation[0]); 
    destView.setTranslationY(srcLocation[1] - dstLocation[1]); 

    // The overlay must be created from any view whose bounds 
    // encompasses both the source and destination views. 
    final ViewGroup rootView = 
       (ViewGroup)MainActivity.this.findViewById(R.id.main_content); 
    rootView.getOverlay().add(destView); 

    // Run animation and when it completes, move the destination 
    // view from the overlay back to it's original parent. Also, 
    // restore the parent's layout params which were changed to 
    // act as a placeholder with the image was being animated. 
    destView.animate() 
      .scaleX(1f) 
      .scaleY(1f) 
      .translationX(0) 
      .translationY(0) 
      .setInterpolator(new DecelerateInterpolator(2)) 
      .setDuration(500) 
      .withEndAction(new Runnable() { 
       @Override 
       public void run() { 
        rootView.getOverlay().remove(destView); 
        destParentView.getLayoutParams().width = parentLayoutWidth; 
        destParentView.getLayoutParams().height = parentLayoutHeight; 
        destParentView.addView(destView); 
       } 
      }); 
}