[Android] Flex Recyclerview create tab menu
Bài đăng này đã không được cập nhật trong 7 năm
I.Giới thiệu Minh sẽ hướng dẫn các bạn tạo 1 thanh Tab menu uốn cong 1 cách đơn giản nhất với việc sử dụng RecycleView. Tab menu của mình có các tính chất sau đây + Tab trung tâm sẽ được chọn làm giá trị hiển thị. + Uốn cong theo vòng cung + Scale tại vị trí trung tâm + Scroll trái phải để chọn tab + Click trái phải để chọn tab
demo: https://j.gifs.com/KZOMw8.gif
II.Các thực hiện
-
Sử dụng 1 thư viện để đính ghim vị trí trung tâm, và scale vị trí trung tâm
- Mình dùng thằng này: https://github.com/BCsl/GalleryLayoutManager
- Thêm đúng 1 câu lệnh đơn giản để add lib
dependencies { compile 'github.hellocsl:GalleryLayoutManager:{lastest-release-version}' }
-
Scale và uốn cong theo vị trí trung tâm
- Tận dụng lớp Transformer chúng ta sẽ tính được độ di chuyển sang trái sang phải dựa vào đó để scale phần tử ở chính giữa
- Ở đây fraction nhận các giá trị (-1 0 1)
- Khi đã Scale phần tử ở giữa sẽ làm cho phần tử đó to ra và chiếm diện tích lớn hơn, vì thế để cân bằng cho giao diện chúng ta setTranslationX lệch trái, lệch phải tương ứng với giá trị đã Scale ra.
- Để uống cong mình setTranslationY công thức tính đường cong (dy = (radius - (radius * radius) / (float) Math.sqrt(radius * radius + dx * dx)) toán lớp 9 gì đó ^^. Về cơ bản uốn cong là di chuyển item theo trục Y, item trung tâm dịch chuyển lớn nhất, rồi di chuyển tương tự với các item bên cạnh trung tâm, theo 1 tỷ lệ hợp lý để được độ cong hoàn thiện
- Công thức mình viết bên dưới các bạn tự suy luận
public class ScaleTransformer implements CircleLayoutManager.ItemTransformer { public final float SCALE = ChapterTabView.SCALE; float dx = 0; float dy = 0; private float radius = 0; @Override public void transformItem(CircleLayoutManager layoutManager, View item, float fraction) { int width = item.getWidth(); int height = item.getHeight(); radius = layoutManager.getWidth() * ChapterTabView.RADIUS_RATIO; dx = item.getX() - layoutManager.getWidth() / 2 + width / 2; dy = (radius - (radius * radius) / (float) Math.sqrt(radius * radius + dx * dx)); item.setPivotX(width / 2.f); item.setPivotY(height / 2f); float scale = 1 - SCALE * Math.abs(fraction); item.setScaleX(scale + SCALE); item.setScaleY(scale + SCALE); if (fraction < 0) { item.setTranslationX(-((1 - scale) * width / 2.0f)); } if (fraction > 0) { item.setTranslationX(((1 - scale) * width / 2.0f)); } item.setTranslationY(dy); } }
-
Thao tác di chuyển scroll, click item
- Việc cố đinh ghim lại 1 phần tử ở giữa mình đã dùng thằng GalleryLayoutManager nó đã hỗ trợ việc đó.
- Để thao tác với menu tab cần các hàm cơ bản sau
-
Tính vị trí của item chính giữa: item giữa sẽ có ( leftX < giữa màn hình < rightX )
private int getPositionCenter() { int center = recyclerViewManga.getWidth() / 2; for (int i = 0; i < recyclerViewManga.getChildCount(); i++) { if (recyclerViewManga.getChildAt(i).getX() < center && recyclerViewManga.getChildAt(i).getX() + recyclerViewManga.getChildAt(i).getWidth() > center) { return i; } } return 0; }
-
Scroll đến vị trí trung tâm, hàm này để thực hiện việc di chuyển đến tab trung tâm bằng cách click đến item bất kỳ. Tính toán khoản cách từ item được click đên trung tâm rồi thực hiện di chuyển
private void scrollCenter(View view) { int widthView = view.getWidth(); int center = recyclerViewManga.getWidth() / 2; float X = view.getX(); float scale = widthView - widthView * SCALE; if (X > center + widthView / 2) { recyclerViewManga.smoothScrollBy((int) -(center - X - scale / 2), 0); } else { if (X < center - widthView / 2 - scale / 2) { recyclerViewManga.smoothScrollBy((int) -(center - (X + widthView) + scale / 2), 0); } } }
-
Để điều khiển từ xa, không cần phải thao tác trên màn hình, mình viết thêm 1 hàm di chuyển đến item tương ứng hay là lựa chọn item đó làm vị trí trung tâm
public void scrollToPosition(int position) { int positionCenter = getPositionCenter(); if (positionCenter + 2 > recyclerViewManga.getChildCount()) { return; } View viewStart = recyclerViewManga.getChildAt(positionCenter + 1); View viewEnd = recyclerViewManga.getChildAt(positionCenter + 2); float distance = (viewEnd.getX() - viewStart.getX()); int width = viewStart.getWidth(); int center = recyclerViewManga.getWidth() / 2; float dx = viewStart.getX() + ((position - 1) * distance); float scale = width - width * SCALE; recyclerViewManga.smoothScrollBy((int) -(center - dx - scale / 2), 0, interpolator); }
-
IV.Kết Thúc - Chỉ vài công thức đơn giản mình đã custom được 1 cái tab view theo ý muốn - Các bạn có thể áp dụng cách thực thi như vậy để có thể tuỳ ý điều khiển hiển thị view của mình - Mình code nhám cái demo cho các bạn tham khảo - Demo: https://github.com/Dattienbtd/tabmenu - Xin cảm ơn các bạn đã đọc.
All rights reserved