[Android] simple use from zero foundation to soaring ViewPager

2.6.3 simple use of viewpager

classification Android basics tutorial

Introduction to this section:

This section brings a UI control - ViewPager (View sliding switching tool) introduced after Android 3.0. I really can't think of how to call this control. Its general function: View switching can be completed through gesture sliding. It is generally used as the guide page of APP or to realize picture rotation. Because it was introduced after Android 3.0, if you want to use it in a lower version, You need to introduce V4 compatibility Package ~, we can also see that ViewPager is in: Android support. v4. View. Under the ViewPager directory ~ let's learn the basic usage of this control ~ Official API document: ViewPager

1. Brief introduction to viewpager

ViewPager is a simple Page switching component. We can fill multiple views into it, and then we can slide left and right to switch different views. We can set the animation effect of switching for our ViewPager through the setPageTransformer() method. Of course, we haven't learned the animation yet, So let's put the animation of ViewPager in the next chapter to explain the drawing and animation! Like ListView and GridView, we also need an Adapter to bind our View and ViewPager, and ViewPager has a specific Adapter - PagerAdapter! In addition, Google officially suggests that we use Fragment to fill the ViewPager, which can more easily generate each Page and manage the life cycle of each Page! Two Fragment specific adapters are provided: FragmentPageAdapter and FragmentStatePagerAdapter. Let's briefly analyze the differences between the two adapters:

  • FragmentPageAdapter: like PagerAdapter, only the current Fragment and one on the left and one on the right will be cached, that is, a total of 3 fragments will be cached. If there are 1, 2, 3 and 4 pages:
    On page 1: cache 1, 2
    On page 2: cache 1, 2, 3
    On page 3: destroy page 1, cache 2, 3, 4
    On page 4: destroy page 2, cache 3, 4
    More pages, and so on~
  • FragmentStatePagerAdapter: when the Fragment is not necessarily useful to the user, the whole Fragment will be destroyed and only the Fragment state will be saved! When the page needs to be displayed again, a new page will be generated!

To sum up, the FragmentPageAdapter is suitable for occasions with few fixed pages; The FragmentStatePagerAdapter is suitable for the situation where there are many pages or the page content is very complex (requiring a lot of memory)!

2. Use of pageradapter

Let's first introduce the most common PagerAdapter. If you want to use this PagerAdapter, you need to rewrite the following four methods: of course, this is only an official suggestion. In fact, we only need to rewrite getCount() and isViewFromObject()~

  • getCount(): get the number of views in the viewpager
  • destroyItem(): removes a page at a given location. It is the responsibility of the adapter to remove this view from the container. This is to ensure that the view can be removed when finishUpdate(viewGroup) returns.

The other two methods involve the contents of a key:

  • instantiateItem(): ① add the view of a given location to the ViewGroup (container) and create and display it. ② return an Object(key) representing the new page. Usually, you can directly return to the view itself. Of course, you can also customize your own key, but the key should correspond to each view one by one
  • isViewFromObject(): judge whether the Key returned by the instantiateItem(ViewGroup, int) function and a page view represent the same view (that is, whether they correspond, and the corresponding represents the same View). Usually, we directly write return view == object!

Usage example 1: simplest usage

Operation effect diagram:

Key part code:

OK, the code is also very simple: first, the layout of each View is in triplicate. The other two views are the same:

view_one.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FFBA55"
    android:gravity="center"
    android:orientation="vertical">
</span><span class="tag">&lt;TextView</span><span class="pln">
    </span><span class="atn">android:layout_width</span><span class="pun">=</span><span class="atv">"wrap_content"</span><span class="pln">
    </span><span class="atn">android:layout_height</span><span class="pun">=</span><span class="atv">"wrap_content"</span><span class="pln">
    </span><span class="atn">android:text</span><span class="pun">=</span><span class="atv">"first Page"</span><span class="pln">
    </span><span class="atn">android:textColor</span><span class="pun">=</span><span class="atv">"#000000"</span><span class="pln">
    </span><span class="atn">android:textSize</span><span class="pun">=</span><span class="atv">"18sp"</span><span class="pln">
    </span><span class="atn">android:textStyle</span><span class="pun">=</span><span class="atv">"bold"</span><span class="pln"> </span><span class="tag">/&gt;</span><span class="pln">

</LinearLayout>

Then write a custom PagerAdapter:

MyPagerAdapter.java:

public class MyPagerAdapter extends PagerAdapter {
    private ArrayList<View> viewLists;

    public MyPagerAdapter() {
    }

    public MyPagerAdapter(ArrayList<View> viewLists) {
        super();
        this.viewLists = viewLists;
    }

    @Override
    public int getCount() {
        return viewLists.size();
    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
        return view == object;
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        container.addView(viewLists.get(position));
        return viewLists.get(position);
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        container.removeView(viewLists.get(position));
    }
}

Next, let's go to Activity, which is very similar to the ListView learned before:

OneActivity.java:

public class OneActivity extends AppCompatActivity{

    private ViewPager vpager_one;
    private ArrayList<View> aList;
    private MyPagerAdapter mAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_one);
        vpager_one = (ViewPager) findViewById(R.id.vpager_one);

        aList = new ArrayList<View>();
        LayoutInflater li = getLayoutInflater();
        aList.add(li.inflate(R.layout.view_one,null,false));
        aList.add(li.inflate(R.layout.view_two,null,false));
        aList.add(li.inflate(R.layout.view_three,null,false));
        mAdapter = new MyPagerAdapter(aList);
        vpager_one.setAdapter(mAdapter);
    }
}

OK, the key code is in the above part, which is very easy to understand~

Usage example 2: title bar - PagerTitleStrip and PagerTabStrip

It is the title that slides with the ViewPager. These two are officially provided. One is ordinary text, the other is underlined, and you can click the text to switch the page. Let's write a simple example below~

Operation effect diagram:

Key code implementation:

The only difference between the two is that the layout is different, and the others are the same:

The layout of the activity where PagerTitleStrip is located: activity_two.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
</span><span class="tag">&lt;TextView</span><span class="pln">
    </span><span class="atn">android:layout_width</span><span class="pun">=</span><span class="atv">"match_parent"</span><span class="pln">
    </span><span class="atn">android:layout_height</span><span class="pun">=</span><span class="atv">"48dp"</span><span class="pln">
    </span><span class="atn">android:background</span><span class="pun">=</span><span class="atv">"#CCFF99"</span><span class="pln">
    </span><span class="atn">android:gravity</span><span class="pun">=</span><span class="atv">"center"</span><span class="pln">
    </span><span class="atn">android:text</span><span class="pun">=</span><span class="atv">"PagerTitleStrip Effect demonstration"</span><span class="pln">
    </span><span class="atn">android:textColor</span><span class="pun">=</span><span class="atv">"#000000"</span><span class="pln">
    </span><span class="atn">android:textSize</span><span class="pun">=</span><span class="atv">"18sp"</span><span class="pln"> </span><span class="tag">/&gt;</span><span class="pln">

</span><span class="tag">&lt;android.support.v4.view.ViewPager</span><span class="pln">
    </span><span class="atn">android:id</span><span class="pun">=</span><span class="atv">"@+id/vpager_two"</span><span class="pln">
    </span><span class="atn">android:layout_width</span><span class="pun">=</span><span class="atv">"wrap_content"</span><span class="pln">
    </span><span class="atn">android:layout_height</span><span class="pun">=</span><span class="atv">"wrap_content"</span><span class="pln">
    </span><span class="atn">android:layout_gravity</span><span class="pun">=</span><span class="atv">"center"</span><span class="tag">&gt;</span><span class="pln">

    </span><span class="tag">&lt;android.support.v4.view.PagerTitleStrip</span><span class="pln">
        </span><span class="atn">android:id</span><span class="pun">=</span><span class="atv">"@+id/pagertitle"</span><span class="pln">
        </span><span class="atn">android:layout_width</span><span class="pun">=</span><span class="atv">"wrap_content"</span><span class="pln">
        </span><span class="atn">android:layout_height</span><span class="pun">=</span><span class="atv">"40dp"</span><span class="pln">
        </span><span class="atn">android:layout_gravity</span><span class="pun">=</span><span class="atv">"top"</span><span class="pln">
        </span><span class="atn">android:textColor</span><span class="pun">=</span><span class="atv">"#FFFFFF"</span><span class="pln"> </span><span class="tag">/&gt;</span><span class="pln">

</android.support.v4.view.ViewPager>

</LinearLayout>

The layout of PagerTabStrip:

activity_three.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="35dp"
        android:background="#C0C080"
        android:gravity="center"
        android:text="PagerTabStrip Effect demonstration"
        android:textSize="18sp" />
        
    <android.support.v4.view.ViewPager
        android:id="@+id/vpager_three"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center">

        <android.support.v4.view.PagerTabStrip
            android:id="@+id/pagertitle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="top" />
     </android.support.v4.view.ViewPager>
</LinearLayout>

The next two are the same. Let's write a custom PagerAdapter first. In addition to the four methods rewritten above, we need to rewrite another method: getPageTitle(). The ~ code for setting the title is as follows:

MyPagerAdapter2.java:

/**
 * Created by Jay on 2015/10/8 0008.
 */
public class MyPagerAdapter2 extends PagerAdapter {
    private ArrayList<View> viewLists;
    private ArrayList<String> titleLists;

    public MyPagerAdapter2() {}
    public MyPagerAdapter2(ArrayList<View> viewLists,ArrayList<String> titleLists)
    {
        this.viewLists = viewLists;
        this.titleLists = titleLists;
    }

    @Override
    public int getCount() {
        return viewLists.size();
    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
        return view == object;
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        container.addView(viewLists.get(position));
        return viewLists.get(position);
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        container.removeView(viewLists.get(position));
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return titleLists.get(position);
    }
}

Finally, there is the Activity part, both of which are the same:

TwoActivity.java:

/**
 * Created by Jay on 2015/10/8 0008.
 */
public class TwoActivity extends AppCompatActivity {

    private ViewPager vpager_two;
    private ArrayList<View> aList;
    private ArrayList<String> sList;
    private MyPagerAdapter2 mAdapter;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_two);
        vpager_two = (ViewPager) findViewById(R.id.vpager_two);
        aList = new ArrayList<View>();
        LayoutInflater li = getLayoutInflater();
        aList.add(li.inflate(R.layout.view_one,null,false));
        aList.add(li.inflate(R.layout.view_two,null,false));
        aList.add(li.inflate(R.layout.view_three, null, false));
        sList = new ArrayList<String>();
        sList.add("Orange");
        sList.add("Pale yellow");
        sList.add("Light brown");
        mAdapter = new MyPagerAdapter2(aList,sList);
        vpager_two.setAdapter(mAdapter);
    }
}

Well, it's very simple. If you have any questions, just take a look at the demo yourself~

Use example 3: ViewPager to achieve the effect of TabHost:

Of course, example 2 is often just useless. In actual development, we may need to customize this title bar. Let's write a simple example to realize the effect of TabHost. If you don't know what TabHost is, please see the effect picture!

Operation effect diagram:

Implement logical parsing:

Let's explain the logic to achieve the above effect, and then paste the code:

The first is the layout: a LinearLayout at the top is wrapped with three textviews, the weight attribute is 1, and then followed by an ImageView with a slider. We set the width to match_parent; At the bottom is our ViewPager. There may be two properties you don't know. One is: flipInterval: This specifies the time interval between View animations!
persistentDrawingCache: sets the drawing cache policy of the control. There are four optional values:

  • none: do not save the drawing cache in memory;
  • Animation: save only the animation drawing cache;
  • Scrolling: only save the scrolling effect drawing cache;
  • All: all drawing caches should be saved in memory;
You can use two at the same time, such as animation|scrolling~

Layout code: activity_four.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/LinearLayout1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="48dp"
        android:background="#FFFFFF">

        <TextView
            android:id="@+id/tv_one"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:layout_weight="1.0"
            android:gravity="center"
            android:text="Orange"
            android:textColor="#000000" />

        <TextView
            android:id="@+id/tv_two"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:layout_weight="1.0"
            android:gravity="center"
            android:text="Pale yellow"
            android:textColor="#000000" />

        <TextView
            android:id="@+id/tv_three"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:layout_weight="1.0"
            android:gravity="center"
            android:text="Light brown"
            android:textColor="#000000" />
    </LinearLayout>

    <ImageView
        android:id="@+id/img_cursor"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:scaleType="matrix"
        android:src="@mipmap/line" />

    <android.support.v4.view.ViewPager
        android:id="@+id/vpager_four"
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        android:layout_gravity="center"
        android:layout_weight="1.0"
        android:flipInterval="30"
        android:persistentDrawingCache="animation" />

</LinearLayout> 

Next, let's go to our Activity. Let's think about it:

  • Step 1: we need to center our moving block under the first text. Here we need to calculate the offset: first obtain the picture width pw, and then obtain the screen width sw. The calculation method is very simple:
    Offset = ((sw / 3)-pw) / 2 / / screen width / 3 - picture width, and then divide by 2, about!
    Then we call setImageMatrix to set the current position of the slider:
    At the same time, we also calculate the moving distance of the slider when switching one page and two pages, which is very simple:
    one = offset * 2 + pw;
    two = one * 2;

  • Step 2: when we slide the page, our Slider needs to move. We need to add an OnPageChangeListener event for ViewPager. We need to make a judgment on the page after sliding, and record which page we are on before sliding. We have drawn a diagram below, which may be easier to understand!

PS: I haven't written for a long time. The words are ugly. It's good to see them clearly. The words are ugly and beautiful. Ha ha~

Well, if you still can't understand it, just draw the picture yourself. The code is as follows:

FourActvitiy.java:

/**
 * Created by Jay on 2015/10/8 0008.
 */
public class FourActivity extends AppCompatActivity implements View.OnClickListener,
        ViewPager.OnPageChangeListener {

    private ViewPager vpager_four;
    private ImageView img_cursor;
    private TextView tv_one;
    private TextView tv_two;
    private TextView tv_three;

    private ArrayList<View> listViews;
    private int offset = 0;//Offset of moving bar picture
    private int currIndex = 0;//The number of the current page
    private int bmpWidth;// Length of moving bar picture
    private int one = 0; //The distance that the moving bar slides one page
    private int two = 0; //The distance the slider moves two pages

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_four);
        initViews();
    }


    private void initViews() {
        vpager_four = (ViewPager) findViewById(R.id.vpager_four);
        tv_one = (TextView) findViewById(R.id.tv_one);
        tv_two = (TextView) findViewById(R.id.tv_two);
        tv_three = (TextView) findViewById(R.id.tv_three);
        img_cursor = (ImageView) findViewById(R.id.img_cursor);

        //Settings for underline Animation:
        bmpWidth = BitmapFactory.decodeResource(getResources(), R.mipmap.line).getWidth();// Get picture width
        DisplayMetrics dm = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(dm);
        int screenW = dm.widthPixels;// Get resolution width
        offset = (screenW / 3 - bmpWidth) / 2;// Calculate offset
        Matrix matrix = new Matrix();
        matrix.postTranslate(offset, 0);
        img_cursor.setImageMatrix(matrix);// Set animation initial position
        //Moving distance
        one = offset * 2 + bmpWidth;// The offset that moves a page, such as 1 - > 2, or 2 - > 3
        two = one * 2;// Move the offset of two pages, such as 1 directly skip 3


        //Fill the View into the ViewPager, and set the click event and page switching event at the same time
        listViews = new ArrayList<View>();
        LayoutInflater mInflater = getLayoutInflater();
        listViews.add(mInflater.inflate(R.layout.view_one, null, false));
        listViews.add(mInflater.inflate(R.layout.view_two, null, false));
        listViews.add(mInflater.inflate(R.layout.view_three, null, false));
        vpager_four.setAdapter(new MyPagerAdapter(listViews));
        vpager_four.setCurrentItem(0);          //Set the current page of ViewPager, counting from 0

        tv_one.setOnClickListener(this);
        tv_two.setOnClickListener(this);
        tv_three.setOnClickListener(this);

        vpager_four.addOnPageChangeListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.tv_one:
                vpager_four.setCurrentItem(0);
                break;
            case R.id.tv_two:
                vpager_four.setCurrentItem(1);
                break;
            case R.id.tv_three:
                vpager_four.setCurrentItem(2);
                break;
        }
    }

    @Override
    public void onPageSelected(int index) {
        Animation animation = null;
        switch (index) {
            case 0:
                if (currIndex == 1) {
                    animation = new TranslateAnimation(one, 0, 0, 0);
                } else if (currIndex == 2) {
                    animation = new TranslateAnimation(two, 0, 0, 0);
                }
                break;
            case 1:
                if (currIndex == 0) {
                    animation = new TranslateAnimation(offset, one, 0, 0);
                } else if (currIndex == 2) {
                    animation = new TranslateAnimation(two, one, 0, 0);
                }
                break;
            case 2:
                if (currIndex == 0) {
                    animation = new TranslateAnimation(offset, two, 0, 0);
                } else if (currIndex == 1) {
                    animation = new TranslateAnimation(one, two, 0, 0);
                }
                break;
        }
        currIndex = index;
        animation.setFillAfter(true);// true indicates that the picture stops at the end of the animation
        animation.setDuration(300); //Set the animation time to 300 milliseconds
        img_cursor.startAnimation(animation);//Start animation
    }

    @Override
    public void onPageScrollStateChanged(int i) {

    }

    @Override
    public void onPageScrolled(int i, float v, int i1) {

    }
}

Well, you may not be familiar with animation. It's okay. We'll take you in the next chapter~

3. Example of viewpager combined with Fragment

Well, when we explained Fragment earlier, we explained an example: Basic introduction to Android tutorial - 5.2.4 Fragment example elaboration - bottom navigation bar + ViewPager sliding switch page I won't elaborate here. If you are interested, just click the link~

4. Download code examples

ViewPagerDemo.zip

Summary of this section:

As for ViewPager, it is not mentioned in some places due to space limitations. For others, you need to consult the documents yourself~

In addition, as mentioned above, we will explain the animation of ViewPager in the next chapter! OK, that's all~

Well, before the national day, I said that I would complete the whole series during the National Day holiday, but I didn't write one. I'm really sorry Because my sister came to play, So, you know~

Keywords: Java Android

Added by jerastraub on Tue, 25 Jan 2022 21:27:24 +0200