ViewPager PageTransformer View getWidth и getMeasuredWidth равны 0
Я реализую компонент Карусель на основе следующего кода: https://github.com/bhaveshjabuvani-credencys/CarouselEffect/blob/master/app/src/main/java/com/carouseleffect/CarouselEffectTransformer.java
Основная проблема заключается в том, что при первом вызове преобразователя страниц и view.getLeft(), и view.getMeasuredWidth() равны 0, поэтому выполнение преобразователя страниц не даст правильных результатов.
Чтобы устранить эту проблему, в макете страницы я добавил следующий вид для каждой страницы, чтобы сохранить индекс / положение представления:
<View
android:id="@+id/pagePosition"
android:layout_width="0dp"
android:layout_height="0dp"
android:visibility="gone"/>
Затем, когда преобразованная страница вызывается, pagePosition используется для имитации правильных leftPadding и leftPosition для каждой страницы, и преобразователь страниц работает, как и ожидалось (первая страница центрируется, а следующая сокращается).
Модифицированный код ViewPager.PageTransformer выглядит следующим образом:
public class CarouselEffectTransformer implements ViewPager.PageTransformer {
private int maxTranslateOffsetX;
private int leftPadding;
private int rightPadding;
private ViewPager viewPager;
public CarouselEffectTransformer(Context context) {
this.maxTranslateOffsetX = dp2px(context, 180);
this.leftPadding = dp2px(context, 50);
this.rightPadding = dp2px(context, 50);
}
public void transformPage(View view, float position) {
if (viewPager == null) {
viewPager = (ViewPager) view.getParent();
}
//********** workaround start ****************
// get child
LinearLayout layout = (LinearLayout) view;
View pagePosition = layout.getChildAt(0);
int pageIndex = (int) pagePosition.getTag();
// check if view was measured
int offsetX = 0;
if (view.getLeft() == 0 && view.getMeasuredWidth() == 0) {
int pageWidth = viewPager.getMeasuredWidth() - leftPadding - rightPadding;
int leftInScreen = leftPadding + pageIndex * pageWidth;
int centerXInViewPager = leftInScreen + (viewPager.getMeasuredWidth() - leftPadding - rightPadding) / 2;
offsetX = centerXInViewPager - viewPager.getMeasuredWidth() / 2;
}
//********** workaround end ****************
else {
int leftInScreen = view.getLeft() - viewPager.getScrollX();
int centerXInViewPager = leftInScreen + view.getMeasuredWidth()/ 2;
offsetX = centerXInViewPager - viewPager.getMeasuredWidth() / 2;
}
float offsetRate = (float) offsetX * 0.38f / viewPager.getMeasuredWidth();
float scaleFactor = 1 - Math.abs(offsetRate);
if (scaleFactor > 0) {
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
view.setTranslationX(-maxTranslateOffsetX * offsetRate);
}
ViewCompat.setElevation(view, scaleFactor);
}
private int dp2px(Context context, float dipValue) {
float m = context.getResources().getDisplayMetrics().density;
return (int) (dipValue * m + 0.5f);
}
}
Некоторая информация о макете:
- ViewPager обновляется путем вызова notifyDataSetChanged() на своем адаптере, поэтому конфигурация хорошая.
- ViewPager находится внутри Relativelayout, и весь макет надувается фрагментом.
Однако я бы предпочел не делать этот обходной путь, поэтому вопрос:
- Почему при первом вызове представления getWidth() и getMeasuredWidth () равны 0?
- Может ли это быть конфликт между ViewPager и жизненным циклом фрагмента?