OnPageChangeListener альфа-затенение
Есть много вопросов, касающихся плавного затухания в Android, но все они включают анимацию. Мой вопрос о кроссфейдинге с использованием OnPageChangeListener ViewPager.
У меня есть ViewPager, который может иметь неограниченное количество просмотров, но на практике использует около 6 или 7 просмотров. Не так много там происходит.
Каждый вид в ViewPager имеет фоновое растровое изображение, которое должно быть зафиксировано и затемнено с фоном следующего (или предыдущего) вида вместо прокрутки вместе с остальной частью вида.
Чтобы добиться этого, я отделил фоны и добавил их в ArrayList, а позже назначил их для ImageViews. Но так как я не хочу рисковать шансом, что моя активность закончится многочисленными ImageViews, я подумал о следующей структуре:
<FrameLayout
android:id="@+id/backgroundContainer"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/bottomImage"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:scaleType="center" />
<ImageView
android:id="@+id/middleImage"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:scaleType="center" />
<ImageView
android:id="@+id/topImage"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:scaleType="center" />
</FrameLayout>
Затем OnPageChangeListener
назначается ViewPager для назначения фонов для ImageViews.
@Override
public void onPageSelected(int position) {
MyLog.i(TAG, "PAGE SELECTED: " + position);
if(position == 0) {
_bottomBackground.setImageBitmap(null);
_topBackground.setImageBitmap(_backgroundStack.get(position+1));
} else if (position == NUM_ITEMS-1) {
_bottomBackground.setImageBitmap(_backgroundStack.get(position-1));
_topBackground.setImageBitmap(null);
} else {
_bottomBackground.setImageBitmap(_backgroundStack.get(position-1));
_topBackground.setImageBitmap(_backgroundStack.get(position+1));
}
_middleBackground.setImageBitmap(_backgroundStack.get(position));
// Make the top front background transparent
_topBackground.setAlpha(0f);
_currentBackgroundPosition = position;
}
Это прекрасно работает, если бы я хотел просто поменять местами фон. Я хочу, чтобы фоны переходили друг в друга, пока пользователь перелистывает ViewPager. У меня затухание для прокрутки вперед, но я не понимаю, почему затухание обратной прокрутки как-то не дает хорошего результата. Во время обратной прокрутки средний фон должен исчезнуть на нижнем фоне.
Боюсь, я что-то упустил. Я никогда не меняю альфа нижнего фона, но результаты журнала всегда показывают одно и то же значение для getAlpha()
что касается среднего фона.
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if(_currentBackgroundPosition == position) {
// scroll forward
_topBackground.setAlpha(positionOffset)
} else {
//scroll backward
_middleBackground.setAlpha(positionOffset);
}
MyLog.i(TAG, "Bottom BackgroundAlpha: " + _bottomBackground.getAlpha());
MyLog.i(TAG, "Middle BackgroundAlpha: " + _middleBackground.getAlpha());
MyLog.i(TAG, "Top BackgroundAlpha: " + _topBackground.getAlpha());
}
И ждать! Есть еще одна вещь, которую я действительно не могу понять, как исправить. Хотя прямая прокрутка исчезает. На заднем фоне очень короткое мерцание. Я предполагаю, что это происходит из-за того, как я настроил onPageSelected
метод.
Есть ли другой способ, как я могу создать / исправить это поведение?
1 ответ
ViewPager.PageTransformer
твой друг. Я собираюсь использовать другой подход к тому, что вы пытались, но это приводит к тому, что я понимаю, чтобы скрыть желаемый результат - смахивание влево / вправо смахивает контент, но затухает между двумя фоновыми изображениями, которые не перемещаются.
каждый Fragment
в ViewPager
будет иметь такой макет:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/image_view"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:scaleType="center" />
<LinearLayout
android:id="@+id/content_area"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- content goes here -->
</LinearLayout>
</FrameLayout>
И вы создадите PageTransformer
который управляет макетом в зависимости от положения, в котором он был проведен:
public class CustomPageTransformer implements ViewPager.PageTransformer {
public void transformPage(View view, float position) {
int pageWidth = view.getWidth();
View imageView = view.findViewById(R.id.image_view);
View contentView = view.findViewById(R.id.content_area);
if (position < -1) { // [-Infinity,-1)
// This page is way off-screen to the left
} else if (position <= 0) { // [-1,0]
// This page is moving out to the left
// Counteract the default swipe
view.setTranslationX(pageWidth * -position);
if (contentView != null) {
// But swipe the contentView
contentView.setTranslationX(pageWidth * position);
}
if (imageView != null) {
// Fade the image in
imageView.setAlpha(1 + position);
}
} else if (position <= 1) { // (0,1]
// This page is moving in from the right
// Counteract the default swipe
view.setTranslationX(pageWidth * -position);
if (contentView != null) {
// But swipe the contentView
contentView.setTranslationX(pageWidth * position);
}
if (imageView != null) {
// Fade the image out
imageView.setAlpha(1 - position);
}
} else { // (1,+Infinity]
// This page is way off-screen to the right
}
}
}
И, наконец, зацепить это PageTransformer
до вашего ViewPager
:
mViewPager.setPageTransformer(true, new CustomPageTransformer());
Я проверил его в существующем приложении, и оно работает хорошо, пока макеты фрагментов имеют прозрачный фон.