Фрагменты ViewPager - переходы с общим элементом
Приложение, которое я разрабатываю, отображает сетку изображений. Когда вы нажимаете изображение, оно переходит в представление деталей. В представлении сведений содержится ViewPager, который позволяет прокручивать каждое изображение в сетке. Это делается путем передачи списков путей (содержащих каждое изображение в сетке) вместе со смещением изображения, которое было нажато, чтобы ViewPager можно было установить для отображения этой страницы вначале.
Какой лучший способ иметь общий переход элемента внутри фрагмента текущей страницы смещения в ViewPager? Изображение сетки (RecyclerView) должно отображаться на полном экране в текущей странице. Я видел возможность отложить и возобновить переходы активности, поэтому приложение будет ждать, пока отобразит переход общего элемента, пока изображение не будет загружено с диска. Но я хочу, чтобы он мог оживить правильную страницу на пейджере представления, а также выйти на любую текущую страницу, когда пользователь вернется (поскольку вы можете провести между страницами). Если теперь вы перейдете на другую страницу, начальная страница - это то, что оживляет обратно в сетку.
В настоящее время я назначаю каждое изображение в Фрагментах пейджера представления с именем перехода в формате "image_ [index]". Когда я начинаю работу с деталями, я использую одно имя перехода с индексом, являющимся смещением.
В связи с этим мне также было интересно, как заставить рябь работать с длинными нажатиями. Когда вы меняете активированное состояние просмотра, оно, похоже, отменяет пульсацию. Мне нужен эффект, похожий на Gmail, где пульсация начинается снова и быстро заканчивается после того, как длинное нажатие завершено и запускает активированное состояние.
Ответы
Ответ 1
Из того, что я могу сказать (и исправьте меня, если я ошибаюсь), то, что вы пытаетесь достичь, в основном примерно так: предположим, что у вас есть MainActivity
, a DetailsActivity
и произвольный набор изображений, MainActivity
отображает набор изображений в сетке, а DetailsActivity
отображает один и тот же набор изображений в горизонтальном ViewPager
. Когда пользователь выбирает изображение в MainActivity
, это изображение должно перейти от своего положения в сетке к правильной странице во втором действии ViewPager
.
Проблема, которую мы хотим решить, - "что, если пользователь переключает страницы внутри DetailsActivity
"? Если это произойдет, мы хотим изменить общий образ, который будет использоваться во время обратного перехода. По умолчанию структура перехода к действию будет использовать общий элемент, который использовался во время перехода ввода... но страница пейджера просмотра изменилась, поэтому, очевидно, мы хотим как-то переопределить это поведение. Для этого нам нужно установить SharedElementCallback
в ваших методах MainActivity
и DetailsActivity
onCreate()
и переопределить метод onMapSharedElements()
следующим образом:
private final SharedElementCallback mCallback = new SharedElementCallback() {
@Override
public void onMapSharedElements(List<String> names, Map<String, View> sharedElements) {
if (mCurrentImagePosition != mOriginalImagePosition) {
View sharedView = getImageAtPosition(mCurrentImagePosition);
names.clear();
sharedElements.clear();
names.add(sharedView.getTransitionName());
sharedElements.put(sharedView.getTransitionName(), sharedView);
}
}
/**
* Returns the image of interest to be used as the entering/returning
* shared element during the activity transition.
*/
private View getImageAtPosition(int position) {
// ...
}
};
Для более полного решения я создал образец проекта на GitHub, который достигнет этого эффекта (слишком много кода для сообщение в одном ответе StackOverflow).
Ответ 2
Я предполагаю, что вы используете Fragment Transitions и что вы не оживляете действия. Это возможно в обоих переходах активности и переходах фрагментов, но конкретный код немного отличается. Однако отсрочка недоступна для переходов фрагментов.
В addSharedElement используется второй параметр. Если вы знаете конкретное имя в целевом фрагменте, когда вы его вызываете, вы можете просто выбрать имя в фрагменте детали для использования. Если вы этого не сделаете, вы можете выбрать любое имя и переназначить его с помощью SharedElementCallback, установленного на фрагменте.
fragment.setEnterSharedElementCallback(new SharedElementCallback() {
@Override
public void onMapSharedElements(List<String> names, Map<String, View> sharedElements) {
sharedElements.put("detailView", mTargetDetailView);
}
});
Если это не соответствует обратному пути, тот же вызов выполняется для его переназначения. Вероятно, это будет как в вызывающем фрагменте, так и в вызываемом фрагменте - на вызывающем фрагменте вы используете setExitSharedElementCallback. Я ожидаю, что это будет в вашем приложении.
Аналогично, в Activity Transitions вы устанавливаете один и тот же SharedElementCallback и используете одно и то же сопоставление, но вы делаете это вместо действия.