269 lines
8.4 KiB
C#
269 lines
8.4 KiB
C#
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;
|
||
}
|
||
}
|
||
}
|