+1

[Android] Flex Recyclerview create tab menu

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

  1. Sử dụng 1 thư viện để đính ghim vị trí trung tâm, và scale vị trí trung tâm

        dependencies {
            compile 'github.hellocsl:GalleryLayoutManager:{lastest-release-version}'
        }
    
  2. 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);
            }
    }
    
  3. 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

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí