Files

15 KiB

Dưới đây là kế hoạch hoàn thiện toàn bộ danh sách các thanh kéo (Sliders) trong bảng Floating Card mờ cho tệp cấu hình JSON đầy đủ của bạn. Chúng ta sẽ đưa tất cả 14 thông số chia theo đúng 4 nhóm cấu trúc của tệp cấu hình vào trong giao diện cuộn dọc của ScrollView.


📐 1. Cấu Trúc Đầy Đủ Cho Layout XML (activity_main.xml)

Thay thế phần nội dung bên trong LinearLayout của bảng Floating Card (nằm dưới tiêu đề) để bổ sung đầy đủ tất cả các thanh kéo, phân chia theo từng nhóm trực quan giúp người dùng dễ thao tác.

<!-- Đặt bên trong LinearLayout của bảng Floating Card mờ (Lớp 3 của cameraContainer) -->
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <!-- ================= NHÓM 1: CƠ BẢN (BASIC ADJUSTMENTS) ================= -->
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="ĐIỀU CHỈNH CƠ BẢN"
        android:textColor="#FF9800"
        android:textStyle="bold"
        android:textSize="11sp"
        android:layout_marginTop="8dp"
        android:layout_marginBottom="4dp"/>

    <!-- Brightness -->
    <TextView android:id="@+id/tvLabelBrightness" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#FFFFFF" android:textSize="11sp" android:text="Brightness (Độ sáng): 0.00"/>
    <com.google.android.material.slider.Slider android:id="@+id/sliderBrightness" android:layout_width="match_parent" android:layout_height="wrap_content" android:valueFrom="-1.0" android:valueTo="1.0" app:thumbColor="#FF9800" app:trackColorActive="#FF9800"/>

    <!-- Contrast -->
    <TextView android:id="@+id/tvLabelContrast" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#FFFFFF" android:textSize="11sp" android:text="Contrast (Tương phản): 0.00"/>
    <com.google.android.material.slider.Slider android:id="@+id/sliderContrast" android:layout_width="match_parent" android:layout_height="wrap_content" android:valueFrom="-1.0" android:valueTo="1.0" app:thumbColor="#FF9800" app:trackColorActive="#FF9800"/>

    <!-- Saturation -->
    <TextView android:id="@+id/tvLabelSaturation" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#FFFFFF" android:textSize="11sp" android:text="Saturation (Bão hòa màu): 0.00"/>
    <com.google.android.material.slider.Slider android:id="@+id/sliderSaturation" android:layout_width="match_parent" android:layout_height="wrap_content" android:valueFrom="-1.0" android:valueTo="1.0" app:thumbColor="#FF9800" app:trackColorActive="#FF9800"/>

    <!-- Vibrance -->
    <TextView android:id="@+id/tvLabelVibrance" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#FFFFFF" android:textSize="11sp" android:text="Vibrance (Bão hòa thông minh): 0.00"/>
    <com.google.android.material.slider.Slider android:id="@+id/sliderVibrance" android:layout_width="match_parent" android:layout_height="wrap_content" android:valueFrom="-1.0" android:valueTo="1.0" app:thumbColor="#FF9800" app:trackColorActive="#FF9800"/>

    <!-- Temperature -->
    <TextView android:id="@+id/tvLabelTemperature" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#FFFFFF" android:textSize="11sp" android:text="Temperature (Nhiệt màu): 0.00"/>
    <com.google.android.material.slider.Slider android:id="@+id/sliderTemperature" android:layout_width="match_parent" android:layout_height="wrap_content" android:valueFrom="-1.0" android:valueTo="1.0" app:thumbColor="#FF9800" app:trackColorActive="#FF9800"/>

    <!-- Tint -->
    <TextView android:id="@+id/tvLabelTint" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#FFFFFF" android:textSize="11sp" android:text="Tint (Sắc độ hồng/xanh): 0.00"/>
    <com.google.android.material.slider.Slider android:id="@+id/sliderTint" android:layout_width="match_parent" android:layout_height="wrap_content" android:valueFrom="-1.0" android:valueTo="1.0" app:thumbColor="#FF9800" app:trackColorActive="#FF9800"/>


    <!-- ================= NHÓM 2: NÂNG CAO (ADVANCED EFFECTS) ================= -->
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="HIỆU ỨNG NÂNG CAO"
        android:textColor="#FF9800"
        android:textStyle="bold"
        android:textSize="11sp"
        android:layout_marginTop="12dp"
        android:layout_marginBottom="4dp"/>

    <!-- Clarity -->
    <TextView android:id="@+id/tvLabelClarity" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#FFFFFF" android:textSize="11sp" android:text="Clarity (Độ rõ nét vùng trung tính): 0.00"/>
    <com.google.android.material.slider.Slider android:id="@+id/sliderClarity" android:layout_width="match_parent" android:layout_height="wrap_content" android:valueFrom="-1.0" android:valueTo="1.0" app:thumbColor="#FF9800" app:trackColorActive="#FF9800"/>

    <!-- Dehaze -->
    <TextView android:id="@+id/tvLabelDehaze" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#FFFFFF" android:textSize="11sp" android:text="Dehaze (Độ trong suốt / Sương mù): 0.00"/>
    <com.google.android.material.slider.Slider android:id="@+id/sliderDehaze" android:layout_width="match_parent" android:layout_height="wrap_content" android:valueFrom="-1.0" android:valueTo="1.0" app:thumbColor="#FF9800" app:trackColorActive="#FF9800"/>

    <!-- Vignette Amount -->
    <TextView android:id="@+id/tvLabelVignetteAmount" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#FFFFFF" android:textSize="11sp" android:text="Vignette Amount (Bo tối góc): 0.00"/>
    <!-- Hiệu ứng bo tối góc đi từ 0.0 (Không bo) đến 1.0 (Bo đen tối đa) -->
    <com.google.android.material.slider.Slider android:id="@+id/sliderVignetteAmount" android:layout_width="match_parent" android:layout_height="wrap_content" android:valueFrom="0.0" android:valueTo="1.0" app:thumbColor="#FF9800" app:trackColorActive="#FF9800"/>


    <!-- ================= NHÓM 3: GIẢ LẬP ĐƯỜNG CONG MÀU (TONE CURVE EMULATION) ================= -->
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="GIẢ LẬP TONE CURVE &amp; MÀU VÙNG TỐI"
        android:textColor="#FF9800"
        android:textStyle="bold"
        android:textSize="11sp"
        android:layout_marginTop="12dp"
        android:layout_marginBottom="4dp"/>

    <!-- Faded Black Level -->
    <TextView android:id="@+id/tvLabelFadedBlack" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#FFFFFF" android:textSize="11sp" android:text="Faded Black Level (Độ mờ vùng đen): 0.00"/>
    <com.google.android.material.slider.Slider android:id="@+id/sliderFadedBlack" android:layout_width="match_parent" android:layout_height="wrap_content" android:valueFrom="0.0" android:valueTo="1.0" app:thumbColor="#FF9800" app:trackColorActive="#FF9800"/>

    <!-- Shadows Tint R -->
    <TextView android:id="@+id/tvLabelShadowsTintR" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#FFFFFF" android:textSize="11sp" android:text="Shadows Tint R (Sắc Đỏ vùng tối): 0.00"/>
    <com.google.android.material.slider.Slider android:id="@+id/sliderShadowsTintR" android:layout_width="match_parent" android:layout_height="wrap_content" android:valueFrom="0.0" android:valueTo="1.0" app:thumbColor="#FF9800" app:trackColorActive="#FF9800"/>

    <!-- Shadows Tint G -->
    <TextView android:id="@+id/tvLabelShadowsTintG" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#FFFFFF" android:textSize="11sp" android:text="Shadows Tint G (Sắc Lục vùng tối): 0.00"/>
    <com.google.android.material.slider.Slider android:id="@+id/sliderShadowsTintG" android:layout_width="match_parent" android:layout_height="wrap_content" android:valueFrom="0.0" android:valueTo="1.0" app:thumbColor="#FF9800" app:trackColorActive="#FF9800"/>

    <!-- Shadows Tint B -->
    <TextView android:id="@+id/tvLabelShadowsTintB" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#FFFFFF" android:textSize="11sp" android:text="Shadows Tint B (Sắc Lam vùng tối): 0.00"/>
    <com.google.android.material.slider.Slider android:id="@+id/sliderShadowsTintB" android:layout_width="match_parent" android:layout_height="wrap_content" android:valueFrom="0.0" android:valueTo="1.0" app:thumbColor="#FF9800" app:trackColorActive="#FF9800"/>


    <!-- ================= NHÓM 4: HẠT NHIỄU PHIM (FILM GRAIN) ================= -->
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="HẠT NHIỄU PHIM"
        android:textColor="#FF9800"
        android:textStyle="bold"
        android:textSize="11sp"
        android:layout_marginTop="12dp"
        android:layout_marginBottom="4dp"/>

    <!-- Grain Amount -->
    <TextView android:id="@+id/tvLabelGrainAmount" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#FFFFFF" android:textSize="11sp" android:text="Grain Amount (Mật độ hạt): 0.00"/>
    <com.google.android.material.slider.Slider android:id="@+id/sliderGrainAmount" android:layout_width="match_parent" android:layout_height="wrap_content" android:valueFrom="0.0" android:valueTo="1.0" app:thumbColor="#FF9800" app:trackColorActive="#FF9800"/>

    <!-- Grain Size -->
    <TextView android:id="@+id/tvLabelGrainSize" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#FFFFFF" android:textSize="11sp" android:text="Grain Size (Kích thước hạt): 0.00"/>
    <com.google.android.material.slider.Slider android:id="@+id/sliderGrainSize" android:layout_width="match_parent" android:layout_height="wrap_content" android:valueFrom="0.0" android:valueTo="1.0" app:thumbColor="#FF9800" app:trackColorActive="#FF9800"/>

</LinearLayout>


💻 2. Logic Khởi Tạo & Đồng Bộ Giá Trị (Kotlin trong MainActivity.kt)

Khi người dùng mở bảng chỉnh sửa cho preset, hàm openAdvancedSliders sẽ thực hiện gán các giá trị ban đầu từ tệp JSON lên các thanh Slider phần cứng đồng thời thiết lập lắng nghe cử chỉ:

fun openAdvancedSliders(selectedPreset: ColorPreset) {
    editingPreset = selectedPreset.deepCopy() // Nhân bản dữ liệu để tránh ghi đè bản gốc

    binding.tvEditPresetName.text = "Chỉnh sửa: ${editingPreset!!.name}"

    // 1. Nạp dữ liệu Nhóm Basic
    binding.sliderBrightness.value = editingPreset!!.basic.brightness
    binding.sliderContrast.value = editingPreset!!.basic.contrast
    binding.sliderSaturation.value = editingPreset!!.basic.saturation
    binding.sliderVibrance.value = editingPreset!!.basic.vibrance
    binding.sliderTemperature.value = editingPreset!!.basic.temperature
    binding.sliderTint.value = editingPreset!!.basic.tint

    // 2. Nạp dữ liệu Nhóm Advanced
    binding.sliderClarity.value = editingPreset!!.advanced.clarity
    binding.sliderDehaze.value = editingPreset!!.advanced.dehaze
    binding.sliderVignetteAmount.value = editingPreset!!.advanced.vignetteAmount

    // 3. Nạp dữ liệu Nhóm Tone Curve Emulation
    binding.sliderFadedBlack.value = editingPreset!!.toneCurve.fadedBlackLevel
    binding.sliderShadowsTintR.value = editingPreset!!.toneCurve.shadowsTintR
    binding.sliderShadowsTintG.value = editingPreset!!.toneCurve.shadowsTintG
    binding.sliderShadowsTintB.value = editingPreset!!.toneCurve.shadowsTintB

    // 4. Nạp dữ liệu Nhóm Film Grain
    binding.sliderGrainAmount.value = editingPreset!!.grain.grainAmount
    binding.sliderGrainSize.value = editingPreset!!.grain.grainSize

    // Gọi hàm thiết lập sự kiện lắng nghe chuyển động cho toàn bộ Sliders
    setupSliderListeners()

    // Hiển thị Card mờ floating lọt lòng màn hình camera như ảnh image_2be399.jpg
    binding.cardAdvancedSliders.visibility = View.VISIBLE
}


🔄 3. Cơ Chế Cập Nhật Giá Trị Thời Gian Thực (Real-time Pipeline)

Viết một hàm tập trung gán sự kiện thay đổi (addOnChangeListener) cho tất cả các thanh kéo. Khi con trỏ dịch chuyển, chữ số nhãn text sẽ đổi ngay lập tức và đẩy cấu trúc Object mới sang GPU xử lý trực tiếp trên kính ngắm.

private fun setupSliderListeners() {
    
    // Ví dụ gán cho Brightness
    binding.sliderBrightness.addOnChangeListener { _, value, _ ->
        binding.tvLabelBrightness.text = String.format("Brightness (Độ sáng): %.2f", value)
        editingPreset?.basic?.brightness = value
        applyLiveFilterToCamera(editingPreset) // Đẩy ma trận màu sang GPU render
    }

    // Ví dụ gán cho Vibrance
    binding.sliderVibrance.addOnChangeListener { _, value, _ ->
        binding.tvLabelVibrance.text = String.format("Vibrance (Bão hòa thông minh): %.2f", value)
        editingPreset?.basic?.vibrance = value
        applyLiveFilterToCamera(editingPreset)
    }

    // Ví dụ gán cho Clarity (Nhóm Advanced)
    binding.sliderClarity.addOnChangeListener { _, value, _ ->
        binding.tvLabelClarity.text = String.format("Clarity (Độ rõ nét vùng trung tính): %.2f", value)
        editingPreset?.advanced?.clarity = value
        applyLiveFilterToCamera(editingPreset)
    }

    // Ví dụ gán cho Faded Black Level (Nhóm Tone Curve)
    binding.sliderFadedBlack.addOnChangeListener { _, value, _ ->
        binding.tvLabelFadedBlack.text = String.format("Faded Black Level (Độ mờ vùng đen): %.2f", value)
        editingPreset?.toneCurve?.fadedBlackLevel = value
        applyLiveFilterToCamera(editingPreset)
    }

    // Ví dụ gán cho Grain Amount (Nhóm Film Grain)
    binding.sliderGrainAmount.addOnChangeListener { _, value, _ ->
        binding.tvLabelGrainAmount.text = String.format("Grain Amount (Mật độ hạt): %.2f", value)
        editingPreset?.grain?.grainAmount = value
        applyLiveFilterToCamera(editingPreset)
    }

    // Thực hiện viết gán tương tự cho toàn bộ các thanh Sliders còn lại trong danh sách...
}

Bảng cấu trúc 14 thông số này sẽ tạo ra khả năng tùy biến bộ lọc ảnh mạnh mẽ không thua kém gì các bộ công cụ chỉnh ảnh phim chuyên nghiệp như VSCO hay Lightroom Mobile.