Tổng quan về NavigationTabStrip
NavigationTabStrip là một thư viện điều hướng nhẹ dành cho nền tảng Android, được thiết kế để mang lại hiệu ứng chuyển đổi mượt mà (60fps) và khả năng tùy biến cao. Thư viện này giải quyết các hạn chế của các thành phần điều hướng truyền thống bằng cách cung cấp hoạt ảnh chuyển tiếp tinh tế, hỗ trợ hai dạng chỉ báo chính (đường kẻ và chấm) và cho phép cấu hình chi tiết thông qua XML hoặc mã nguồn Java.
Cấu hình dự án và tích hợp thư viện
Để bắt đầu sử dụng thư viện, bạn cần thêm dependency vào tệp build.gradle ở cấp độ ứng dụng.
allprojects {
repositories {
maven { url 'https://jitpack.io' }
}
}
dependencies {
implementation 'com.github.devlight.navigationtabstrip:navigationtabstrip:1.0.4'
}
Thiết lập giao diện qua XML
Cách tiếp cận phổ biến nhất là khai báo trực tiếp trong tệp layout. Dưới đây là ví dụ về việc cấu hình một thanh điều hướng phía dưới với các thông số cơ bản:
<com.gigamole.navigationtabstrip.NavigationTabStrip
android:id="@+id/navigation_strip"
android:layout_width="match_parent"
android:layout_height="56dp"
android:background="#FFFFFF"
app:nts_color="#00BCD4"
app:nts_size="14sp"
app:nts_weight="4dp"
app:nts_type="line"
app:nts_gravity="bottom"
app:nts_corners_radius="2dp"
app:nts_animation_duration="350"
app:nts_active_color="#00BCD4"
app:nts_inactive_color="#B0BEC5"/>
Trong res/values/strings.xml, bạn định nghĩa các nhãn tương ứng:
<string-array name="tab_labels">
<item>Trang chủ</item>
<item>Khám phá</item>
<item>Thông báo</item>
<item>Cá nhân</item>
</string-array>
Tùy biến nâng cao với Java/Kotlin
Để có sự linh hoạt cao hơn, ví dụ như thay đổi giao diện động, bạn có thể khởi tạo và cấu hình NavigationTabStrip trực tiếp trong Activity hoặc Fragment.
NavigationTabStrip navStrip = findViewById(R.id.navigation_strip);
// Thiết lập tiêu đề
navStrip.setTitles("Nổi bật", "Thể loại", "Xếp hạng", "Tìm kiếm");
navStrip.setTabIndex(0, true);
// Cấu hình chỉ báo hình học
navStrip.setStripType(NavigationTabStrip.StripType.LINE);
navStrip.setStripGravity(NavigationTabStrip.StripGravity.BOTTOM);
navStrip.setStripWeight(4); // Độ dày chỉ báo (dp)
navStrip.setStripFactor(2.0f); // Hệ số mở rộng
navStrip.setCornersRadius(3); // Bo góc chỉ báo
// Cấu hình màu sắc và hiệu ứng
navStrip.setAnimationDuration(350);
navStrip.setInactiveColor(Color.parseColor("#90A4AE"));
navStrip.setActiveColor(Color.parseColor("#00BCD4"));
Tùy chỉnh Typeface (Font chữ)
Thư viện hỗ trợ việc thay đổi font chữ để phù hợp với ngôn ngữ thiết kế của ứng dụng.
// Sử dụng font từ assets
navStrip.setTypeface("fonts/Roboto-Medium.ttf");
// Hoặc sử dụng font hệ thống
Typeface customFont = Typeface.create("sans-serif-medium", Typeface.NORMAL);
navStrip.setTypeface(customFont);
Kết hợp với ViewPager
Việc đồng bộ hóa thanh điều hướng với ViewPager là một trường hợp sử dụng điển hình. Quy trình thực hiện được mô tả dưới đây:
ViewPager contentPager = findViewById(R.id.view_pager);
contentPager.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()) {
@Override
public Fragment getItem(int position) {
return ContentFragment.newInstance(position);
}
@Override
public int getCount() {
return 4;
}
});
// Gắn kết NavigationTabStrip với ViewPager
navStrip.setViewPager(contentPager);
// Lắng nghe sự kiện thay đổi trang
navStrip.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
// Xử lý logic khi đang cuộn
}
@Override
public void onPageSelected(int position) {
// Xử lý logic khi trang được chọn hoàn tất
}
@Override
public void onPageScrollStateChanged(int state) {
// Theo dõi trạng thái cuộn
}
});
Điều khiển dữ liệu động và Giao diện Dark Mode
Trong các ứng dụng hiện đại, dữ liệu điều hướng có thể thay đổi dựa trên quyền của người dùng hoặc ngữ cảnh.
// Cập nhật danh sách tiêu đề động
List<String> dynamicLabels = new ArrayList<>(Arrays.asList("Tab A", "Tab B", "Tab C"));
navStrip.setTitles(dynamicLabels);
// Sửa đổi một tiêu đề cụ thể
navStrip.updateTitle(1, "Danh mục mới");
// Xử lý giao diện Dark Mode
private void updateTheme(boolean isDark) {
int activeColor = isDark ? Color.parseColor("#BB86FC") : Color.parseColor("#00BCD4");
int inactiveColor = isDark ? Color.parseColor("#A0A0A0") : Color.parseColor("#B0BEC5");
int bgColor = isDark ? Color.parseColor("#121212") : Color.parseColor("#FFFFFF");
navStrip.setActiveColor(activeColor);
navStrip.setInactiveColor(inactiveColor);
navStrip.setBackgroundColor(bgColor);
}
Giải quyết vấn đề hiệu suất và Tương thích
Để đảm bảo ứng dụng vận hành trơn tru trên các thiết bị có cấu hình thấp, bạn cần chú ý đến các yếu tố sau:
- Giảm thiểu việc vẽ lại (Overdraw): Thiết lập nền trong suốt cho thanh điều hướng nếu nền của view cha đã được thiết lập.
- Tránh cập nhật liên tục: Thay vì gọi hàm thêm từng tiêu đề (ví dụ:
addTitle) trong vòng lặp, hãy thiết lập toàn bộ danh sách một lần bằngsetTitles. - Ngăn chặn rò rỉ bộ nhớ: Trong Fragment, luôn giải phóng listener khi view bị hủy.
@Override
public void onDestroyView() {
super.onDestroyView();
if (navStrip != null) {
navStrip.setOnPageChangeListener(null);
navStrip.setViewPager(null);
}
}
Đánh giá và Lựa chọn giải pháp thay thế
Mặc dù NavigationTabStrip cung cấp nhiều tính năng hữu ích, người phát triển cần lưu ý rằng dự án này hiện tại không còn được duy trì tích cực. Dưới đây là so sánh với các giải pháp chính thống khác:
| Thư viện | Ưu điểm | Nhược điểm | Đề xuất dùng |
|---|---|---|---|
| NavigationTabStrip | Animation mượt, dễ tùy biến hiệu ứng | Không còn cập nhật, tương thích AndroidX cần kiểm tra | Dự án nhỏ, cần hiệu ứng đặc thù |
| TabLayout (Material) | Chính thức, hỗ trợ tốt Material Design 3 | Tùy biến phức tạp đôi khi khó khăn | Hầu hết các dự án mới |
| BottomNavigationView | Tích hợp sẵn badge, tuân thủ chuẩn UX | Hạn chế về tùy biến animation | Điều hướng chính cấp 1 (Top level) |
Đối với các dự án mới bắt đầu, nên ưu tiên sử dụng com.google.android.material.tabs.TabLayout hoặc BottomNavigationView để đảm bảo tính ổn định lâu dài. Tuy nhiên, nếu cần duy trì hoặc tích hợp nhanh hiệu ứng chuyển động đặc thù của NavigationTabStrip, bạn có thể copy mã nguồn vào dự án (Fork) để tự bảo trì.