Szukaj…


Wprowadzenie

ViewPager to menedżer układu, który pozwala użytkownikowi przewijać strony danych w lewo i prawo. Najczęściej jest używany w połączeniu z Fragment, który jest wygodnym sposobem dostarczania i zarządzania cyklem życia każdej strony.

Uwagi

Jedną ważną rzeczą, na którą należy zwrócić uwagę przy korzystaniu z ViewPager, jest to, że istnieją dwie różne wersje zarówno FragmentPagerAdapter jak i FragmentStatePagerAdapter .

Jeśli używasz rodzimych fragmentów android.app.Fragment z FragmentPagerAdapter lub FragmentStatePagerAdapter, musisz użyć wersji biblioteki obsługi v13 adaptera, tj. android.support.v13.app.FragmentStatePagerAdapter .

Jeśli korzystasz z biblioteki obsługi android.support.v4.app.Fragment Fragmenty z FragmentPagerAdapter lub FragmentStatePagerAdapter, musisz użyć wersji biblioteki wsparcia v4 adaptera, tj. android.support.v4.app.FragmentStatePagerAdapter .

Podstawowe użycie ViewPager z fragmentami

ViewPager pozwala pokazać wiele fragmentów w działaniu, którym można nawigować, przesuwając w lewo lub w prawo. ViewPager musi być podawany jako widok lub fragment za pomocą PagerAdapter .

Istnieją jednak dwie bardziej szczegółowe implementacje, które okażą się najbardziej przydatne w przypadku korzystania z Fragmentów, które są FragmentPagerAdapter i FragmentStatePagerAdapter . Kiedy Fragment musi zostać utworzony po raz pierwszy, getItem(position) zostanie wywołany dla każdej pozycji, która wymaga utworzenia. Metoda getCount() zwróci całkowitą liczbę stron, aby ViewPager wiedział, ile fragmentów należy wyświetlić.

Zarówno FragmentPagerAdapter jak i FragmentStatePagerAdapter przechowują pamięć podręczną fragmentów, które ViewPager będzie musiał wyświetlić. Domyślnie ViewPager będzie próbował zapisać maksymalnie 3 Fragmenty, które odpowiadają aktualnie widocznemu Fragmentowi, i te obok prawej i lewej. FragmentStatePagerAdapter zachowa stan każdego z twoich fragmentów.

Należy pamiętać, że obie implementacje zakładają, że twoje fragmenty zachowają swoje pozycje, więc jeśli getItem() listę fragmentów zamiast mieć ich statyczną liczbę, jak widać w getItem() , musisz utworzyć podklasę PagerAdapter i przesłonić przynajmniej metody instantiateItem() , destroyItem() i getItemPosition() .

Wystarczy dodać ViewPager do swojego układu, jak opisano w podstawowym przykładzie :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout> 
    <android.support.v4.view.ViewPager
        android:id="@+id/vpPager"> 
    </android.support.v4.view.ViewPager>
</LinearLayout>

Następnie zdefiniuj adapter, który określi, ile stron istnieje i jaki fragment ma zostać wyświetlony dla każdej strony adaptera.

public class MyViewPagerActivity extends AppCompatActivity {
    private static final String TAG = MyViewPagerActivity.class.getName();

    private MyPagerAdapter mFragmentAdapter;
    private ViewPager mViewPager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);    
        setContentView(R.layout.myActivityLayout);

        //Apply the Adapter
        mFragmentAdapter = new MyPagerAdapter(getSupportFragmentManager());    
        mViewPager = (ViewPager) findViewById(R.id.view_pager);
        mViewPager.setAdapter(mFragmentAdapter);
    }

    private class MyPagerAdapter extends FragmentPagerAdapter{

        public MyPagerAdapter(FragmentManager supportFragmentManager) {
            super(supportFragmentManager);
        }

        // Returns the fragment to display for that page
        @Override
        public Fragment getItem(int position) {
            switch(position) {
                case 0:
                    return new Fragment1();

                case 1:
                    return new Fragment2();

                case 2:
                    return new Fragment3();

                default:
                    return null;
            }
        }

        // Returns total number of pages    
        @Override
        public int getCount() {
            return 3;
        }

    }
}
3.2.x

Jeśli używasz android.app.Fragment , musisz dodać tę zależność:

compile 'com.android.support:support-v13:25.3.1'

Jeśli używasz android.support.v4.app.Fragment , musisz dodać tę zależność:

compile 'com.android.support:support-fragment:25.3.1'

ViewPager z TabLayout

TabLayout może służyć do łatwiejszej nawigacji.
Możesz ustawić tabulatory dla każdego fragmentu w adapterze, używając metody TabLayout.newTab() , ale istnieje inna wygodniejsza i łatwiejsza metoda dla tego zadania, którą jest TabLayout.setupWithViewPager() .

Ta metoda zostanie zsynchronizowana poprzez tworzenie i usuwanie kart zgodnie z zawartością adaptera powiązanego z ViewPager każdym razem, gdy go wywołasz.
Ponadto ustawi oddzwonienie, więc za każdym razem, gdy użytkownik przewróci stronę, wybierana będzie odpowiednia karta.

Po prostu zdefiniuj układ

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout>

    <android.support.design.widget.TabLayout
        android:id="@+id/tabs"
        app:tabMode="scrollable" />

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

</LinearLayout>

Następnie zaimplementuj FragmentPagerAdapter i zastosuj go do ViewPager :

public class MyViewPagerActivity extends AppCompatActivity {
    private static final String TAG = MyViewPagerActivity.class.getName();

    private MyPagerAdapter mFragmentAdapter;
    private ViewPager mViewPager;
    private TabLayout mTabLayout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);    
        setContentView(R.layout.myActivityLayout);

        // Get the ViewPager and apply the PagerAdapter
        mFragmentAdapter = new MyPagerAdapter(getSupportFragmentManager());    
        mViewPager = (ViewPager) findViewById(R.id.view_pager);
        mViewPager.setAdapter(mFragmentAdapter);

        // link the tabLayout and the viewpager together
        mTabLayout = (TabLayout) findViewById(R.id.tab_layout);
        mTabLayout.setupWithViewPager(mViewPager);
    }

    private class MyPagerAdapter extends FragmentPagerAdapter{

        public MyPagerAdapter(FragmentManager supportFragmentManager) {
            super(supportFragmentManager);
        }

         // Returns the fragment to display for that page
        @Override
        public Fragment getItem(int position) {
            switch(position) {
                case 0:
                    return new Fragment1();

                case 1:
                    return new Fragment2();

                case 2:
                    return new Fragment3();

                default:
                    return null;
            }
        }
        
        // Will be displayed as the tab's label
        @Override
        public CharSequence getPageTitle(int position) {
            switch(position) {
                case 0:
                    return "Fragment 1 title";

                case 1:
                    return "Fragment 2 title";

                case 2:
                    return "Fragment 3 title";

                default:
                    return null;
            }
        }

        // Returns total number of pages 
        @Override
        public int getCount() {
            return 3;
        }

    }
}

ViewPager z PreferenceFragment

Do niedawna użycie android.support.v4.app.FragmentPagerAdapter uniemożliwiało użycie PreferenceFragment jako jednego z fragmentów używanych w FragmentPagerAdapter.

Najnowsze wersje biblioteki obsługi v7 zawierają teraz klasę PreferenceFragmentCompat , która będzie współpracować z ViewPager i wersją v4 FragmentPagerAdapter.

Przykład fragmentu, który rozszerza PreferenceFragmentCompat :

import android.os.Bundle; 
import android.support.v7.preference.PreferenceFragmentCompat; 
import android.view.View; 
 
public class MySettingsPrefFragment extends PreferenceFragmentCompat { 
  
    public MySettingsPrefFragment() { 
        // Required empty public constructor 
    } 
 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        addPreferencesFromResource(R.xml.fragment_settings_pref); 
    } 
 
    @Override 
    public void onCreatePreferences(Bundle bundle, String s) { 
 
    } 
}

Możesz teraz używać tego fragmentu w podklasie android.support.v4.app.FragmentPagerAdapter :

private class PagerAdapterWithSettings extends FragmentPagerAdapter {

    public PagerAdapterWithSettings(FragmentManager supportFragmentManager) {
        super(supportFragmentManager);
    }

    @Override
    public Fragment getItem(int position) {
        switch(position) {
            case 0:
                return new FragmentOne();

            case 1:
                return new FragmentTwo();

            case 2:
                return new MySettingsPrefFragment();

            default:
                return null;
        }
    }
    
    // .......

}

Dodawanie ViewPager

Upewnij się, że do pliku build.gradle aplikacji w zależnościach dodano następującą zależność:

compile 'com.android.support:support-core-ui:25.3.0'

Następnie dodaj ViewPager do układu aktywności:

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

Następnie zdefiniuj swój PagerAdapter :

public class MyPagerAdapter extends PagerAdapter {

    private Context mContext;

    public CustomPagerAdapter(Context context) {
        mContext = context;
    }

    @Override
    public Object instantiateItem(ViewGroup collection, int position) {
 
        // Create the page for the given position. For example:
        LayoutInflater inflater = LayoutInflater.from(mContext);
        ViewGroup layout = (ViewGroup) inflater.inflate(R.layout.xxxx, collection, false);
        collection.addView(layout);
        return layout;
    }

    @Override
    public void destroyItem(ViewGroup collection, int position, Object view) {
        // Remove a page for the given position. For example:
        collection.removeView((View) view);
    }

    @Override
    public int getCount() {
        //Return the number of views available.
        return numberOfPages;
    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
        // Determines whether a page View is associated with a specific key object
        // as returned by instantiateItem(ViewGroup, int). For example:
        return view == object;
    }    
}

Na koniec skonfiguruj ViewPager w swojej aktywności:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
        viewPager.setAdapter(new MyPagerAdapter(this));
    }
}

ViewPager ze wskaźnikiem kropek

ViewPager ze wskaźnikiem kropek

Potrzebujemy tylko: ViewPager , TabLayout i 2 drawable dla wybranych i domyślnych kropek.

Po pierwsze, musimy dodać TabLayout do naszego układu ekranu i połączyć go z ViewPager . Możemy to zrobić na dwa sposoby:


Zagnieżdżony TabLayout w ViewPager

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

    <android.support.design.widget.TabLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
</android.support.v4.view.ViewPager>

W takim przypadku TabLayout zostanie automatycznie połączony z ViewPager , ale TabLayout będzie obok ViewPager , a nie nad nim.


Oddzielny tabLayout

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

<android.support.design.widget.TabLayout
    android:id="@+id/tab_layout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"/>

W takim przypadku możemy umieścić TabLayout dowolnym miejscu, ale musimy połączyć TabLayout z ViewPager programowo

ViewPager pager = (ViewPager) view.findViewById(R.id.photos_viewpager);
PagerAdapter adapter = new PhotosAdapter(getChildFragmentManager(), photosUrl);
pager.setAdapter(adapter);

TabLayout tabLayout = (TabLayout) view.findViewById(R.id.tab_layout);
tabLayout.setupWithViewPager(pager, true);

Po stworzeniu naszego układu musimy przygotować nasze kropki. Tworzymy więc trzy pliki: selected_dot.xml , default_dot.xml i tab_selector.xml .


selected_dot.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape
            android:innerRadius="0dp"
            android:shape="ring"
            android:thickness="8dp"
            android:useLevel="false">
            <solid android:color="@color/colorAccent"/>
        </shape>    
    </item>
</layer-list>

default_dot.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape
            android:innerRadius="0dp"
            android:shape="ring"
            android:thickness="8dp"
            android:useLevel="false">
            <solid android:color="@android:color/darker_gray"/>
        </shape>    
    </item>
</layer-list>

tab_selector.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:drawable="@drawable/selected_dot"
          android:state_selected="true"/>

    <item android:drawable="@drawable/default_dot"/>
</selector>

Teraz musimy dodać tylko 3 linie kodu do TabLayout w naszym układzie xml i gotowe.

app:tabBackground="@drawable/tab_selector"
app:tabGravity="center"
app:tabIndicatorHeight="0dp"

Skonfiguruj OnPageChangeListener

Jeśli trzeba nasłuchiwać zmian wybranego można wdrożyć stronie ViewPager.OnPageChangeListener słuchacza na ViewPager:

viewPager.addOnPageChangeListener(new OnPageChangeListener() {
    
    // This method will be invoked when a new page becomes selected. Animation is not necessarily complete.
    @Override
    public void onPageSelected(int position) {
         // Your code
    }
    
    // This method will be invoked when the current page is scrolled, either as part of 
    // a programmatically initiated smooth scroll or a user initiated touch scroll.
    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
         // Your code
    }
    
    // Called when the scroll state changes. Useful for discovering when the user begins
    // dragging, when the pager is automatically settling to the current page, 
    // or when it is fully stopped/idle.
    @Override
    public void onPageScrollStateChanged(int state) {
         // Your code
    }
});


Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow