killapp/Assets/Scripts/UI/Components/QRCodeGenerator.cs
2026-05-18 08:42:33 +08:00

269 lines
8.4 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using UnityEngine;
using UnityEngine.UI;
using ZXing;
using ZXing.QrCode;
using ZXing.Common;
using ZXing.Rendering;
using ZXing.QrCode.Internal;
namespace Kill.UI.Components
{
/// <summary>
/// 二维码生成器
/// 支持生成用户ID等文本的二维码图片
/// </summary>
public class QRCodeGenerator : MonoBehaviour
{
[Header("显示组件")]
public RawImage qrCodeImage; // 显示二维码的RawImage
public int textureSize = 256; // 二维码图片尺寸(像素)
[Header("二维码样式")]
public Color foregroundColor = Color.black; // 前景色(二维码颜色)
public Color backgroundColor = Color.white; // 背景色
public int margin = 2; // 边距
// 当前生成的纹理
private Texture2D currentTexture;
// void Start()
// {
// Generate("123123");
// }
/// <summary>
/// 生成二维码
/// </summary>
/// <param name="content">二维码内容如用户ID</param>
public void Generate(string content)
{
if (string.IsNullOrEmpty(content))
{
Debug.LogWarning("[QRCodeGenerator] 内容为空,无法生成二维码");
return;
}
// 生成二维码纹理
Texture2D texture = GenerateQRCodeTexture(content, textureSize, textureSize);
if (texture != null)
{
// 清理旧纹理
if (currentTexture != null)
{
Destroy(currentTexture);
}
currentTexture = texture;
// 显示二维码
if (qrCodeImage != null)
{
qrCodeImage.texture = currentTexture;
qrCodeImage.SetNativeSize();
// 可以在这里调整显示大小
float scale = Mathf.Min(
qrCodeImage.rectTransform.rect.width / textureSize,
qrCodeImage.rectTransform.rect.height / textureSize
);
qrCodeImage.rectTransform.sizeDelta = new Vector2(textureSize * scale, textureSize * scale);
}
Debug.Log($"[QRCodeGenerator] 二维码生成成功: {content}");
}
}
/// <summary>
/// 生成用户ID二维码
/// </summary>
/// <param name="userId">用户ID</param>
public void GenerateUserQRCode(string userId)
{
// 可以添加前缀标识这是用户ID
string content = $"USER:{userId}";
Generate(content);
}
/// <summary>
/// 生成设备分享二维码
/// </summary>
/// <param name="deviceId">设备ID</param>
/// <param name="userId">用户ID</param>
public void GenerateDeviceShareQRCode(string deviceId, string userId)
{
// 格式: DEVICE:设备ID:用户ID
string content = $"DEVICE:{deviceId}:{userId}";
Generate(content);
}
/// <summary>
/// 生成二维码纹理
/// </summary>
private Texture2D GenerateQRCodeTexture(string content, int width, int height)
{
try
{
// 配置二维码参数
var options = new QrCodeEncodingOptions
{
Width = width,
Height = height,
Margin = margin,
CharacterSet = "UTF-8",
ErrorCorrection = ErrorCorrectionLevel.M // 中等容错率
};
// 创建写入器
var writer = new BarcodeWriter<Texture2D>
{
Format = BarcodeFormat.QR_CODE,
Options = options,
Renderer = new ZXingRender()
};
// 生成二维码
Texture2D texture = writer.Write(content);
// 应用颜色
ApplyColors(texture, foregroundColor, backgroundColor);
return texture;
}
catch (System.Exception ex)
{
Debug.LogError($"[QRCodeGenerator] 生成二维码失败: {ex.Message}");
return null;
}
}
/// <summary>
/// 应用自定义颜色到二维码
/// </summary>
private void ApplyColors(Texture2D texture, Color foreground, Color background)
{
Color32[] pixels = texture.GetPixels32();
for (int i = 0; i < pixels.Length; i++)
{
// 黑色像素变前景色,白色像素变背景色
if (pixels[i].r < 128)
{
pixels[i] = foreground;
}
else
{
pixels[i] = background;
}
}
texture.SetPixels32(pixels);
texture.Apply();
}
/// <summary>
/// 保存二维码到相册(移动端)
/// </summary>
public void SaveToGallery(string filename = "QRCode")
{
if (currentTexture == null)
{
Debug.LogWarning("[QRCodeGenerator] 没有可保存的二维码");
return;
}
// 将纹理转为PNG字节
byte[] bytes = currentTexture.EncodeToPNG();
// 保存到相册
#if UNITY_ANDROID
string path = $"/storage/emulated/0/DCIM/{filename}.png";
System.IO.File.WriteAllBytes(path, bytes);
// 刷新相册
using (AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
{
using (AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity"))
{
using (AndroidJavaObject mediaScanner = new AndroidJavaObject("android.media.MediaScannerConnection"))
{
mediaScanner.CallStatic("scanFile", currentActivity, new string[] { path }, null, null);
}
}
}
#elif UNITY_IOS
// iOS 使用原生插件保存
// NativeGallery.SaveImageToGallery(currentTexture, "QRCode", filename);
#else
string path = System.IO.Path.Combine(Application.persistentDataPath, $"{filename}.png");
System.IO.File.WriteAllBytes(path, bytes);
Debug.Log($"[QRCodeGenerator] 二维码已保存到: {path}");
#endif
ToastUI.Show("二维码已保存到相册");
}
/// <summary>
/// 获取当前二维码纹理
/// </summary>
public Texture2D GetCurrentTexture()
{
return currentTexture;
}
/// <summary>
/// 清除二维码
/// </summary>
public void Clear()
{
if (currentTexture != null)
{
Destroy(currentTexture);
currentTexture = null;
}
if (qrCodeImage != null)
{
qrCodeImage.texture = null;
}
}
private void OnDestroy()
{
Clear();
}
}
/// <summary>
/// ZXing 纹理渲染器
/// </summary>
public class ZXingRender : IBarcodeRenderer<Texture2D>
{
public Texture2D Render(BitMatrix matrix, BarcodeFormat format, string content)
{
return Render(matrix, format, content, null);
}
public Texture2D Render(BitMatrix matrix, BarcodeFormat format, string content, EncodingOptions options)
{
int width = matrix.Width;
int height = matrix.Height;
Texture2D texture = new Texture2D(width, height, TextureFormat.RGBA32, false);
Color32[] pixels = new Color32[width * height];
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
pixels[y * width + x] = matrix[x, y] ? Color.black : Color.white;
}
}
texture.SetPixels32(pixels);
texture.Apply();
texture.filterMode = FilterMode.Point; // 保持像素清晰
return texture;
}
}
}