Android
ViewPager
Sök…
Introduktion
ViewPager är en layouthanterare som låter användaren bläddra åt vänster och höger genom datasidor. Det används oftast tillsammans med Fragment, vilket är ett bekvämt sätt att leverera och hantera livscykeln på varje sida.
Anmärkningar
En viktig sak att notera om ViewPager-användning är att det finns två olika versioner av både FragmentPagerAdapter
och FragmentStatePagerAdapter
.
Om du använder android.app.Fragment
ursprungliga fragment med en FragmentPagerAdapter eller FragmentStatePagerAdapter, måste du använda v13-supportbibliotekets versioner av adaptern, dvs. android.support.v13.app.FragmentStatePagerAdapter
.
Om du använder android.support.v4.app.Fragment
supportbibliotekfragment med en FragmentPagerAdapter eller FragmentStatePagerAdapter, måste du använda versionerna för v4 supportbibliotek av adaptern, dvs android.support.v4.app.FragmentStatePagerAdapter
.
Grundläggande ViewPager-användning med fragment
En ViewPager
tillåter att visa flera fragment i en aktivitet som kan navigeras genom att antingen vända till vänster eller höger. En ViewPager
måste matas antingen av Visningar eller fragment med hjälp av en PagerAdapter
.
Det finns dock två mer specifika implementationer som du kommer att hitta mest användbara om du använder Fragment som är FragmentPagerAdapter
och FragmentStatePagerAdapter
. När ett fragment måste instanseras för första gången, kommer getItem(position)
att kallas för varje position som behöver inställas. getCount()
returnerar det totala antalet sidor så att ViewPager
vet hur många fragment som måste visas.
Både FragmentPagerAdapter
och FragmentStatePagerAdapter
behåller en cache av de fragment som ViewPager
behöver visa. Som standard kommer ViewPager
att försöka lagra maximalt 3 fragment som motsvarar det för närvarande synliga fragmentet och de bredvid höger och vänster. Även FragmentStatePagerAdapter
behåller tillståndet för vart och ett av dina fragment.
Var medveten om att båda implementeringarna antar att dina fragment kommer att behålla sina positioner, så om du behåller en lista över fragmenten istället för att ha ett statiskt antal av dem som du kan se i getItem()
måste du skapa en underklass av PagerAdapter
och åsidosätta åtminstone instantiateItem()
, destroyItem()
och getItemPosition()
metoder.
Lägg bara till en ViewPager i din layout som beskrivs i grundexemplet :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout>
<android.support.v4.view.ViewPager
android:id="@+id/vpPager">
</android.support.v4.view.ViewPager>
</LinearLayout>
Definiera sedan adaptern som kommer att avgöra hur många sidor som finns och vilket fragment som ska visas för varje sida i adaptern.
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;
}
}
}
Om du använder android.app.Fragment
måste du lägga till detta beroende:
compile 'com.android.support:support-v13:25.3.1'
Om du använder android.support.v4.app.Fragment
måste du lägga till detta beroende:
compile 'com.android.support:support-fragment:25.3.1'
ViewPager med TabLayout
En TabLayout
kan användas för enklare navigering.
Du kan ställa in flikarna för varje fragment i din adapter med hjälp av TabLayout.newTab()
men det finns en annan bekvämare och enklare metod för den här uppgiften som är TabLayout.setupWithViewPager()
.
Den här metoden synkroniseras genom att skapa och ta bort flikar enligt innehållet i adaptern som är associerad med din ViewPager
varje gång du ringer den.
Dessutom ställer den in en återuppringning så att varje gång användaren vänder på sidan kommer motsvarande flik att väljas.
Definiera bara en layout
<?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>
Implementera sedan FragmentPagerAdapter
och applicera den på 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 med PreferenceFragment
Tills nyligen skulle android.support.v4.app.FragmentPagerAdapter
förhindra användning av ett PreferenceFragment
som ett av de fragment som används i FragmentPagerAdapter.
De senaste versionerna av support v7-biblioteket inkluderar nu klassen PreferenceFragmentCompat
, som fungerar med en ViewPager och v4-versionen av FragmentPagerAdapter.
Exempel Fragment som utvidgar 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) {
}
}
Du kan nu använda detta fragment i en android.support.v4.app.FragmentPagerAdapter
underklass:
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;
}
}
// .......
}
Lägga till en ViewPager
Se till att följande beroende läggs till i appens build.gradle
fil under beroenden:
compile 'com.android.support:support-core-ui:25.3.0'
Lägg sedan till ViewPager
i din aktivitetslayout:
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
Definiera sedan din 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;
}
}
Slutligen konfigurera ViewPager
i din aktivitet:
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 med en prickindikator
Allt vi behöver är: ViewPager , TabLayout och 2 rader för utvalda och standardprickar.
Först måste vi lägga till TabLayout
i vår skärmlayout och ansluta den till ViewPager
. Vi kan göra detta på två sätt:
Nested TabLayout i 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>
I detta fall
TabLayout
automatiskt tillViewPager
, menTabLayout
kommer bredvidViewPager
, inte över honom.
Separera 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"/>
I det här fallet kan vi placera
TabLayout
helst, men vi måste anslutaTabLayout
tillViewPager
programmatiskt
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);
När vi skapat vår layout måste vi förbereda våra prickar. Så vi skapar tre filer: selected_dot.xml
, default_dot.xml
och 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>
Nu måste vi lägga till bara TabLayout
rader med kod till TabLayout
i vår xml-layout och du är klar.
app:tabBackground="@drawable/tab_selector"
app:tabGravity="center"
app:tabIndicatorHeight="0dp"
Konfigurera OnPageChangeListener
Om du behöver lyssna efter ändringar på den valda sidan kan du implementera ViewPager.OnPageChangeListener
lyssnaren på 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
}
});