Android
ViewPager
Поиск…
Вступление
ViewPager - это менеджер макетов, который позволяет пользователю листать страницы слева и справа. Он чаще всего используется совместно с Fragment, что является удобным способом обеспечения и управления жизненным циклом каждой страницы.
замечания
Важно отметить, что использование ViewPager состоит в том, что существуют две разные версии FragmentPagerAdapter
и FragmentStatePagerAdapter
.
Если вы используете android.app.Fragment
native Fragments с помощью FragmentPagerAdapter или FragmentStatePagerAdapter, вам нужно использовать версии поддержки библиотеки v13 для адаптера, то есть android.support.v13.app.FragmentStatePagerAdapter
.
Если вы используете android.support.v4.app.Fragment
поддержки android.support.v4.app.Fragment
с помощью FragmentPagerAdapter или FragmentStatePagerAdapter, вам нужно использовать версии библиотеки поддержки v4 для адаптера, то есть android.support.v4.app.FragmentStatePagerAdapter
.
Использование Basic ViewPager с фрагментами
ViewPager
позволяет отображать несколько фрагментов в активности, которые можно перемещать либо влево, либо вправо. ViewPager
должен быть фидом либо Представлений, либо фрагментов с помощью PagerAdapter
.
Есть, однако, еще две конкретные реализации, которые вы найдете наиболее полезными в случае использования фрагментов, которые являются FragmentPagerAdapter
и FragmentStatePagerAdapter
. Когда в первый раз необходимо создать экземпляр фрагмента, getItem(position)
будет вызываться для каждой позиции, для которой требуется создание экземпляра. Метод getCount()
вернет общее количество страниц, чтобы ViewPager
знал, сколько фрагментов необходимо ViewPager
.
И FragmentPagerAdapter
и FragmentStatePagerAdapter
хранят кеш фрагментов, которые должен показать ViewPager
. По умолчанию ViewPager
попытается сохранить максимум 3 фрагмента, соответствующих ViewPager
видимому фрагменту, а также рядом с правой и левой. Также FragmentStatePagerAdapter
сохранит состояние каждого из ваших фрагментов.
Имейте в виду, что обе реализации предполагают, что ваши фрагменты будут сохранять свои позиции, поэтому, если вы сохраните список фрагментов вместо статического числа из них, как вы можете видеть в методе getItem()
, вам нужно будет создать подкласс PagerAdapter
и переопределить, по крайней мере, destroyItem()
instantiateItem()
, destroyItem()
и getItemPosition()
.
Просто добавьте ViewPager в свой макет, как описано в основном примере :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout>
<android.support.v4.view.ViewPager
android:id="@+id/vpPager">
</android.support.v4.view.ViewPager>
</LinearLayout>
Затем определите адаптер, который определит, сколько страниц существует и какой фрагмент будет отображаться для каждой страницы адаптера.
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;
}
}
}
Если вы используете android.app.Fragment
вы должны добавить эту зависимость:
compile 'com.android.support:support-v13:25.3.1'
Если вы используете android.support.v4.app.Fragment
вы должны добавить эту зависимость:
compile 'com.android.support:support-fragment:25.3.1'
ViewPager с TabLayout
TabLayout
можно использовать для упрощения навигации.
Вы можете установить вкладки для каждого фрагмента в вашем адаптере, используя TabLayout.newTab()
но есть еще один удобный и удобный метод для этой задачи, который является TabLayout.setupWithViewPager()
.
Этот метод будет синхронизироваться, создавая и удаляя вкладки в соответствии с содержимым адаптера, связанного с вашим ViewPager
каждый раз, когда вы его вызываете.
Кроме того, он будет устанавливать обратный вызов, чтобы каждый раз, когда пользователь переворачивает страницу, будет выбрана соответствующая вкладка.
Просто определите макет
<?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>
Затем выполните FragmentPagerAdapter
и примените его к 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 с PreferenceFragment
До недавнего времени использование android.support.v4.app.FragmentPagerAdapter
предотвратило бы использование PreferenceFragment
как одного из фрагментов, используемых в FragmentPagerAdapter.
В последних версиях библиотеки поддержки v7 теперь есть класс PreferenceFragmentCompat
, который будет работать с ViewPager и версией версии FragmentPagerAdapter версии v4.
Пример фрагмента, который расширяет 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) {
}
}
Теперь вы можете использовать этот фрагмент в подклассе 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;
}
}
// .......
}
Добавление ViewPager
Убедитесь, что в файл build.gradle
вашего приложения добавлена build.gradle
зависимость:
compile 'com.android.support:support-core-ui:25.3.0'
Затем добавьте ViewPager
в свой макет действий:
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
Затем определите свой 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;
}
}
Наконец, настройте ViewPager
в своей деятельности:
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 с индикатором точек
Все, что нам нужно: ViewPager , TabLayout и 2 чертежа для выбранных и стандартных точек.
Во-первых, мы должны добавить TabLayout
в наш макет экрана и подключить его к ViewPager
. Мы можем сделать это двумя способами:
Вложенная TabLayout в 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>
В этом случае
TabLayout
будет автоматически подключаться кViewPager
, ноTabLayout
будет рядом сViewPager
, а не над ним.
Отдельный 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"/>
В этом случае мы можем поместить
TabLayout
любом месте, но мы должны подключатьTabLayout
с помощьюViewPager
программно
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);
Как только мы создали наш макет, мы должны подготовить наши точки. Поэтому мы создаем три файла: selected_dot.xml
, default_dot.xml
и 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>
Теперь нам нужно добавить только 3 строки кода в TabLayout
в наш макет xml, и все готово.
app:tabBackground="@drawable/tab_selector"
app:tabGravity="center"
app:tabIndicatorHeight="0dp"
Настройка OnPageChangeListener
Если вам необходимо отслеживать изменения на странице выбранного вы можете реализовать ViewPager.OnPageChangeListener
слушателя на 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
}
});