Вопрос по scroll, android-viewpager, android – Плавная прокрутка не работает в ViewPager (поддержка библиотеки)

10

Я пишу приложение, которое используетViewPager принимать гостейFragments.

Когда я изменяю фрагмент программно, функция плавной прокрутки не работает. Я использую метод ViewPager.setCurrentItem (int item, boolean smoothScroll).

Может быть, кто-нибудь знает обойти эту ошибку? Может быть, с анимацией?

РЕДАКТИРОВАТЬ: Я использую пакет поддержки. И вопрос в том, использую ли яViewPager.setCurrentItem(2, true) или жеViewPager.setCurrentItem(2, false) результат тот же. Вид переключается очень быстро (не плавно).

Прежде всего, viewpager ТОЛЬКО существует в пакете поддержки. Теперь возникает вопрос, с какой проблемой вы сталкиваетесь? если вы делаете setCurrentItem (2, false), что он делает вместо этого? Вы можете отредактировать свой вопрос, чтобы быть немного более конкретным? Jorge Aguilar
Поэтому я поставил mPager.setCurrentItem (1, true); в postrunnable дать пользователю подсказку, что объект является пейджером. Проблема в том, что анимация отсутствует, когда я помещаю ее в postrunnable, что убивает точку. Есть ли другой способ, которым я мог бы сделать это? MinceMan

Ваш Ответ

2   ответа
17

создав 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*/);
    }
  }
} 
Я согласен, что это обходной путь для ошибки ViewPager (IMO)
Если вы используете этот обходной путь и ProGuard, вам необходимо добавить его в конфигурацию ProGuard:-keepclassmembers class android.support.v4.view.ViewPager { private android.widget.Scroller mScroller; }
Это решение неприятно, но на самом деле должно работать! Спасибо, я постараюсь реализовать ваше предложение. Tautvydas
-1

что мне помогло, это вызвать mPager.setCurrentItem после mPagerAdapter.notifyDataSetChanged (), а не как опубликованный исполняемый файл.

Вот пример (в MonoDroid):

    public void UpdateDetialsView(string type)
    {
        string typeName4 = Java.Lang.Class.FromType(typeof(ParcelRecordComplaintDetailsView)).Name;

        if (_fragments.Count > 3)
        {
            _fragments.RemoveAt(_fragments.Count - 1);

            ////////////////////////////////////////////////////////////
            // Called here it wasn't working for me (Posted or not)

            //_viewPager.Post(new Action(() => { _viewPager.SetCurrentItem(3, true); }));
        }

        _fragments.Add(Fragment.Instantiate(Activity, typeName4));

        _pagerAdapter.NotifyDataSetChanged();

        ////////////////////////////////////////////////////////////
        // Called here it works as expected

        _viewPager.SetCurrentItem(3, true);
    }

где

    protected MyAdapter _pagerAdapter;
    protected ViewPager _viewPager;
    private List<Android.App.Fragment> _fragments;

а также

    public class MyAdapter : Android.Support.V13.App.FragmentStatePagerAdapter
    {
        private List<Fragment> _fragments;

        public override Java.Lang.Object InstantiateItem(View p0, int p1)
        {
            return base.InstantiateItem(p0, p1);
        }

        public MyAdapter(Android.App.FragmentManager fm) : base(fm)
        {

        }

        public MyAdapter(Android.App.FragmentManager fm, List<Android.App.Fragment> fragments) : base(fm)
        {
            _fragments = fragments;
        }

        public override int Count
        {
            //get { return FRAG_PAGES; }
            get { return _fragments.Count; }
        }

        public override Android.App.Fragment GetItem(int p0)
        {
            return _fragments[p0];
        }

        public override float GetPageWidth(int p0)
        {
            //return base.GetPageWidth(p0);

            return (float) (0.5f);
        }

        public override int GetItemPosition(Java.Lang.Object p0)
        {
            //return base.GetItemPosition(p0);
            return PagerAdapter.PositionNone;
        }
    }
Интересно. Вы меняете фрагменты, это правильно? Я не изменяю сами фрагменты, просто пытаюсь переключаться между ними. Я попробую кое-что с этой идеей NotifyDataSetChanged (). Спасибо! Tautvydas
Да, я меняю их динамически. У меня есть 4 половины экрана панели, которые реализованы в виде фрагментов и размещены внутри ViewPager. Каждая панель отображает подробности элемента от панели слева (и именно поэтому я их динамически обновляю). Я не думаю, что NotifyDataSetChanged должен повредить что-либо, если вы вызываете его, фактически не изменив ничего заранее, хотя я не уверен, поможет ли это (если это не так, возможно, вы можете что-то изменить в очень незначительном фрагменте, измените его назад, затем вызвать NotifyDataSetChanged, чтобы заставить его?).

Похожие вопросы