프로그래밍 방식으로 혁신 할 때 ViewPager 애니메이션 기간 변경
슬라이드를 변경하고 있습니다.
viewPager.setCurrentItem(index++, true);
그러나 그것은 빠르게 변합니다. 애니메이션 속도를 수동으로 설정하는 방법이 있습니까?
나는 스스로를 믿습니다. 아직 테스트하지 나는 않은하지만 해야 우리 일을하거나 최소한의 수정이 필요합니다. Galaxy Nexus JB 4.2.1에서 테스트되었습니다. ViewPagerCustomDuration
대신 XML에서 를 사용 ViewPager
하며 다음을 수행 할 수 있습니다.
ViewPagerCustomDuration vp = (ViewPagerCustomDuration) findViewById(R.id.myPager);
vp.setScrollDurationFactor(2); // make the animation twice as slow
ViewPagerCustomDuration.java
:
import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.animation.Interpolator;
import java.lang.reflect.Field;
public class ViewPagerCustomDuration extends ViewPager {
public ViewPagerCustomDuration(Context context) {
super(context);
postInitViewPager();
}
public ViewPagerCustomDuration(Context context, AttributeSet attrs) {
super(context, attrs);
postInitViewPager();
}
private ScrollerCustomDuration mScroller = null;
/**
* Override the Scroller instance with our own class so we can change the
* duration
*/
private void postInitViewPager() {
try {
Field scroller = ViewPager.class.getDeclaredField("mScroller");
scroller.setAccessible(true);
Field interpolator = ViewPager.class.getDeclaredField("sInterpolator");
interpolator.setAccessible(true);
mScroller = new ScrollerCustomDuration(getContext(),
(Interpolator) interpolator.get(null));
scroller.set(this, mScroller);
} catch (Exception e) {
}
}
/**
* Set the factor by which the duration will change
*/
public void setScrollDurationFactor(double scrollFactor) {
mScroller.setScrollDurationFactor(scrollFactor);
}
}
ScrollerCustomDuration.java
:
import android.annotation.SuppressLint;
import android.content.Context;
import android.view.animation.Interpolator;
import android.widget.Scroller;
public class ScrollerCustomDuration extends Scroller {
private double mScrollFactor = 1;
public ScrollerCustomDuration(Context context) {
super(context);
}
public ScrollerCustomDuration(Context context, Interpolator interpolator) {
super(context, interpolator);
}
@SuppressLint("NewApi")
public ScrollerCustomDuration(Context context, Interpolator interpolator, boolean flywheel) {
super(context, interpolator, flywheel);
}
/**
* Set the factor by which the duration will change
*/
public void setScrollDurationFactor(double scrollFactor) {
mScrollFactor = scrollFactor;
}
@Override
public void startScroll(int startX, int startY, int dx, int dy, int duration) {
super.startScroll(startX, startY, dx, dy, (int) (duration * mScrollFactor));
}
}
이것이 누군가를 돕기를 바랍니다!
@ df778899의 답변 과 Android ValueAnimator API를 기반으로 더 나은 솔루션을 찾았습니다 . 반사없이 잘 작동하며 매우 유연합니다. 또한 사용자 정의 ViewPager를 작성하여 android.support.v4.view 패키지에 넣을 필요가 없습니다. 다음은 예입니다.
private void animatePagerTransition(final boolean forward) {
ValueAnimator animator = ValueAnimator.ofInt(0, viewPager.getWidth());
animator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
viewPager.endFakeDrag();
}
@Override
public void onAnimationCancel(Animator animation) {
viewPager.endFakeDrag();
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
animator.setInterpolator(new AccelerateInterpolator());
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
private int oldDragPosition = 0;
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int dragPosition = (Integer) animation.getAnimatedValue();
int dragOffset = dragPosition - oldDragPosition;
oldDragPosition = dragPosition;
viewPager.fakeDragBy(dragOffset * (forward ? -1 : 1));
}
});
animator.setDuration(AppConstants.PAGER_TRANSITION_DURATION_MS);
if (viewPager.beginFakeDrag()) {
animator.start();
}
}
최신 정보 :
이 솔루션을 사용하여 한 번에 여러 페이지를 스 와이프 할 수 있는지 확인했습니다 (예 : 첫 페이지가 마지막 페이지 다음에 표시되어야하는 경우). 지정된 페이지 수를 처리하기 위해 약간 수정 된 코드입니다.
private int oldDragPosition = 0;
private void animatePagerTransition(final boolean forward, int pageCount) {
// if previous animation have not finished we can get exception
if (pagerAnimation != null) {
pagerAnimation.cancel();
}
pagerAnimation = getPagerTransitionAnimation(forward, pageCount);
if (viewPager.beginFakeDrag()) { // checking that started drag correctly
pagerAnimation.start();
}
}
private Animator getPagerTransitionAnimation(final boolean forward, int pageCount) {
ValueAnimator animator = ValueAnimator.ofInt(0, viewPager.getWidth() - 1);
animator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
viewPager.endFakeDrag();
}
@Override
public void onAnimationCancel(Animator animation) {
viewPager.endFakeDrag();
}
@Override
public void onAnimationRepeat(Animator animation) {
viewPager.endFakeDrag();
oldDragPosition = 0;
viewPager.beginFakeDrag();
}
});
animator.setInterpolator(new AccelerateInterpolator());
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int dragPosition = (Integer) animation.getAnimatedValue();
int dragOffset = dragPosition - oldDragPosition;
oldDragPosition = dragPosition;
viewPager.fakeDragBy(dragOffset * (forward ? -1 : 1));
}
});
animator.setDuration(AppConstants.PAGER_TRANSITION_DURATION_MS / pageCount); // remove divider if you want to make each transition have the same speed as single page transition
animator.setRepeatCount(pageCount);
return animator;
}
public class PresentationViewPager extends ViewPager {
public static final int DEFAULT_SCROLL_DURATION = 250;
public static final int PRESENTATION_MODE_SCROLL_DURATION = 1000;
public PresentationViewPager (Context context) {
super(context);
}
public PresentationViewPager (Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setDurationScroll(int millis) {
try {
Class<?> viewpager = ViewPager.class;
Field scroller = viewpager.getDeclaredField("mScroller");
scroller.setAccessible(true);
scroller.set(this, new OwnScroller(getContext(), millis));
} catch (Exception e) {
e.printStackTrace();
}
}
public class OwnScroller extends Scroller {
private int durationScrollMillis = 1;
public OwnScroller(Context context, int durationScroll) {
super(context, new DecelerateInterpolator());
this.durationScrollMillis = durationScroll;
}
@Override
public void startScroll(int startX, int startY, int dx, int dy, int duration) {
super.startScroll(startX, startY, dx, dy, durationScrollMillis);
}
}
}
더 나은 솔루션은 지원 패키지에서 클래스를 만들어 개인 필드에 액세스하는 것입니다. 편집 은 클래스에 MAX_SETTLE_DURATION
의해 작성된 600ms에 바인딩 ViewPager
됩니다.
package android.support.v4.view;
import android.content.Context;
import android.util.AttributeSet;
public class SlowViewPager extends ViewPager {
// The speed of the scroll used by setCurrentItem()
private static final int VELOCITY = 200;
public SlowViewPager(Context context) {
super(context);
}
public SlowViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
void setCurrentItemInternal(int item, boolean smoothScroll, boolean always) {
setCurrentItemInternal(item, smoothScroll, always, VELOCITY);
}
}
XML을 사용하여 접근 할 수 있습니다.
다음은 Librera Reader 에서 사용되는 코드입니다.
public class MyViewPager extends ViewPager {
public MyViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
initMyScroller();
}
private void initMyScroller() {
try {
Class<?> viewpager = ViewPager.class;
Field scroller = viewpager.getDeclaredField("mScroller");
scroller.setAccessible(true);
scroller.set(this, new MyScroller(getContext())); // my liner scroller
Field mFlingDistance = viewpager.getDeclaredField("mFlingDistance");
mFlingDistance.setAccessible(true);
mFlingDistance.set(this, Dips.DP_10);//10 dip
Field mMinimumVelocity = viewpager.getDeclaredField("mMinimumVelocity");
mMinimumVelocity.setAccessible(true);
mMinimumVelocity.set(this, 0); //0 velocity
} catch (Exception e) {
LOG.e(e);
}
}
public class MyScroller extends Scroller {
public MyScroller(Context context) {
super(context, new LinearInterpolator()); // my LinearInterpolator
}
@Override
public void startScroll(int startX, int startY, int dx, int dy, int duration) {
super.startScroll(startX, startY, dx, dy, 175);//175 duration
}
}
}
하루 종일 낭비한 후 offscreenPageLimit을 총 no로 설정 한 솔루션을 찾았습니다. 페이지의.
일정한 길이의 ViewPager 스크롤을 부드럽게 유지하기 위해 setOffScreenLimit (page.length)는 모든 뷰를 메모리에 유지합니다. 그러나 이것은 View.requestLayout 함수 호출을 포함하는 모든 애니메이션 (예 : 여백 또는 경계 변경과 관련된 모든 애니메이션)에 문제가됩니다. 메모리에있는 모든 뷰가 무효화되기 때문에 (Romain Guy에 따라) 정말 느려집니다. 그래서 매끄럽게 만들기 위해 몇 가지 다른 방법을 시도했지만 requestLayout 및 기타 무효화 메서드를 재정의하면 다른 많은 문제가 발생합니다.
좋은 타협은 화면 밖 제한을 동적으로 수정하여 페이지 사이의 대부분의 스크롤이 매우 부드러워지면서 사용자가 뷰를 제거하여 모든 페이지 내 애니메이션이 매끄럽게되도록하는 것입니다. 이것은 메모리에서 다른 뷰를 만들어야하는 뷰가 1 개 또는 2 개뿐 일 때 정말 잘 작동합니다.
*** feset limit u를 설정하면 모든 조각을 동시에로드하므로 솔루션이 작동하지 않을 때 사용합니다.
'ProgramingTip' 카테고리의 다른 글
jQuery $ (document) .ready () 두 번 실행 (0) | 2020.11.07 |
---|---|
Rails ActiveRecord는 여러 쿼리없이 "where"절을 어떻게 연결합니까? (0) | 2020.11.07 |
MySQL SELECT DISTINCT 여러 열 (0) | 2020.11.07 |
Express에서 app.use ()와 router.use ()의 차이점 (0) | 2020.11.07 |
하이라이트 색상 변경 (0) | 2020.11.07 |