Ở các bài học trước, chúng ta đã cùng nhau tìm hiểu về cách tạo danh sách đơn giản sử dụng 2 loại View phổ biến là LISTVIEW và cao cấp hơn là RECYCLERVIEW. Chúng đều là những View hỗ trợ hiển thị danh sách mạnh, dù rằng có một số điểm khác nhau.
Bài học này chúng ta tiếp tục tìm hiểu một dạng “danh sách” đặc biệt khác là View Pager và Tab, mà các bạn thường thấy trong các ứng dụng như Viber, Zalo, các ứng dụng đọc truyện tranh,…
Nội dung
Để đọc hiểu bài này tốt nhất các bạn nên có kiến thức cơ bản về các phần:
Biết “Tab” là cái gì (trong trình duyệt mà các bạn hay dùng ý).
Trong bài học này, chúng ta sẽ cùng tìm hiểu các vấn đề:
ViewPager.
Tab trong Android và liên kết tab với ViewPager.
Khuyến mãi thêm: CoordinatorLayout.
Mại dzô!
ViewPager và FragmentPagerAdapter
Các bạn nhìn hình sau có thấy kích thích không…
(Ảnh hơi nặng)
Đó, những gì các bạn thấy nó được gọi là ViewPager, vậy ViewPager là…
Một dạng cấu trúc View trượt ngang.
Bao gồm nhiều trang, mỗi trang là một Fragment con.
Nếu như trong ListView / RecyclerView, các item muốn đổ vào ListView hay RecyclerView thì phải qua Adapter. Ở đây ta có thể coi như mỗi Fragment chính là một Item, và Adapter ở đây được gọi là FragmentPagerAdapter.
Một ví dụ khác là ứng dụng lịch của Android, ở đây minh họa phiên bản 4.1:
Sau đây chúng ta cùng tìm hiểu cách tạo ra một trang tương tự, đi kèm với một thanh Tab có dạng như:
Xây dựng View Pager
Bước 1: Như thường lệ, chúng ta tạo một project mới toanh mang tên ViewPagerExamplevà chọn Empty Activity:
Bước 2: Chúng ta vẫn tạo ra một cặp MainActivity.java và activity_main.xml như thường lệ. À các bạn không cần phải tạo từng file một đâu, chúng ta tạo được cả cặp bằng cách chuột phải vào package chính (khoanh đỏ như hình dưới), chọn New > Activity > Empty Activity:
Bước 3: Ý tưởng thực hiện như sau: Chúng ta sẽ tạo ra một Activity chứa ViewPager, ViewPager chứa 3 Fragment khác nhau và có màu sắc là xanh / đỏ / vàng.
Tạo một file layout dành cho fragment có tên fragment_main.xml:
Do nội dung của Fragment không có gì đặc biệt, mặt khác nó lại là thành phần của ViewPager nên chúng ta sẽ viết Fragment dưới dạng class con của MainActivity.java. Chúng ta để class là static, nhằm tách biệt sự ràng buộc với class mẹ.
publicstaticclassPlaceholderFragmentextendsFragment {privatestaticfinal String KEY_COLOR = "key_color";
publicPlaceholderFragment() {
}
// Method static dạng singleton, cho phép tạo fragment mới, lấy tham số đầu vào để cài đặt màu sắc.publicstatic PlaceholderFragment newInstance(int color) {
PlaceholderFragment fragment = new PlaceholderFragment();
Bundle args = new Bundle();
args.putInt(KEY_COLOR, color);
fragment.setArguments(args);
return fragment;
}
@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
RelativeLayout relativeLayout = (RelativeLayout) rootView.findViewById(R.id.rl_fragment);
/**
* Số 1: Màu xanh.
* Số 2: Màu đỏ.
* Số 3: Màu vàng.
*/switch (getArguments().getInt(KEY_COLOR)) {
case1:
relativeLayout.setBackgroundColor(Color.GREEN);
break;
case2:
relativeLayout.setBackgroundColor(Color.RED);
break;
case3:
relativeLayout.setBackgroundColor(Color.YELLOW);
break;
default:
relativeLayout.setBackgroundColor(Color.GREEN);
break;
}
TextView textView = (TextView) rootView.findViewById(R.id.section_label);
textView.setText("Kteam");
return rootView;
}
}
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
38
39
40
41
42
43
44
45
46
47
48
Mình xin giải thích code một chút:
KEY_COLOR: Ở đây mình đặt dữ liệu màu sắc dưới dạng số, các giá trị được lưu dạng key-value (khóa-giá trị) trong gói dữ liệu Bundle của Android (xem lại bài INTENT & MANIFEST để hiểu thêm).
Hàm newInstance() ở đây được sử dụng thay cho constructor và cũng là để dễ hiểu hơn, đỡ phải dùng constructor cồng kềnh. Chỉ cần truyền vào tham số int color và lưu vào Bundle là đủ.
Tại hàm onCreatedView, như chúng ta đã biết, các view của fragment được khởi tạo tại đây. Vì thế chúng ta lấy con số được đưa vào Bundle khi nãy ra dùng, và ở đây đặt là:
1: Màu xanh.
2: Màu đỏ.
3: Màu vàng.
Bước 4: Chúng ta tạo tiếp một class con cũng nằm trong MainActivity.java, class này kế thừa từ Adapter dành cho ViewPager (FragmentPagerAdapter):
À giải thích từng phần như trên có lẽ các bạn sẽ thấy code hơi rời rạc nhỉ? Trả lại các bạn code đầy đủ sau khi thực hiện các bước trên của MainActivity.java nhé:
package com.howkteam.viewpagerexample;
import android.graphics.Color;
import android.os.Bundle;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import android.widget.TextView;
publicclassMainActivityextendsAppCompatActivity {private SectionsPagerAdapter mSectionsPagerAdapter;
private ViewPager mViewPager;
@OverrideprotectedvoidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
mViewPager = (ViewPager) findViewById(R.id.container);
mViewPager.setAdapter(mSectionsPagerAdapter);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(mViewPager);
}
publicstaticclassPlaceholderFragmentextendsFragment {privatestaticfinal String KEY_COLOR = "key_color";
publicPlaceholderFragment() {
}
// Method static dạng singleton, cho phép tạo fragment mới, lấy tham số đầu vào để cài đặt màu sắc.publicstatic PlaceholderFragment newInstance(int color) {
PlaceholderFragment fragment = new PlaceholderFragment();
Bundle args = new Bundle();
args.putInt(KEY_COLOR, color);
fragment.setArguments(args);
return fragment;
}
@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
RelativeLayout relativeLayout = (RelativeLayout) rootView.findViewById(R.id.rl_fragment);
/**
* Số 1: Màu xanh.
* Số 2: Màu đỏ.
* Số 3: Màu vàng.
*/switch (getArguments().getInt(KEY_COLOR)) {
case1:
relativeLayout.setBackgroundColor(Color.GREEN);
break;
case2:
relativeLayout.setBackgroundColor(Color.RED);
break;
case3:
relativeLayout.setBackgroundColor(Color.YELLOW);
break;
default:
relativeLayout.setBackgroundColor(Color.GREEN);
break;
}
TextView textView = (TextView) rootView.findViewById(R.id.section_label);
textView.setText("Kteam");
return rootView;
}
}
publicclassSectionsPagerAdapterextendsFragmentPagerAdapter {publicSectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
@Overridepublic Fragment getItem(int position) {
// position + 1 vì position bắt đầu từ số 0.return PlaceholderFragment.newInstance(position + 1);
}
@OverridepublicintgetCount() {
return3;
}
@Overridepublic CharSequence getPageTitle(int position) {
switch (position) {
case0:
return"SECTION 1";
case1:
return"SECTION 2";
case2:
return"SECTION 3";
}
returnnull;
}
}
}
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
Lúc này chúng ta chỉ việc chạy và build. Nếu như gặp lỗi lúc build thì nhiều khả năng là do bạn đã thiếu dependencies trong project. Hãy chắc rằng có 2 dòng sau trong file build.gradle trong thư mục /app
Cảm ơn các bạn đã theo dõi bài viết. Hãy để lại bình luận hoặc góp ý của mình để phát triển bài viết tốt hơn. Đừng quên “Luyện tập – Thử thách – Không ngại khó”.
Tải xuống
Tài liệu
Nhằm phục vụ mục đích học tập Offline của cộng đồng, Kteam hỗ trợ tính năng lưu trữ nội dung bài học Giao diện trượt ngang với ViewPager và Tab trong Android cơ bản dưới dạng file PDF trong link bên dưới.
Ngoài ra, bạn cũng có thể tìm thấy các tài liệu được đóng góp từ cộng đồng ở mục TÀI LIỆU trên thư viện Howkteam.com
Đừng quên like và share để ủng hộ Kteam và tác giả nhé!
Thảo luận
Nếu bạn có bất kỳ khó khăn hay thắc mắc gì về khóa học, đừng ngần ngại đặt câu hỏi trong phần bên dưới hoặc trong mục HỎI & ĐÁP trên thư viện Howkteam.com để nhận được sự hỗ trợ từ cộng đồng.
Theo mình nghĩ
Code ở trên cần bổ sung thêm các code sau mới chay được:
AndroidManifest.xml :<activity android:name="com.vuvannoi.viewpagerexample.MainActivity"
android:theme="@style/AppTheme.NoActionBar">
styles.xml:<style name="AppTheme.NoActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
anh ơi em bị lỗi ở "setSupportActionBar(toolbar);"
Caused by: java.lang.IllegalStateException: This Activity already has an action bar supplied by the window decor. Do not request Window.FEATURE_SUPPORT_ACTION_BAR and set windowActionBar to false in your theme to use a Toolbar instead.
e chạy bị lỗi dòng android:theme="@style/AppTheme.AppBarOverlay" trong activity_main a ơi, hình như cái apptheme này chưa được định nghĩa trong đây n k hiểu, e chưa biết thêm kiểu gì
làm cách nào để mình lướt màn hình theo chiều dọc thì các fragment cũng di chuyển theo chiều dọc ạ?
cho mình hỏi chút.ví dụ mình có 3 tab:tab1,tab2,tab3.
mình cho ở trong mỗi tab là một cái Button.vậy xử lí button trong các tab đó kiểu gì ạ???
Theo mình nghĩ
Code ở trên cần bổ sung thêm các code sau mới chay được:
AndroidManifest.xml :<activity android:name="com.vuvannoi.viewpagerexample.MainActivity"
android:theme="@style/AppTheme.NoActionBar">
styles.xml:<style name="AppTheme.NoActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
anh ơi em bị lỗi ở "setSupportActionBar(toolbar);"
Caused by: java.lang.IllegalStateException: This Activity already has an action bar supplied by the window decor. Do not request Window.FEATURE_SUPPORT_ACTION_BAR and set windowActionBar to false in your theme to use a Toolbar instead.
sửa làm sao anh ơi TT-TT