ViewPager nằm trong bộ thư viện android.support.v4.view.ViewPager. Ta thường gặp ViewPager trên rất nhiều ứng dụng và thường thao tác với ViewPager bằng cách trượt qua trái, trượt qua phải để chuyển giữa các layout. Và cụ thể thì ta thường gặp ViewPager trên ứng dụng Thư viện ảnh,danh bạ. v.v.v. “Hướng dẫn ViewPager trong Android” sẽ gồm 3 phần dựa trên 3 cách xây dựng adapter.
Overview
ViewPager thường được sử dụng với Fragment.Android ViewPager cung cấp cho ta 3 cách để xây dựng adapter tùy vào từng trường hợp mà ta nên chọn cách phù hợp nhất :
1. extend FragmentPagerAdapter: Khi chúng ta có số lượng ít các fragment và có thể là các fragment tĩnh. Vì mỗi fragment khi hiển thị sẽ được lưu data trong bộ nhớ cache. Khi ta đã chuyển qua các fragment khác thì FragmentPagerAdapter sẽ gọi hàm detach Fragment này vào 1 transaction, thay vì gọi hàm remove fragment có nghĩa là những fragment instances vẫn tồn tại trong FragmentManager, có thể làm đầy bộ nhớ, ảnh hưởng đến hiệu suất của ứng dụng nếu chúng ta sử dụng nhiều Fragment trong ViewPager.
2. extend FragmentStatePagerAdapter: Khi ta phải sử dụng nhiều fragment động. FragmentStatePagerAdapter có thể lưu data trong savedInstanceState và destroyView khi mà fragment không còn hiển thị. Khi người dùng back lại với fragment đó dữ liệu sẽ restore từ BundleFragment. Cũng vì vậy mà nó không ảnh hưởng đến quá hiệu suât của ứng dụng khi mà chúng ta có 1 số lượng lớn các Fragment.
Tóm lại sự khác biệt của FragmentPagerAdapter và FragmentStatePagerAdapter ở cách xử lý dữ liệu khi mà ta chuyển đổi giữa các fragment
FragmentPagerAdapter : thì trong hàm destroyItem() nó chỉ gọi hàm detach() :
|
|
if (mCurTransaction == null) {
mCurTransaction = mFragmentManager.beginTransaction();
}
mCurTransaction.detach((Fragment)object); //fragment này sẽ không được remove mà
nó vẫn còn tồn tại trong Transaction của FragmentManager
|
FragmentStatePagerAdapter: trong hàm destroyItem() nó sẽ gọi hàm remove() sau khi gọi hàm mSaveState()
1
2
3
4
5
6
7
8
9
10
11
12
|
Fragment fragment = (Fragment) object;
if (mCurTransaction == null) {
mCurTransaction = mFragmentManager.beginTransaction();
}
while (mSavedState.size() <= position) {
mSavedState.add(null);
}
mSavedState.set(position, fragment.isAdded()
? mFragmentManager.saveFragmentInstanceState(fragment) : null);
mFragments.set(position, null);
mCurTransaction.remove(fragment); //Fragment sẽ được remove hoàn toàn khỏi FragmentManager.
|
3. extend PagerAdapter: Khi mà ta chỉ cần sử dụng Views thuần đơn giản thay vì sử dụng fragments phức tạp. VD: Trong ứng dụng gallary ta chỉ cần trượt qua trái hoặc qua phải để chuyển qua lại các hình ảnh, với cấu trúc đó ta nên sử extend PagerAdapter.
Chúng ta sẽ bắt đầu với PagerAdpater
1. Layout
Đầu tiên ta cần layout: activity_main.xml để chứa
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="kenhlaptrinh.net.viewpager_klt.MainActivity">
<android.support.v4.view.ViewPager
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/viewPager" />
</RelativeLayout>
|
Tiếp theo là 1 layout item để chứa item của ViewPager:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:fitsSystemWindows="true"
android:layout_height="match_parent">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/img_pager_item"
android:scaleType="fitXY"
android:adjustViewBounds="true"
android:clickable="false"/>
</LinearLayout>
|
2. MainActivity.java
Trong hàm OnCreate() chúng ta cần khai báo 1 đối tượng ViewPager và trỏ nó tới @+id/viewpager
|
|
public class MainActivity extends Activity {
private ViewPager mPager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mPager = (ViewPager) findViewById(R.id.viewPager);
}
}
|
Trong ứng dụng này chúng ta sẽ cần 1 danh sách hình ảnh từ trong Resource Drawable để load lên ViewPager (Chú ý : chúng ta chỉ trọn được hình ảnh có độ phân giải nhỏ hơn 720*1200 nếu không bạn sẽ bị lỗi OutOfMemory).
|
|
private int[] mImageResources = {
R.drawable.anh1,
R.drawable.anh2,
R.drawable.anh3,
R.drawable.anh4
};
|
Và giờ chúng ta cần phải khởi tạo đối tượng ViewPagerAdapter và truyền vào danh sách Images và Activity cha. Dưới đây là code tất cả trong class MainActivity.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
import android.app.Activity;
import android.support.v4.view.ViewPager;
import android.os.Bundle;
public class MainActivity extends Activity {
private ViewPager mPager;
private ViewPagerAdapter mPagerAdapter;
private int[] mImageResources = {
R.drawable.anh1,
R.drawable.anh2,
R.drawable.anh3,
R.drawable.anh4
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mPager = (ViewPager) findViewById(R.id.viewPager);
mPagerAdapter = new ViewPagerAdapter(this, mImageResources);
mPager.setAdapter(mPagerAdapter);
}
}
|
3. ViewPagerAdapter.java
Trong MainActivity hàm OnCreate() chúng ta mới khởi tạo 1 ViewPagerAdapter với mImageResources là danh sách hình ảnh vậy chúng ta sẽ làm gì với danh sách hình ảnh này ?
|
|
new ViewPagerAdapter(this, mImageResources);
|
Cũng giống như các Adapter khác công việc của Adapter sẽ là làm sao để nó duyệt qua từng phần tử của mảng dữ liệu để hiển thị nó lên View. Vậy chúng ta sẽ viết và custorm nó như sau :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
public class ViewPagerAdapter extends PagerAdapter {
private Context mContext;
private int[] mResources;
public ViewPagerAdapter(Context mContext, int[] mResources) {
this.mContext = mContext;
this.mResources = mResources;
}
@Override
public int getCount() {
return mResources.length;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
View itemView = LayoutInflater.from(mContext).inflate(R.layout.item_view, container, false);
ImageView imageView = (ImageView) itemView.findViewById(R.id.img_pager_item);
imageView.setImageResource(mResources[position]);
// imageView.setImageDrawable (container.getResources().getDrawable(mResources[position]));
container.addView(itemView);
return itemView;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
}
|
Ok. Ở đây bạn sẽ thấy chúng ta đang extend từ Class PagerAdapter. Vậy thì chúng ta sẽ phải @Overide lại các phương thức sau :
- instantiateItem(ViewGroup, int)
- destroyItem(ViewGroup, int, Object)
- getCount()
- isViewFromObject(View, Object)
instantiateItem : là method tạo page ở những cho từng position nhất định và tái sử dụng page theo từng key (position) của mảng data mResources[]. Nó tương tự các method getView hay bindViewHolder trong ListViewAdapter hoặc RecyclerViewAdapter.
getCount: method trả về số lượng phần tử mảng data hay giờ nó là số lượng view cần hiển thị lên ViewPager.
destroyItem: Xóa page từ ViewPager, ngoài ra ta có thể sử dụng hàm removeView() để xóa đi object hoặc removeViewAt() để xóa object dựa trên position.
isViewFromObject() : trả về object dựa trên instantiateItem đang hiển thị dựa vào position.
No comments:
Post a Comment