Hướng Dẫn Thực Chiến Thành Phần RcImage Trong HarmonyOS6 - Phần 2

Tiếp theo bài viết trước: Hướng Dẫn Thực Chiến Thành Phần RcImage Trong HarmonyOS6 - Phần 1

Sáu: Thực Chiến Xem Trước Hình Ảnh

6.1 Kiến Trúc Chức Năng Xem Trước

Hệ thống xem trước hình ảnh
├─ 🔹 Cách kích hoạt
│  ├─ Nhấp vào hình ảnh
│  └─ previewable: true
│
├─ 🔹 Chế độ xem trước
│  ├─ Xem trước một hình
│  └─ Xem trước danh sách (hỗ trợ chuyển đổi)
│
├─ 🔹 Tính năng tương tác
│  ├─ Điều khiển phóng to (+ / -)
│  ├─ Chuyển đổi hình (< / >)
│  └─ Đóng xem trước (X / lớp phủ)
│
└─ 🔹 Tùy chọn cấu hình
   ├─ Hiển thị lớp phủ
   ├─ Hiển thị nút đóng
   └─ Cài đặt phạm vi zoom

6.2 Xem Trước Một Hình Ảnh

Ứng dụng: Hình minh họa bài viết, chi tiết sản phẩm, hiển thị giấy tờ

this.TieuDeDe('Nhấp để xem (một hình)')
HinhAnh({
  nguonHinh: 'https://images.unsplash.com/photo-1506905925346-21bda4d32df4?w=800',
  rongHinh: 300,
  caoHinh: 200,
  hinhDang: 'tròn',
  banKinh: 12,
  coXemTruoc: true,
  hienThiChuThich: true,
  noiDungChuThich: 'Nhấp để xem lớn',
  khiMoXemTruoc: () => {
    console.log('Mở xem trước')
  },
  khiDongXemTruoc: () => {
    console.log('Đóng xem trước')
  }
})

Điểm kỹ thuật:

  • previewable: true Kích hoạt chức năng xem trước
  • onPreviewOpen Lắng nghe sự kiện mở xem trước
  • onPreviewClose Lắng nghe sự kiện đóng xem trước

Ví dụ thực tế - Xem trước hình minh họa bài viết:

@Builder
NoiDungBaiViet() {
  Column { space: 16 } {
    Text('Thực Chiến HarmonyOS6')
      .fontSize(24)
      .fontWeight(FontWeight.Bold)
    
    Text('Hình ảnh có thể nhấp để xem lớn')
      .fontSize(14)
      .fontColor('#909399')
    
    // Hình minh họa 1
    HinhAnh({
      nguonHinh: 'https://example.com/hinh-bai-viet-1.jpg',
      rongHinh: '100%',
      caoHinh: 250,
      hinhDang: 'tròn',
      banKinh: 12,
      coXemTruoc: true,
      hienThiChuThich: true,
      noiDungChuThich: 'Hình 1: Sơ đồ kiến trúc hệ thống'
    })
    
    Text('Nội dung chính...')
      .fontSize(16)
      .lineHeight(28)
    
    // Hình minh họa 2
    HinhAnh({
      nguonHinh: 'https://example.com/hinh-bai-viet-2.jpg',
      rongHinh: '100%',
      caoHinh: 250,
      hinhDang: 'tròn',
      banKinh: 12,
      coXemTruoc: true,
      hienThiChuThich: true,
      noiDungChuThich: 'Hình 2: Hiệu quả chạy'
    })
  }
  .width('100%')
  .padding(16)
}

6.3 Xem Trước Danh Sách Hình Ảnh (tính năng cốt lõi)

Ứng dụng: Album ảnh, nhiều hình sản phẩm, thư viện hình ảnh

this.TieuDeDe('Xem trước danh sách hình (hỗ trợ chuyển trái/phải)')
Text('Nhấp vào bất kỳ hình nào để xem, hỗ trợ zoom và chuyển đổi')
  .fontSize(14)
  .fontColor('#909399')
  .margin({ bottom: 10 })

Row { space: 10 } {
  ForEach(this.danhSachHinh, (hinh: string, index: number) => {
    HinhAnh({
      nguonHinh: hinh,
      rongHinh: 80,
      caoHinh: 80,
      hinhDang: 'tròn',
      banKinh: 8,
      kichThuocHinh: 'cover',
      coXemTruoc: true,
      danhSachXemTruoc: this.danhSachHinh,        // Danh sách hình xem trước
      chiSoHienTai: index,                 // Chỉ số hình hiện tại
      tuyenChonXemTruoc: {
        hienThiLopPhu: true,                    // Hiển thị lớp phủ
        hienThiNutDong: true,                   // Hiển thị nút đóng
        tyLeBanDau: 1,                   // Tỷ lệ zoom ban đầu
        tyLeNhoNhat: 0.5,                     // Tỷ lệ zoom nhỏ nhất
        tyLeLonNhat: 3                        // Tỷ lệ zoom lớn nhất
      }
    })
  })
}
.width('100%')
.justifyContent(FlexAlign.SpaceAround)

Tham số quan trọng:

Tham số Loại Mô tả Giá trị mặc định
previewList string[] Danh sách hình xem trước Bắt buộc
previewIndex number Chỉ số hình hiện tại Bắt buộc
previewOptions object Đối tượng cấu hình xem trước Tùy chọn

Chi tiết cấu hình previewOptions:

Thiết lập Loại Mô tả Giá trị đề xuất
showMask boolean Hiển thị lớp phủ true
showClose boolean Hiển thị nút đóng true
initialScale number Tỷ lệ zoom ban đầu 1
minScale number Tỷ lệ zoom nhỏ nhất 0.5
maxScale number Tỷ lệ zoom lớn nhất 3

Ví dụ thực tế - Xem trước nhiều hình sản phẩm:

@State danhSachHinhSanPham: string[] = [
  'https://example.com/san-pham-1.jpg',
  'https://example.com/san-pham-2.jpg',
  'https://example.com/san-pham-3.jpg',
  'https://example.com/san-pham-4.jpg'
]
@State chiSoXemTruocHienTai: number = 0

@Builder
ThuVienSanPham() {
  Column { space: 12 } {
    // Hình chính xem trước
    HinhAnh({
      nguonHinh: this.danhSachHinhSanPham[this.chiSoXemTruocHienTai],
      rongHinh: '100%',
      caoHinh: 375,
      kichThuocHinh: 'contain',
      mauNen: '#F5F5F5',
      coXemTruoc: true,
      danhSachXemTruoc: this.danhSachHinhSanPham,
      chiSoHienTai: this.chiSoXemTruocHienTai,
      tuyenChonXemTruoc: {
        hienThiLopPhu: true,
        hienThiNutDong: true,
        tyLeBanDau: 1,
        tyLeNhoNhat: 0.5,
        tyLeLonNhat: 4  // Cho phép zoom lớn hơn cho hình sản phẩm
      }
    })
    
    // Danh sách hình thu nhỏ
    Row { space: 8 } {
      ForEach(this.danhSachHinhSanPham, (hinh: string, index: number) => {
        HinhAnh({
          nguonHinh: hinh,
          rongHinh: 60,
          caoHinh: 60,
          hinhDang: 'tròn',
          banKinh: 6,
          kichThuocHinh: 'cover',
          doDayVien: this.chiSoXemTruocHienTai === index ? 2 : 0,
          mauVien: '#409EFF',
          khiHinhDuocCham: () => {
            this.chiSoXemTruocHienTai = index
          }
        })
      })
    }
    .width('100%')
    .justifyContent(FlexAlign.Start)
  }
  .width('100%')
  .padding(16)
}

6.4 Giải Thích Chức Năng Xem Trước

this.TieuDeDe('Giải thích chức năng xem trước')
Column { space: 8 } {
  this.TextThongTin('• Nhấp vào hình để mở xem trước')
  this.TextThongTin('• Nhấp vào lớp phủ hoặc nút đóng để thoát')
  this.TextThongTin('• Sử dụng nút + / - để phóng to/thu nhỏ hình')
  this.TextThongTin('• Sử dụng nút < / > để chuyển hình (chế độ danh sách)')
}
.alignItems(HorizontalAlign.Start)
.width('100%')
.padding(16)
.backgroundColor('#FFF9E6')
.borderRadius(8)

Tóm tắt tương tác:

Hành động Cách kích hoạt Chức năng
**Mở xem trước** Nhấp vào hình Vào chế độ xem trước toàn màn hình
**Đóng xem trước** Nhấp lớp phủ/nút đóng Thoát chế độ xem trước
**Phóng to** Nhấp nút + Phóng to hình theo tỷ lệ
**Thu nhỏ** Nhấp nút - Thu nhỏ hình theo tỷ lệ
**Hình trước** Nhấp nút < Chuyển sang hình trước
**Hình sau** Nhấp nút > Chuyển sang hình sau

Bảy: Thực Chiến Kiểu Dạng Viền

7.1 Tham Số Hệ Thống Viền

Tham số Loại Mô tả Giá trị mặc định
rcBorderWidth number Độ rộng viền 0
rcBorderColor string Màu viền '#000000'
rcBorderStyle BorderStyle Kiểu viền Solid
rcPadding number Đệm trong 0

7.2 Viền Đường Thẳng

Ứng dụng: Thẻ sản phẩm, nhấn mạnh

this.TieuDeDe('Có viền')
HinhAnh({
  nguonHinh: 'https://images.unsplash.com/photo-1506905925346-21bda4d32df4?w=500',
  rongHinh: 300,
  caoHinh: 200,
  doDayVien: 2,
  mauVien: '#409eff',
  kieuVien: BorderStyle.Solid
})

Quy tắc thiết kế:

  • Độ rộng viền: 1-3px
  • Màu sắc: Màu thương hiệu hoặc màu chủ đề
  • Phù hợp cho hình cần nhấn mạnh

7.3 Viền Đường Gạch Ngang

Ứng dụng: Bản nháp, trạng thái chờ tải

this.TieuDeDe('Viền gạch ngang')
HinhAnh({
  nguonHinh: 'https://images.unsplash.com/photo-1469474968028-56623f02e42e?w=500',
  rongHinh: 300,
  caoHinh: 200,
  doDayVien: 2,
  mauVien: '#67c23a',
  kieuVien: BorderStyle.Dashed
})

Ví dụ thực tế - Chỗ tải lên hình:

@Builder
ChoTaiLenHinh() {
  Stack() {
    HinhAnh({
      nguonHinh: this.hinhDuocTai || $r('app.media.upload_placeholder'),
      rongHinh: 200,
      caoHinh: 200,
      doDayVien: 2,
      mauVien: '#DCDFE6',
      kieuVien: BorderStyle.Dashed,
      khiHinhDuocCham: () => {
        this.hienThiChonHinh()
      }
    })
    
    if (!this.hinhDuocTai) {
      Column { space: 8 } {
        Text('+')
          .fontSize(48)
          .fontColor('#C0C4CC')
        Text('Nhấp để tải lên')
          .fontSize(14)
          .fontColor('#909399')
      }
    }
  }
}

7.4 Viền Điểm

Ứng dụng: Thiết kế đặc biệt, hiệu ứng trang trí

this.TieuDeDe('Viền điểm')
HinhAnh({
  nguonHinh: 'https://images.unsplash.com/photo-1501785888041-af3ef285b470?w=500',
  rongHinh: 300,
  caoHinh: 200,
  doDayVien: 3,
  mauVien: '#e6a23c',
  kieuVien: BorderStyle.Dotted
})

7.5 Hình Tròn + Viền

Ứng dụng: Avatar người dùng VIP, nhận dạng đặc biệt

this.TieuDeDe('Hình tròn + viền')
HinhAnh({
  nguonHinh: 'https://images.unsplash.com/photo-1518173946687-a4c8892bbd9f?w=500',
  rongHinh: 150,
  caoHinh: 150,
  hinhDang: 'circle',
  kichThuocHinh: 'cover',
  doDayVien: 4,
  mauVien: '#f56c6c',
  kieuVien: BorderStyle.Solid
})

Ví dụ thực tế - Avatar người dùng VIP:

@Builder
AvatarNguoiDungVIP(thongTinNguoiDung: ThongTinNguoiDung) {
  Stack { alignContent: Alignment.BottomEnd } {
    HinhAnh({
      nguonHinh: thongTinNguoiDung.avatarUrl,
      rongHinh: 80,
      caoHinh: 80,
      hinhDang: 'circle',
      kichThuocHinh: 'cover',
      doDayVien: 3,
      mauVien: thongTinNguoiDung.laVIP ? '#FFD700' : '#E0E0E0',
      kieuVien: BorderStyle.Solid
    })
    
    if (thongTinNguoiDung.laVIP) {
      Text('VIP')
        .fontSize(10)
        .fontColor('#FFFFFF')
        .backgroundColor('#FFD700')
        .padding({ left: 4, right: 4, top: 2, bottom: 2 })
        .borderRadius(4)
        .offset({ x: -5, y: -5 })
    }
  }
}

7.6 Góc Tròn + Viền + Nền

Ứng dụng: Thiết kế thẻ, hiển thị tinh tế

this.TieuDeDe('Góc tròn + viền + nền')
HinhAnh({
  nguonHinh: 'https://images.unsplash.com/photo-1506905925346-21bda4d32df4?w=500',
  rongHinh: 300,
  caoHinh: 200,
  hinhDang: 'round',
  banKinh: 16,
  mauNen: '#E8F4FF',
  doDayVien: 2,
  mauVien: '#409eff',
  kieuVien: BorderStyle.Solid,
  rcPadding: 8
})

Điểm nổi bật thiết kế:

  • Sử dụng rcPadding tạo hiệu ứng đệm trong
  • bgColorrcBorderColor tương hỗ
  • Phù hợp cho hiển thị sản phẩm cao cấp

7.7 Thực Chiến Sự Kiện Nhấp

Ứng dụng: Phản hồi tương tác, hiển thị hộp thoại

this.TieuDeDe('Sự kiện nhấp')
HinhAnh({
  nguonHinh: 'https://images.unsplash.com/photo-1469474968028-56623f02e42e?w=500',
  rongHinh: 300,
  caoHinh: 200,
  hinhDang: 'round',
  banKinh: 12,
  hienThiChuThich: true,
  noiDungChuThich: 'Nhấp vào tôi',
  khiHinhDuocCham: () => {
    this.getUIContext().getPromptAction().showDialog({
      title: 'Thông báo',
      message: 'Hình ảnh đã được nhấn!',
      buttons: [
        {
          text: 'Đồng ý',
          color: '#409EFF'
        }
      ]
    })
  }
})

Ví dụ thực tế - Menu thao tác hình ảnh:

@Builder
HinhAnhCoMenu(duongDanHinh: string) {
  HinhAnh({
    nguonHinh: duongDanHinh,
    rongHinh: 300,
    caoHinh: 200,
    hinhDang: 'round',
    banKinh: 12,
    khiHinhDuocCham: () => {
      this.getUIContext().getPromptAction().showActionMenu({
        title: 'Thao tác hình',
        buttons: [
          {
            text: 'Lưu vào thư viện',
            color: '#409EFF'
          },
          {
            text: 'Chia sẻ bạn bè',
            color: '#67C23A'
          },
          {
            text: 'Xóa hình',
            color: '#F56C6C'
          },
          {
            text: 'Hủy',
            color: '#909399'
          }
        ]
      })
    }
  })
}

Mười Một: Các Vấn Đề Thường Gặp và Giải Pháp

11.1 Vấn Đề Hiển Thị Hình Ảnh

Vấn đề 1: Hình ảnh bị méo

Nguyên nhân: Chọn chế độ điền không phù hợp

Giải pháp:

// ❌ Sai: Sử dụng fill gây méo
HinhAnh({
  nguonHinh: avatarNguoiDung,
  rongHinh: 100,
  caoHinh: 100,
  kichThuocHinh: 'fill'
})

// ✅ Đúng: Sử dụng cover giữ tỷ lệ
HinhAnh({
  nguonHinh: avatarNguoiDung,
  rongHinh: 100,
  caoHinh: 100,
  kichThuocHinh: 'cover',
  hinhDang: 'circle'
})

Vấn đề 2: Hình tròn hiển thị không đầy đủ

Nguyên nhân: Không sử dụng chế độ điền cover

Giải pháp:

HinhAnh({
  nguonHinh: avatar,
  rongHinh: 80,
  caoHinh: 80,
  hinhDang: 'circle',
  kichThuocHinh: 'cover'  // Bắt buộc phải đặt
})

11.2 Vấn Đề Hiệu Năng

Vấn đề 3: Danh sách dài bị giật lag

Nguyên nhân: Tải quá nhiều hình ảnh cùng lúc

Giải pháp:

List() {
  LazyForEach(this.nguonHinhDuLieu, (hinh: string, index: number) => {
    ListItem() {
      HinhAnh({
        nguonHinh: hinh + '?w=200', // Tải kích thước nhỏ
        rongHinh: 200,
        caoHinh: 200
      })
    }
  })
}
.cachedCount(5) // Lưu 5 mục

Vấn đề 4: Bộ nhớ sử dụng cao

Nguyên nhân: Bộ nhớ cache hình ảnh không được giải phóng

Giải pháp:

aboutToDisappear() {
  this.danhSachHinh = []
  this.boNhoHinhAnh.clear()
}

11.3 Vấn Đề Tương Tác

Vấn đề 5: Chuyển đổi danh sách xem trước thất bại

Nguyên nhân: previewIndex không được đặt đúng

Giải pháp:

ForEach(this.hinhs, (hinh: string, index: number) => {
  HinhAnh({
    nguonHinh: hinh,
    coXemTruoc: true,
    danhSachXemTruoc: this.hinhs,
    chiSoHienTai: index  // Phải truyền chỉ số hiện tại
  })
})

11.4 Danh Sách Thực Hành Tốt Nhất

Bắt buộc tuân thủ
Quy tắc Mô tả Lý do
**Chỉ định kích thước** Luôn đặt imageWidth và imageHeight Tránh rung lưới
**Xử lý lỗi** Mở showError cho hình mạng Nâng cao trải nghiệm
**Chế độ điền** Chọn imageFit phù hợp Tránh méo
**Cấu hình xem trước** Danh sách xem trước phải đặt previewList Trải nghiệm đầy đủ
️ Đề xuất tuân thủ
Đề xuất Mô tả Lợi ích
**Sử dụng góc tròn** Dùng góc 8-16 để tăng tính thẩm mỹ Phong cách thiết kế hiện đại
**Trạng thái tải** Mở showLoading để thông báo người dùng Giảm lo lắng chờ đợi
**Trang trí viền** Thêm viền cho hình quan trọng Phân cấp rõ ràng
**Phản hồi nhấp** Cung cấp sự kiện nhấp cho hình tương tác Trải nghiệm tương tác đầy đủ
️ Cấm thực hiện
Cấm Lý do Giải pháp thay thế
**Không đặt kích thước** Gây rối loạn bố cục Chỉ định rõ ràng rộng cao
**Tải hình quá lớn** Rủi ro tràn bộ nhớ Sử dụng CDN cắt ảnh
**Lạm dụng xem trước** Ảnh hưởng hiệu năng Chỉ kích hoạt khi cần
**Bỏ qua lỗi** Trống ảnh phá vỡ trải nghiệm Mở showError

Phụ Lục: Tài Liệu Nhanh

A.1 Bảng Tham Số Thường Dùng

Tham số Loại Giá trị thường dùng Tần suất sử dụng
imageSrc string/Resource URL / $r() ⭐⭐⭐⭐⭐
imageWidth number/string 200 / '100%' ⭐⭐⭐⭐⭐
imageHeight number 200 ⭐⭐⭐⭐⭐
imageFit string cover / contain ⭐⭐⭐⭐
imageShape string square / circle / round ⭐⭐⭐⭐
imageRadius number 8 / 16 ⭐⭐⭐
previewable boolean true / false ⭐⭐⭐
showLoading boolean true ⭐⭐⭐
showError boolean true ⭐⭐⭐

A.2 Đoạn Mã Cho Tình Huển Điển Hình

Avatar người dùng
HinhAnh({
  nguonHinh: duongDanAvatar,
  rongHinh: 48,
  caoHinh: 48,
  hinhDang: 'circle',
  kichThuocHinh: 'cover'
})

Hình thu nhỏ sản phẩm
HinhAnh({
  nguonHinh: hinhSanPham,
  rongHinh: 120,
  caoHinh: 120,
  hinhDang: 'round',
  banKinh: 8,
  kichThuocHinh: 'cover',
  coXemTruoc: true
})

Hình minh họa bài viết
HinhAnh({
  nguonHinh: hinhBaiViet,
  rongHinh: '100%',
  caoHinh: 250,
  hinhDang: 'round',
  banKinh: 12,
  coXemTruoc: true,
  hienThiChuThich: true,
  noiDungChuThich: 'Mô tả hình'
})

Kết Luận

Tài liệu thực chiến này được biên soạn dựa trên kinh nghiệm dự án thực tế, bao gồm 6 kịch bản cốt lõi của thành phần RcImage trong HarmonyOS6, trình bày đầy đủ phương pháp sử dụng RcImage.

Thẻ: HarmonyOS RcImage UI Components Mobile development cross-platform

Đăng vào ngày 4 tháng 6 lúc 21:10