Подтвердить что ты не робот

ViewPager setCurrentItem (pageId, true) НЕ плавает

Я компилирую на SDK 4.03, Samsung Infuse Android 2.2, библиотеку поддержки для Android 4 и используя ViewPager в своем приложении, фактический салфетки отлично работает, но когда я делаю

viewPager.setCurrentItem(id); // , or
viewPager.setCurrentItem(id, true);  

Он не сглаживает прокрутку, но мгновенно переключает представления. Хотя в документации четко указано, что это цель, устанавливающая второй аргумент true. Что с этим?

4b9b3361

Ответ 1

Я исправил это, создав MyViewPager, который переопределяет ViewPager.mScroller, используя отражение.

public class MyViewPager extends ViewPager {

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

    private void setMyScroller() {
        try {
            Class<?> viewpager = ViewPager.class;
            Field scroller = viewpager.getDeclaredField("mScroller");
            scroller.setAccessible(true);
            scroller.set(this, new MyScroller(getContext()));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public class MyScroller extends Scroller {
        public MyScroller(Context context) {
            super(context, new DecelerateInterpolator());
        }

        @Override
        public void startScroll(int startX, int startY, int dx, int dy, int duration) {
            super.startScroll(startX, startY, dx, dy, 1000 /*1 secs*/);
        }
    }
}

Ответ 2

Это то, что я сделал. Я переопределил метод private-private smoothScrollTo в ViewPager, поставив свой собственный подкласс в один и тот же пакет. Ему передавалось значение, равное нулю, что приводит к поведению привязки вместо гладкой прокрутки.

package android.support.v4.view;

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

public class MyViewPager extends ViewPager {

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

    public MyViewPager(Context context, AttributeSet attr) {
        super(context, attr);
    }

    void smoothScrollTo(int x, int y, int velocity) {
        super.smoothScrollTo(x, y, 1);
    }
}

Он отлично поработал, если вы хотите, чтобы вы могли рассчитать и обеспечить фактическую скорость ISO всего за 1.

Ответ 3

Я вызвал функцию setCurrentItem в обработчике, и он отлично работал у меня.

new Handler().post(new Runnable() {
        @Override
        public void run() {
            myViewPager.setCurrentItem(1, true);
        }
    });

Надеюсь, что это поможет.

Ответ 4

Я знаю, что этот поток довольно старый, но это один из лучших результатов Google. Я уже много раз возвращался вперед, чтобы решить эту проблему. Ни одно из решений выше не помогло мне вообще. Однако я нашел решение, которое работает для меня.

В настоящее время моя настройка выглядит как просмотр изнутри viewpager. Когда вы нажимаете на одно из представлений, он создает новую страницу и прокручивает ее. Это было очень быстро, но кажется, что это потому, что я звонил

mViewPager.setCurrentItem(intIndex, true);

изнутри моего OnClickEvent. По какой-то причине viewpager не нравится, поэтому вместо этого я сделал эту функцию. Он создает новый поток, который запускает runnable в потоке пользовательского интерфейса. Этот runnable - это то, что сообщает ViewPager прокрутку к определенному элементу.

public static void scrollToIndex(int index) {

    final int intIndex = index;

    //We're going to make another thread to separate ourselves from whatever
    //thread we are in 
    Thread sepThread = new Thread(new Runnable(){

        public void run()
        {
            //Then, inside that thread, run a runnable on the ui thread.
            //MyActivity.getContext() is a static function that returns the 
            //context of the activity. It useful in a pinch.
            ((Activity)MyActivity.getContext()).runOnUiThread(new Runnable(){

                @Override
                public void run() {

                    if (mSlidingTabLayout != null)
                    {
                        //I'm using a tabstrip with this as well, make sure
                        //the tabstrip is updated, or else it won't scroll
                        //correctly
                        if(mSlidingTabLayout.getTabStripChildCount() <= intIndex)
                        mSlidingTabLayout.updateTabStrip();

                        //Inside this thread is where you call setCurrentItem
                        mViewPager.setCurrentItem(intIndex, true);

                    }

                }

            });

         }
    });


    sepThread.start();


}

Надеюсь, я по крайней мере помог кому-то с этой проблемой. Удачи!

Изменить: Оглядываясь на мой ответ, я уверен, что вы можете просто запустить на поток ui, и он должен работать. Возьмите это с солью, хотя я еще не проверял ее.

Ответ 5

ViewPager сильно изменился с 5 по 9. Некоторые из этих изменений могут быть связаны с вашей проблемой:

  • Исправлены ошибки для поведения пользовательского интерфейса в ViewPager (версии 5 и 6).
  • Исправлено множество ошибок для ViewPager (версия 9)

Давая понять, что ваш код должен работать нормально, я полагаю, что ваша библиотека поддержки не обновляется. Попробуйте обновить библиотеку, если это не так.

Ответ 6

Я создал этот класс, потому что я не был полностью удовлетворен вышеуказанными решениями

Класс переопределяет setCurrentItem(int item, boolean smoothScroll) и использует отражение, чтобы сохранить этот метод как можно более оригинальным. Ключевым моментом является то, что скорость не равна 0. Вам нужно только заменить текущий ViewPager на этот класс MyViewPager и использовать его как обычно:

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

import java.lang.reflect.Field;
import java.lang.reflect.Method;

import androidx.viewpager.widget.ViewPager;

public class MyViewPager extends ViewPager {

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

    /**
     * Set the currently selected page. If the ViewPager has already been through its first
     * layout with its current adapter there will be a smooth animated transition between
     * the current item and the specified item.
     *
     * @param item         Item index to select
     * @param smoothScroll True to smoothly scroll to the new item, false to transition immediately
     */
    @Override
    public void setCurrentItem(int item, boolean smoothScroll) {
        final Class<?> viewpager = ViewPager.class;
        int velocity = 1;

        try {
            Field mPopulatePending = viewpager.getDeclaredField("mPopulatePending");
            mPopulatePending.setAccessible(true);
            mPopulatePending.set(this, false);

            Method setCurrentItemInternal = viewpager.getDeclaredMethod("setCurrentItemInternal", int.class, boolean.class, boolean.class, int.class);
            setCurrentItemInternal.setAccessible(true);
            setCurrentItemInternal.invoke(this, item, smoothScroll, false, velocity);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Ответ 7

У меня была та же проблема, но сегодня я нашел простое решение. Может быть, это поможет вам. Во-первых, давайте предположим, что у нас есть ViewPager, который заполняет весь экран. Чтобы переключаться между страницами, я создал собственный пользовательский вид с вкладками и поместил его поверх ViewPager. Щелчок на вкладке должен плавно прокручиваться на соответствующую страницу в ViewPager с помощью setCurrentItem (item, true) - но он прокручивается мгновенно, без каких-либо плавности! Затем я попытался добавить простую кнопку (не пользовательскую) через обратный вызов ViewPager +:

@Override
public void onClick(View v) {
   viewPager.setCurrentItem(item, true);
}

После этого гладкий свиток смотрел на работу. Итак, решение было очень простым: внутри класса Button внутренний булевский onTouch (...) прослушиватель возвращает true, поэтому он всегда ПОТРЕБИТ события касания! Затем гладкая прокрутка начала работать для моего пользовательского представления вкладок, когда я заменил "return false" на "return true" во внутреннем булевом onTouch (...) прослушивателе.

Я надеюсь, что моя история успеха поможет вам.

Ответ 8

Для тех, кто использует Xamarin (хотя этот подход применим и к Java), я могу предложить использовать следующий подход на основе вышеприведенного ответа (ViewPager из Android Support Library v7 AppCompat 19.1.0):

public void ScrollSmooth(int i)
{
    var jClass = JNIEnv.GetObjectClass(_pager.Handle);
    var jMethod = JNIEnv.GetMethodID(jClass, "setCurrentItemInternal", "(IZZI)V");
    JNIEnv.CallVoidMethod (_pager.Handle, jMethod, new JValue (i), new JValue (true), new JValue (false), new JValue (1));
}

Он полагается на реализацию ViewPager из http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.0.1_r1/android/support/v4/view/ViewPager.java

Ответ 9

Потратив весь свой день, я нашел решение с установленным offscreenPageLimit на общее количество нет. страницы.

пожалуйста, следуйте этому fooobar.com/questions/102600/...

Ответ 10

Обратите внимание на эту переменную mFirstLayout - она будет установлена в значение true при обратном onAttachedToWindow viewpager для onAttachedToWindow (например, в обзоре реселлера) onAttachedToWindow поэтому не будет smoothScroll. Вы должны переопределить onAttachedToWindow для управления переменной mFirstLayout. Что-то вроде этого:

        @Override
        protected void onAttachedToWindow() {
            super.onAttachedToWindow();
            try {
                Field mFirstLayout = ViewPager.class.getDeclaredField("mFirstLayout");
                mFirstLayout.setAccessible(true);
                mFirstLayout.set(this, false);
                getAdapter().notifyDataSetChanged();
                setCurrentItem(getCurrentItem());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

Ответ 11

попробуйте этот код:

viewPager.postDelayed(new Runnable()
{
    @Override
    public void run()
    {
        viewPager.setCurrentItem(id, true);
    }
}, 100);