Files
photobooth-app/13_FIX_UX.md

8.1 KiB

🎨 KẾ HOẠCH THAY ĐỔI UX: GIẢI PHÓNG TẦM NHÌN VỚI THÀNH TRƯỢT THƯỚC ĐO TỐI GIẢN

Mục tiêu: Loại bỏ hoàn toàn khối Card View mờ lọt lòng cũ. Khi người dùng nhấn giữ một Preset (hoặc nhấn nút Edit nhỏ), khu vực điều khiển camera phía dưới sẽ biến đổi thành thanh tinh chỉnh thông số 3 tầng dạng nén tối giản bám sát theo sơ đồ ảnh image.png.


📐 1. Tái Cấu Trúc Lại XML Layout Hạ Tầng (activity_main.xml)

Bảng Sliders cũ sẽ bị xóa bỏ. Thay vào đó, ta tạo một cụm layout tinh chỉnh mới có tên layoutTimelineEditor. Mặc định cụm này sẽ ẩn đi (android:visibility="gone"). Khi kích hoạt, nó sẽ đè lên vị trí của bảng chọn Frame/Preset và Control Panel cũ.

<!-- KHU VỰC ĐIỀU KHIỂN CHỈNH SỬA ẢNH (Thay thế Control Panel khi nhấn giữ preset) -->
<ConstraintLayout
    android:id="@+id/layoutTimelineEditor"
    android:layout_width="match_parent"
    android:layout_height="180dp"
    android:background="#000000"
    android:visibility="gone"
    app:layout_bottom_toBottomOf="parent">

    <!-- TẦNG 1: THANH TRƯỢT THƯỚC ĐO ĐỘC ĐÁO (RULER SLIDER) -->
    <!-- Hiển thị vạch chia số và kim chỉ vị trí trung tâm 0 như ảnh image_44676a.png -->
    <FrameLayout
        android:id="@+id/rulerContainer"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_marginTop="8dp"
        app:layout_constraintTop_toTopOf="parent">

        <!-- Các vạch thước kẻ nhỏ (Có thể tự vẽ bằng Custom View hoặc dùng ảnh lặp) -->
        <ImageView
            android:id="@+id/imgRulerTicks"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:src="@drawable/bg_ruler_ticks"
            android:scaleType="centerCrop" />

        <!-- Kim chỉ số 0 màu cam chính giữa cố định -->
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:layout_gravity="center">
            <TextView
                android:id="@+id/tvRulerValue"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="0"
                android:textColor="#FF9800"
                android:textSize="12sp"
                android:textStyle="bold"
                android:layout_gravity="center_horizontal"/>
            <ImageView
                android:layout_width="12dp"
                android:layout_height="12dp"
                android:src="@drawable/ic_arrow_down_orange"
                android:layout_gravity="center_horizontal"/>
        </LinearLayout>
    </FrameLayout>

    <!-- TẦNG 2: PHẦN HIỂN THỊ ICON CÁC THUỘC TÍNH (HORIZONTAL LIST) -->
    <!-- Chứa danh sách cuộn ngang các nút: Brightness, Contrast, Saturation... -->
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rvAttributeIcons"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:orientation="horizontal"
        android:paddingStart="16dp"
        android:paddingEnd="16dp"
        app:layout_constraintTop_toBottomOf="@id/rulerContainer"
        app:layout_constraintBottom_toTopOf="@id/layoutEditorActionButtons" />

    <!-- TẦNG 3: THANH THAO TÁC HOÀN THÀNH (HỦY / ĐỒNG Ý) -->
    <RelativeLayout
        android:id="@+id/layoutEditorActionButtons"
        android:layout_width="match_parent"
        android:layout_height="48dp"
        android:paddingStart="20dp"
        android:paddingEnd="20dp"
        app:layout_constraintBottom_toBottomOf="parent">

        <!-- Nút X (Hủy bỏ các thông số vừa chỉnh) -->
        <ImageButton
            android:id="@+id/btnEditorClose"
            android:layout_width="36dp"
            android:layout_height="36dp"
            android:background="@null"
            android:src="@drawable/ic_close_white"
            android:layout_alignParentStart="true"
            android:layout_centerVertical="true"/>

        <!-- Nút Dấu Tích (Đồng ý để lưu preset) -->
        <ImageButton
            android:id="@+id/btnEditorCheck"
            android:layout_width="36dp"
            android:layout_height="36dp"
            android:background="@null"
            android:src="@drawable/ic_check_white"
            android:layout_alignParentEnd="true"
            android:layout_centerVertical="true"/>
    </RelativeLayout>

</ConstraintLayout>


💻 2. Kịch Bản Thao Tác Cử Chỉ Động (Kotlin Logic)

Hệ thống điều khiển cử chỉ mới sẽ hoạt động dựa trên hai tương tác chính: Chọn thuộc tínhBắt sự kiện vuốt trên ảnh.

🔹 2.1. Quản lý Thuộc tính được Chọn (Tầng 2)

Tạo một biến Enum để nhận biết người dùng đang nhấn vào thuộc tính nào trong rvAttributeIcons:

enum class EditAttribute { BRIGHTNESS, CONTRAST, SATURATION, VIBRANCE, TEMPERATURE }
private var currentAttribute = EditAttribute.BRIGHTNESS // Mặc định là độ sáng

Khi người dùng bấm chọn một icon trong danh sách, icon đó sẽ đổi sang màu cam để thông báo trạng thái hoạt động, đồng thời nạp giá trị hiện tại của thuộc tính đó lên kim chỉ thước đo tvRulerValue.

🔹 2.2. Cơ chế Swipe trên ảnh để đổi giá trị (Gesture Detector)

Đính kèm một bộ lắng nghe cử chỉ vuốt chạm (OnTouchListener) trực tiếp vào khung hình Camera chính (cameraContainer).

  1. Bước 1: Bắt sự kiện Touch: Chạm màn hình. Người dùng đặt ngón tay lên vùng hiển thị ảnh và vuốt sang trái hoặc phải. Hệ thống ghi lại điểm chạm đầu tiên startX.

  2. Bước 2: Quy đổi độ dời sang giá trị số: Tính khoảng cách. Khi ngón tay di chuyển, tính toán khoảng cách chênh lệch deltaX = currentX - startX. Quy đổi khoảng cách pixel này sang dải giá trị nguyên từ -100 đến +100.

  3. Bước 3: Dịch chuyển vạch thước kẻ & Áp bộ lọc: Cập nhật đồ họa. Dựa vào giá trị deltaX:

  • Di chuyển tịnh tiến hình ảnh vạch thước imgRulerTicks sang trái hoặc phải để tạo cảm giác trượt thực tế.
  • Cập nhật số trên kim chỉ tvRulerValue.
  • Gán giá trị mới vào thuộc tính đang chọn (ví dụ: editingPreset.basic.brightness) và ra lệnh cho GPU render cập nhật màu sắc ngay lập tức trên ảnh.

💾 3. Lưu Preset Với Tên Mới Khi Ấn Đồng Ý

Khi người dùng nhấn vào nút Dấu tích (Đồng ý để lưu preset) ở góc dưới bên phải màn hình chỉnh sửa:

  1. App sẽ hiển thị một thông báo popup (Dialog) gọn gàng hỏi tên bộ lọc mới.
  2. Tiến hành đóng gói file JSON chứa toàn bộ 14 thông số hoàn chỉnh.
  3. Ẩn thanh layoutTimelineEditor, mở lại giao diện Control Panel chụp ảnh thông thường, đồng thời tải lại thanh timeline chính để preset mới xuất hiện ngay lập tức.

📅 4. Các Đầu Việc Cần Làm Ngay (Checklist)

  • Chuẩn bị Icon Đơn Sắc: Tìm và sử dụng các icon vector SVG tiêu chuẩn và tối giản cho nút Độ sáng (Mặt trời), Tương phản (Hình tròn chia đôi), Bão hòa (Vòng tròn màu)... để sử dụng cho các nút
  • Thiết lập Custom View cho Thước Đo: Code logic dịch chuyển tọa độ X (translationX) của hình ảnh vạch thước imgRulerTicks đồng bộ theo tỷ lệ ngón tay vuốt trên màn hình.
  • Gán cử chỉ gỡ lỗi: Đảm bảo khi người dùng thao tác vuốt trên ảnh, các cử chỉ của hệ thống camera (như zoom bằng 2 ngón tay) tạm thời bị khóa lại để không làm nhiễu loạn quá trình chỉnh màu.