it-swarm.com.de

Ändern Sie die Dauer der ViewPager-Animation, wenn Sie programmgesteuert gleiten

Ich wechsle mit 

viewPager.setCurrentItem(index++, true);

Aber es wird schnell. Gibt es eine Möglichkeit, die Animationsgeschwindigkeit manuell einzustellen?

Gesucht und nur gefunden, dass jemand überall dasselbe fragt (außer StackOverflow, vielleicht habe ich hier Glück :)), ohne Antworten.

Mögen:

https://groups.google.com/group/Android-developers/browse_thread/thread/a13405c0b5833893?fwc=1

Danke im Voraus.

64
Ixx

Ich wollte es selbst machen und habe eine Lösung gefunden (allerdings mit Reflektion). Ich habe es noch nicht getestet, aber es sollte funktionieren oder nur minimale Änderungen erfordern. Getestet auf Galaxy Nexus JB 4.2.1. Sie müssen ein ViewPagerCustomDuration in Ihrem XML-Code anstelle von ViewPager verwenden, und dann können Sie dies tun:

_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));
    }

}
_

Hoffe das hilft jemandem!

103
Oleg Vaskevich

Ich habe eine bessere Lösung gefunden, basierend auf @ df778899s Antwort und der Android ValueAnimator API . Es funktioniert einwandfrei ohne Reflektion und ist sehr flexibel. Außerdem müssen Sie keinen benutzerdefinierten ViewPager erstellen und in das Paket Android.support.v4.view einfügen. Hier ist ein Beispiel:

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();
    }
}

AKTUALISIEREN:

Es wurde nur geprüft, ob mit dieser Lösung mehrere Seiten gleichzeitig gewischt werden können (beispielsweise, wenn die erste Seite nach der letzten angezeigt werden soll). Dies ist ein geringfügig geänderter Code, um die angegebene Seitenanzahl zu verarbeiten:

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;
}
30
lobzik
 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);
        }
    }
}
8
Cícero Moura

Eine bessere Lösung ist, einfach auf die privaten Felder zuzugreifen, indem Sie die Klasse im Support Package erstellen.EDITDies ist an den MAX_SETTLE_DURATION von 600 ms gebunden, der von der ViewPager-Klasse festgelegt wird.

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);
    }

}

Sie können dann natürlich ein benutzerdefiniertes Attribut hinzufügen, damit dieses über XML festgelegt werden kann.

7
Paul Burke

Nachdem ich meinen ganzen Tag verschwendet hatte, fand ich eine Lösung für offscreenPageLimit auf total no. der Seite.

Um eine konstante Länge des ViewPager-Bildlaufs beizubehalten, behält setOffScreenLimit (page.length) alle Ansichten im Speicher. Dies stellt jedoch ein Problem für alle Animationen dar, die den Aufruf der View.requestLayout-Funktion beinhalten (z. B. Animationen, bei denen Änderungen am Rand oder an den Begrenzungen vorgenommen werden). Das macht sie wirklich langsam (wie bei Romain Guy), da alle Ansichten, die sich im Speicher befinden, ebenfalls ungültig werden. Also habe ich ein paar verschiedene Möglichkeiten ausprobiert, um die Dinge reibungslos zu gestalten, aber requestLayout und andere Ungültigkeitsverfahren zu überschreiben, führt zu vielen anderen Problemen.

Ein guter Kompromiss ist das dynamische Ändern des Off-Screen-Limits, sodass die meisten Bildlaufseiten zwischen den Seiten sehr glatt sind und gleichzeitig sichergestellt wird, dass alle Animationen auf der Seite glatt sind, indem die Ansichten des Benutzers entfernt werden. Das funktioniert wirklich gut, wenn Sie nur 1 oder 2 Ansichten haben, die andere Ansichten aus dem Speicher nehmen müssen.

*** Verwenden Sie diese Option, wenn keine Lösung funktioniert, da durch das Setzen des Offeset-Limits u alle Fragmente gleichzeitig geladen werden

0
Anil Jaiswal

Hier ist mein Code in 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
        }
    }

 }
0
Foobnix