[android] एंड्रॉइड में Viewpager नियंत्रक की धीमी गति



Answers

मैं खुद को करना चाहता हूं और एक समाधान प्राप्त कर लिया है (हालांकि प्रतिबिंब का उपयोग कर)। यह स्वीकार्य समाधान के समान है लेकिन एक ही इंटरपोलेटर का उपयोग करता है और केवल कारक के आधार पर अवधि बदलता है। आपको ViewPagerCustomDuration बजाय अपने XML में ViewPagerCustomDuration का उपयोग करने की आवश्यकता है, और फिर आप यह कर सकते हैं:

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 {
            Class<?> viewpager = ViewPager.class;
            Field scroller = viewpager.getDeclaredField("mScroller");
            scroller.setAccessible(true);
            Field interpolator = viewpager.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));
    }

}

उम्मीद है कि यह किसी की मदद करता है!

Question

एंड्रॉइड में व्यूपेजर एडेप्टर के साथ स्क्रॉल स्पीड को धीमा करने का कोई तरीका है?

आप जानते हैं, मैं इस कोड को देख रहा हूं। मैं यह नहीं समझ सकता कि मैं क्या गलत हूं।

try{ 
    Field mScroller = mPager.getClass().getDeclaredField("mScroller"); 
    mScroller.setAccessible(true); 
    Scroller scroll = new Scroller(cxt);
    Field scrollDuration = scroll.getClass().getDeclaredField("mDuration");
    scrollDuration.setAccessible(true);
    scrollDuration.set(scroll, 1000);
    mScroller.set(mPager, scroll);
}catch (Exception e){
    Toast.makeText(cxt, "something happened", Toast.LENGTH_LONG).show();
} 

यह कुछ भी नहीं बदलता है अभी तक कोई अपवाद नहीं होता है?




यह सही समाधान नहीं है, आप वेग धीमा नहीं कर सकते क्योंकि यह एक int । लेकिन मेरे लिए यह काफी धीमा है और मुझे प्रतिबिंब का उपयोग करने की ज़रूरत नहीं है।

उस पैकेज पर ध्यान दें जहां कक्षा है। smoothScrollTo पैकेज दृश्यता है।

package android.support.v4.view;

import android.content.Context;
import android.util.AttributeSet;

public class SmoothViewPager extends ViewPager {
    private int mVelocity = 1;

    public SmoothViewPager(Context context) {
        super(context);
    }

    public SmoothViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    void smoothScrollTo(int x, int y, int velocity) {
        //ignore passed velocity, use one defined here
        super.smoothScrollTo(x, y, mVelocity);
    }
}



ViewPager पर fakeDrag विधियां एक वैकल्पिक समाधान प्रदान करने लगती हैं।

उदाहरण के लिए यह आइटम 0 से 1 तक पृष्ठ होगा:

rootView.setOnClickListener(new OnClickListener() {
  @Override
  public void onClick(View v) {
      ViewPager pager = (ViewPager) getActivity().findViewById(R.id.pager);
      //pager.setCurrentItem(1, true);
      pager.beginFakeDrag();
      Handler handler = new Handler();
      handler.post(new PageTurner(handler, pager));
  }
});


private static class PageTurner implements Runnable {
  private final Handler handler;
  private final ViewPager pager;
  private int count = 0;

  private PageTurner(Handler handler, ViewPager pager) {
    this.handler = handler;
    this.pager = pager;
  }

  @Override
  public void run() {
    if (pager.isFakeDragging()) {
      if (count < 20) {
        count++;
        pager.fakeDragBy(-count * count);
        handler.postDelayed(this, 20);
      } else {
        pager.endFakeDrag();
      }
    }
  }
}

( count * count सिर्फ ड्रैग की गति को चलाने के लिए है)




एक पूरी तरह से अलग दृष्टिकोण का उपयोग कर एक जवाब यहाँ है। कोई कह सकता है कि इसमें एक हैकी महसूस है; हालांकि, यह प्रतिबिंब का उपयोग नहीं करता है, और मैं तर्क दूंगा कि यह हमेशा काम करेगा।

हमें ViewPager.smoothScrollTo के अंदर निम्न कोड मिलता है:

    if (velocity > 0) {
        duration = 4 * Math.round(1000 * Math.abs(distance / velocity));
    } else {
        final float pageWidth = width * mAdapter.getPageWidth(mCurItem);
        final float pageDelta = (float) Math.abs(dx) / (pageWidth + mPageMargin);
        duration = (int) ((pageDelta + 1) * 100);
    }
    duration = Math.min(duration, MAX_SETTLE_DURATION);

यह कुछ चीजों के आधार पर अवधि की गणना करता है। कुछ भी देखें जिसे हम नियंत्रित कर सकते हैं? mAdapter.getPageWidth । चलिए अपने एडाप्टर में ViewPager.OnPageChangeListener को लागू करते हैं। जब हम ViewPager स्क्रॉल कर रहे हैं, तो हम यह पता लगाने जा रहे हैं, और चौड़ाई के लिए नकली मान दें । अगर मैं अवधि k*100 होना चाहता हूं, तो मैं getPageWidth लिए 1.0/(k-1) कर getPageWidth । निम्नलिखित एडाप्टर के इस हिस्से के कोटलिन इम्प्लाइज है जो अवधि को 400 में बदल देता है:

    var scrolling = false
    override fun getPageWidth(position: Int): Float {
        return if (scrolling) 0.333f else 1f
    }

    // OnPageChangeListener to detect scroll state
    override fun onPageScrollStateChanged(state: Int) {
        scrolling = state == ViewPager.SCROLL_STATE_SETTLING
    }

    override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
    }

    override fun onPageSelected(position: Int) {
    }

एडाप्टर को OnPageChangedListener के रूप में जोड़ने के लिए मत भूलना।

मेरा विशेष मामला सुरक्षित रूप से यह मान सकता है कि उपयोगकर्ता पृष्ठों के बीच खींचने के लिए स्वाइप नहीं कर सकता है। यदि आपको ड्रैग के बाद निपटने का समर्थन करना है, तो आपको अपनी गणना में थोड़ा और करने की आवश्यकता है।

एक नकारात्मक बात यह है कि यह ViewPager में उस हार्डकोडेड 100 बेस अवधि मान पर निर्भर करता है। यदि यह बदलता है, तो आपके दृष्टिकोण इस दृष्टिकोण के साथ बदल जाते हैं।




Related



Tags

android android