ViewPagerIndicator и setOnPageChangeListener

Я хотел бы изменить цвет фона, когда пользователь меняет страницы, для этого мне нужно использовать ViewPager setOnPageChangeListener. Но похоже это тормозит ViewPagerIndicator, так как индикатор застревает на первой странице. Вот код

viewPager.setOnPageChangeListener(new OnPageChangeListener() {
    @Override
    public void onPageSelected(int position) {
        ColorDrawable[] colors = {new ColorDrawable(backgroundColors[previousPosition]), new ColorDrawable(backgroundColors[position])};
        TransitionDrawable trans = new TransitionDrawable(colors);
        viewPager.setBackgroundDrawable(trans);
        trans.startTransition(200);
        previousPosition = position;
    }

    @Override
    public void onPageScrolled(int arg0, float arg1, int arg2) {}

    @Override
    public void onPageScrollStateChanged(int arg0) {}
});

person Mehdiway    schedule 04.08.2014    source источник


Ответы (3)


В итоге я использовал метод ViewPagerIndicator setOnPageChangeListener вместо метода ViewPager.

mIndicator = (IconPageIndicator)findViewById(R.id.indicator);
mIndicator.setViewPager(viewPager);

Код становится:

mIndicator.setOnPageChangeListener(new OnPageChangeListener() {
    @Override
    public void onPageSelected(int position) {
        ColorDrawable[] colors = {new ColorDrawable(backgroundColors[previousPosition]), new ColorDrawable(backgroundColors[position])};
        TransitionDrawable trans = new TransitionDrawable(colors);
        viewPager.setBackgroundDrawable(trans);
        trans.startTransition(200);
        previousPosition = position;
    }

    @Override
    public void onPageScrolled(int arg0, float arg1, int arg2) {}

    @Override
    public void onPageScrollStateChanged(int arg0) {}
});
person Mehdiway    schedule 04.08.2014
comment
Я думаю, что это правильный способ использования индикатора вкладок и пользовательского PageChangeListener :-) - person Berťák; 04.08.2014

Этот способ изменения цвета между вкладками является первым подходом, но я думаю, что не так уж сложно придумать лучший вариант.

В вашем подходе: я думаю, что в вашем подходе, как только вы выбираете новую страницу, вы запускаете переход цвета фона. В этом случае переходы фиксируются во времени (200 миллисекунд в вашем случае), но это не кажется естественным, еще хуже, когда вы переключаете страницы, пролистывая их. Проблема в том, что onPageSelected является триггером включения/выключения. Вы находитесь на странице 0 или 1 или 2, но нет такого состояния, как "между 0 и 1".

Было бы здорово, если бы цвет был точно пропорционален количеству свайпов, это пропорционально реальному состоянию при переходе между вкладками??

Как это сделать?

В действии, размещающем пейджер просмотра, установите макет с таким количеством фоновых слоев, сколько вкладок вы хотите в пейджере просмотра. Если у вас есть 3 вкладки, установите 3 фоновых слоя, перекрывающих друг друга.

Например:

<LinearLayout
    android:id="@+id/background_main_fragment_activity_bottom"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/background_gradient_radial_blue_vivid"
    android:orientation="vertical"
    tools:visibility="visible">
</LinearLayout>

<LinearLayout
    android:id="@+id/background_main_fragment_activity_middle"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/background_gradient_radial_blue_samknows"
    android:orientation="vertical"
    tools:visibility="visible">
</LinearLayout>

<LinearLayout
    android:id="@+id/background_main_fragment_activity_top"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/background_gradient_radial_blue_light"
    android:orientation="vertical"
    tools:visibility="visible">
</LinearLayout>

<android.support.v4.view.ViewPager
    android:id="@+id/viewpager"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
</android.support.v4.view.ViewPager>

Каждый LinearLayout является фоном для определенной вкладки.

Идея состоит в том, чтобы изменить альфа-значение линейных макетов, сделав их видимыми, частично видимыми или невидимыми.

Вместо использования метода onPageSelected мы будем использовать onPageScrolled, взгляните:

// Set a listener that will be invoked whenever the page changes or is incrementally scrolled.
// This listener is used for changing smoothly the colour of the background, this is modifying the visibility of the different layers

viewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener()
{
        // Called when the scroll state changes

@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels)
{
        super.onPageScrolled(position, positionOffset, positionOffsetPixels);

        switch (position)
        {
            case 0:
                layout_ll_background_middle.setAlpha(positionOffset);
                break;

            case 1:                     
                layout_ll_background_top.setAlpha(positionOffset);
                break;

            default:
                break;
        }               
    }

    // This method will be invoked when a new page becomes selected

    @Override
    public void onPageSelected(int position)
    {       // When swiping between pages, select the corresponding tab         
            getActionBar().setSelectedNavigationItem(position);
            // Set the title    
            actionBar.setTitle(adapter_ViewPager.getPageTitle(position));       
    }           
});

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

Удачи

person Sotti    schedule 04.08.2014
comment
Это большое улучшение UX. Ты настоящий MVP - person Mehdiway; 18.12.2014

Поскольку синхронизированные переходы не совсем подходят для варианта использования, и альфа не должна использоваться (таким образом) для переходов/анимаций на Android, вот что я придумал:

Прежде всего убедитесь, что ни один дочерний вид не имеет фона, установленного там, где этого не должно быть. В базовом макете установите для фона макета начальный цвет.

В вашем Activity.onCreate() добавьте это:

final ViewPager mPager = (ViewPager) findViewById(R.id.ofYourPager);
// if you have a page indicator
final YourPageIndicator pageIndicator = (YourPageIndicator) findViewById(R.id.ofYourIndicator);

// change background on swipe
final int[] colors = {
    getResources().getColor(R.color.yourFirstColor),
    getResources().getColor(R.color.yourSecondColor),
    getResources().getColor(R.color.yourThirdColor),
    // --- add as many colours as you have pages ---
};
final ArgbEvaluator argbEvaluator = new ArgbEvaluator();
mPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        if (position < (mPagerAdapter.getCount() - 1) && position < (colors.length - 1)) {
            Integer color = (Integer) argbEvaluator.evaluate(positionOffset, colors[position], colors[position + 1]);
            mPager.setBackgroundColor(color);
            pageIndicator.setBackgroundColor(color);
        } else {
            mPager.setBackgroundColor(colors[colors.length - 1]);
            pageIndicator.setBackgroundColor(colors[colors.length - 1]);
        }
    }

    @Override
    public void onPageSelected(int position) {}

    @Override
    public void onPageScrollStateChanged(int state) {}
});

Я взял идею из этого поста, который нашел: http://kubaspatny.github.io/2014/09/18/viewpager-background-transition/

person m02ph3u5    schedule 23.06.2015