Skip to content

princegyw/ViewPagerDemo

Repository files navigation

ViewPager

ListView enables us to populate and show thousands of datum within it and it is a a vertical flip up and down. However, many of time, we need to flip horizontally. For example, we may want to make an album to show images and which enables us to flip images one by one. The final look of the project is as the snapshot showing below.

1. ViewPager

ViewPager is defined in Android android.support.v4 library. One can layout with a ViewPager as below.

<?xml version="1.0" encoding="utf-8"?>  
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:layout_width="fill_parent"  
    android:layout_height="fill_parent"  
    android:orientation="vertical" >  

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

2. ViewPagerAdapter

ViewPagerAdapter is the key class which we used to populate Item views of ViewPager. we define a ViewPagerAdapter class by extending PagerAdapter. The minimum required methods which we to override are:

instantiateItem(ViewGroup, int)
destroyItem(ViewGroup, int, Object)
getCount()
isViewFromObject(View, Object)
instantiateItem(ViewGroup, int)

Get called when need to instantiate and Item, much like getView() in ListView adapter. Besides returning the Item view, you should add the Item view as child view to the param ViewGroup.

destroyItem(ViewGroup, int, Object)

Get called when flip away; recycle behavior is defined here.

getCount()

Return the number of the datum.

An example of ViewPagerAdapter
/**
 * Created by wilson on 2015/9/6.
 * An example of ViewPagerAdapter
 */
public class ViewPagerAdapter extends PagerAdapter {

    private Context mContext;
    private JSONArray mJSONArray; //data source

    private HashMap<Integer, ViewPagerItemView> mHashMap;

    public ViewPagerAdapter(Context context, JSONArray JSONArray) {
        mContext = context;
        mJSONArray = JSONArray;
        mHashMap = new HashMap<>();
    }

    @Override
    public int getCount() {
        return mJSONArray.length();
    }

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

    //call when need to instantiate and Item, much like getView() in ListView adapter
    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        Log.d("gyw", "ViewPagerAdapter::instantiateItem(); position:" + position);
        ViewPagerItemView itemView;
        if (mHashMap.containsKey(position)) { //view is cached but bitmap maybe recycled
            itemView = mHashMap.get(position);
            itemView.reload();
        } else {
            itemView = new ViewPagerItemView(mContext);
            try {
                JSONObject jsonObject = mJSONArray.getJSONObject(position);
                itemView.setData(jsonObject);
            } catch (JSONException e) {
                e.printStackTrace();
            }

            mHashMap.put(position, itemView);
            container.addView(itemView);
        }
        return  itemView;
    }

    //call when flip away; recycle behavior is defined here
    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        Log.d("gyw", "ViewPagerAdapter::destroyItem(); position:" + position);
        ((ViewPagerItemView) object).recycle();
    }
}

3. OnPageChangeListener Interface

As inheriting onPageChangeListener, three methods must be overwritten.

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

}

@Override
public void onPageSelected(int i) {
    //This method will be invoked when a new page becomes selected.
}

@Override
public void onPageScrollStateChanged(int i) {

}

Here is an example of How to set OnPageChangeListener within MainActivity.

public class MainActivity extends AppCompatActivity
    implements ViewPager.OnPageChangeListener{

    private static final int ALBUM_NUM = 12;

    private static final int[] ALBUM_RES = {
            R.drawable.dog1, R.drawable.dog2, R.drawable.dog3, R.drawable.dog4,
            R.drawable.dog5, R.drawable.dog6, R.drawable.dog7, R.drawable.dog8,
            R.drawable.dog9, R.drawable.dog10, R.drawable.dog11, R.drawable.dog12,

    };

    private ViewPager mViewPager;
    private ViewPagerAdapter mViewPagerAdapter;
    private LinearLayout mLinearLayout;

    private ImageView[] indicators;

    private JSONArray mJSONArray;

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

        setupDataSources();

        mViewPager = (ViewPager) findViewById(R.id.viewpager);
        mViewPagerAdapter = new ViewPagerAdapter(this, mJSONArray);

        mLinearLayout = (LinearLayout) findViewById(R.id.viewGroup);
        initialSetImageIndicators();

        mViewPager.setAdapter(mViewPagerAdapter);
        mViewPager.setOnPageChangeListener(this);
    }

    private void setupDataSources() {
        mJSONArray = new JSONArray();
        for (int i = 0; i < ALBUM_NUM; ++i) {
            JSONObject object = new JSONObject();
            try {
                object.put("id", ALBUM_RES[i % ALBUM_RES.length]);
                object.put("name", "Image dog" + i);
                mJSONArray.put(object);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    }

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

    }

    @Override
    public void onPageSelected(int i) {
        setImageIndicators(i);
    }

    @Override
    public void onPageScrollStateChanged(int i) {

    }

    private void initialSetImageIndicators() {
        indicators = new ImageView[ALBUM_NUM];
        for (int i = 0; i < ALBUM_NUM; ++i) {
            ImageView imageView = new ImageView(this);
            if (i == 0) {
                imageView.setImageResource(R.drawable.indicator_select);
            } else {
                imageView.setImageResource(R.drawable.indicator_idle);
            }
            LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
            lp.leftMargin = 5;
            lp.rightMargin = 5;
            indicators[i] = imageView;
            mLinearLayout.addView(imageView, lp);
        }
    }

    private void setImageIndicators(int pos) {
        for (int i = 0; i < ALBUM_NUM; ++i) {
            if (i == pos) {
                indicators[i].setImageResource(R.drawable.indicator_select);
            } else {
                indicators[i].setImageResource(R.drawable.indicator_idle);
            }
        }
    }
}

Tips: Even though we recycled the bitmap objects both in Java layer and C layer. Hoever, GC won't be sure to execute promptly thus you still may receive OutOfMemory(OOM) error. To avoid this, a lazy way is to declare to use android:largeHeap="true" in your application in AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.wilson.viewpagerdemo" >
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme"
        android:largeHeap="true">
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

Tips: Cache Strategy of ViewPager is to cache three views in total. Android will instantiate the next Item view and keep the previous Item view.
cache log

5. Source Code

https://github.com/princegyw/ViewPagerDemo

About

An image album which shows the basic use of ViewPager

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages