五、删除相册中的图片

(1)制作删除图片窗口的UI

在Popup Window Canvas下新建UI>Panel,命名为Confirm,按照之前介绍的方法设置大小、位置、背景图等。(参考大小:长550宽320)
在Confirm下新建UI>Text,放到Confirm偏上居中的位置,调整大小。(参考大小:长450宽150)在Text的Text组件中输入以下文字并调整字体、字号等:
是否确定删除这张图片?
在Confirm下新建UI>Button,并复制一个,分别放到Confirm偏下左右两侧,分别命名为Yes Btn和No Btn,调整大小。在Yes Btn的子物体Text的Text组件中,输入文字“是”,在No Btn的子物体Text的Text组件中,输入文字“否”,并调整字体、字号等。
完成后的删除图片窗口UI将类似于下图:

(2)创建字典

为什么要创建字典呢?这是因为当我们点击一张图片删除它时,能直接获取到的只有这张图片的Sprite或它所在格子的信息,而我们要删除的图片是保存在本地文件夹里的png文件,我们要建立这两者之间的联系。而字典恰好有一个很棒的功能,就是它能通过Key-Value的写法将两组变量一一对应。下面就让我们一起来写一下吧!
Dictionary<String, String> dic = new Dictionary<String, String>(); //生成相册的字典(将截图文件夹中的文件名和Sprite文件名一一对应) public void ImagesDic() { dic.Clear(); for (int i = 0; i < sprites.Length; i++) { dic.Add(screenshotNames[i], sprites[i].name); } } public void CreateSprites() { ImagesDic(); }
可以看到,截图名称和Sprite名称是成对写入字典的,它们就是字典的Key和Value,我们将在删除文件时用Value(Sprite名称)来调取Key(截图名称)。ImagesDic()这个方法要在CreateSprites()结尾来调用。

(3)获得要删除的图片所在格子

通过鼠标点击检测,我们可以拿到要删除的格子名称。之前的所有脚本都是在AlbumManager这个脚本中写的,不过这个功能和相册格子的关系非常密切,所以我们在Scripts文件夹中新建一个脚本,命名为SlotHolder。然后,将它挂在所有Slot Holder上(可以先选中所有Slot Holder,然后统一添加该脚本)。将Confirm拖入Confirm Panel栏位,将Album Manger拖入Album Manager栏位,将Yes Btn拖入Confirm Button栏位,将No Btn拖入Cancel Button栏位。
下面我们来写SlotHolder脚本。
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; using System; public class SlotHolder : MonoBehaviour, IPointerClickHandler { public GameObject confirmPanel; public GameObject albumManager; GameObject selectedSlot; String selectedSlotName; public Button confirmButton; public Button cancelButton; void Start() { //给确认窗口的删除按钮(是)加上监听事件(关闭窗口) confirmButton.onClick.AddListener(CloseConfirmWindow); //给确认窗口的关闭按钮(否)加上监听事件 cancelButton.onClick.AddListener(CloseConfirmWindow); } public void OnPointerClick(PointerEventData eventData) { //单击右键呼出删除图片的确认窗口 if (eventData.button == PointerEventData.InputButton.Right && this.transform.GetChild(0).gameObject.activeInHierarchy == true) { selectedSlotName = name; albumManager.GetComponent<AlbumManager>().slotname = name; selectedSlot = GameObject.Find(selectedSlotName); OpenConfirmWindow(); } } void OpenConfirmWindow() { confirmPanel.SetActive(true); } void CloseConfirmWindow() { confirmPanel.SetActive(false); } }
注意,脚本前面要添加using UnityEngine.EventSystems的命名空间和IPointerClickHandler的接口,否则就无法使用检测所点击格子的重要功能。
这里,我们设为单击右键呼出删除图片的窗口,如果按“是”且所点击的格子中有显示的图片,则删除该格子中的图片,如果按“否”则关闭该窗口。
拿到格子信息的关键在于,OnPointerClick这个方法里有一个名为name的参数,它可以直接返回给我们所点击物体的名称。我们用这个name可以查找到格子本身,并把它赋给AlbumManager脚本中的slotname,让AlbumManager脚本也知道要删除的是哪个格子中的图片。这样,删除图片的工作就准备就绪啦。

(4)删除图片

接下来,我们再回到AlbumManager,在这个脚本中执行删除图片的操作。
GameObject slot; public string slotname; public Button deleteBtn; void Start() { //给确认窗口的删除按钮(是)加上监听事件(删除图片) deleteBtn.onClick.AddListener(DeleteTextures); } public void DeleteTextures() { //获得当前点击删除的格子 slot = GameObject.Find(slotname); //获得该格子的Sprite名称 string slotspritename = slot.transform.GetChild(0).gameObject.GetComponent<Image>().sprite.name; //从字典中获得Sprite对应的Key(截图文件名) string key = dic.FirstOrDefault(item => item.Value == slotspritename).Key; string texturepath = folderPath + key; //Debug.Log(texturepath); //关闭该格子的显示和Sprite,删除截图文件夹中的相应图片文件 slot.transform.GetChild(0).gameObject.GetComponent<Image>().sprite = null; slot.transform.GetChild(0).gameObject.SetActive(false); File.Delete(texturepath); #if UNITY_EDITOR UnityEditor.AssetDatabase.Refresh(); #endif //刷新相册图片 ReplaceImages(); }
之前,我们已经拿到了slotname,所以很轻松地就能找到它对应的slotspritename。利用之前我们做的字典,就可以从Sprite名称(value)拿到我们的key,也就是图片名称!然后再生成图片的完整路径以便删除。这里,你可以Debug一下路径名称,看看是否有误。最后,当然就是痛快地执行File.Delete了~不要忘了,最后还要刷新一下AssetDatabase和相册图片。
注意,SlotHolder脚本里给删除图片按钮“是”加的监听事件是关闭窗口,AlbumManger脚本里给删除图片按钮“是”加的监听事件才是删除图片。
另外,再给大家留一道简单的思考题。我们的脚本中,用了一句简写方法获得key,如果用foreach语句,要怎么获得这个key呢?希望看到大家的答案哦~
到这步为止的脚本如下:
AlbumManger.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; using System; using UnityEngine.UI; using System.IO; using UnityEditor; using System.Linq; public class AlbumManager : MonoBehaviour { public GameObject album; public GameObject alertWindow; GameObject slot; public Button albumCloseBtn; public Button alertBtn; public Button deleteBtn; bool isOpen = false; private int screenshotCount = 0; private int fileCount = 0; private string screenshotFileName; public string slotname; private string folderPath; DirectoryInfo screenshotDir; Sprite[] sprites; Texture2D[] textures; String[] screenshotNames; String[] screenshotPaths; static List<int> screenshotlist = new List<int>(); Dictionary<String, String> dic = new Dictionary<String, String>(); public List<GameObject> slots = new List<GameObject>(); void Start() { folderPath = Application.persistentDataPath + "/Textures/"; screenshotDir = new DirectoryInfo(folderPath); if (!Directory.Exists(folderPath)) Directory.CreateDirectory(folderPath); albumCloseBtn.onClick.AddListener(ShowOrHideAlbum); alertBtn.onClick.AddListener(CloseAlertWindow); deleteBtn.onClick.AddListener(DeleteTextures); screenshotlist.Add(screenshotCount); screenshotCount = PlayerPrefs.GetInt("MaxNumber"); ReplaceImages(); } void Update() { if (Input.GetKeyDown(KeyCode.A)) { ShowOrHideAlbum(); } if (Input.GetKeyDown(KeyCode.S)) { if(fileCount < slots.Count) { StartCoroutine(CaptureScreenshot()); } else { this.GetComponent<AlbumManager>().alertWindow.SetActive(true); } } } private IEnumerator CaptureScreenshot() { screenshotCount ++; screenshotlist.Add(screenshotCount); PlayerPrefs.SetInt("MaxNumber", screenshotlist.Max()); screenshotFileName = "Screenshot_" + screenshotCount + ".png"; ScreenCapture.CaptureScreenshot(folderPath + screenshotFileName); yield return new WaitForSeconds(0.5f); #if UNITY_EDITOR AssetDatabase.Refresh(); #endif ReplaceImages(); } public void CreateSprites() { FileInfo[] screenshotFiles = screenshotDir.GetFiles("*.png"); fileCount = screenshotDir.GetFiles("*.png").Length; Array.Resize(ref textures, fileCount); Array.Resize(ref sprites, fileCount); Array.Resize(ref screenshotNames, fileCount); Array.Resize(ref screenshotPaths, fileCount); for (int i = 0; i < fileCount; i++) { textures[i] = new Texture2D (256, 256); screenshotPaths[i] = screenshotFiles[i].FullName; screenshotNames[i] = screenshotFiles[i].Name; byte[] rawPNG = File.ReadAllBytes(screenshotPaths[i]); textures[i].LoadImage(rawPNG); sprites[i] = Sprite.Create(textures[i], new Rect(0f, 0f, textures[i].width, textures[i].height), Vector2.zero, 100.0f); sprites[i].name = "Sprite" + i; } ImagesDic(); } public void ReplaceImages() { CreateSprites(); for (int j = 0; j < slots.Count; j++) { slots[j].transform.GetChild(0).gameObject.GetComponent<Image>().sprite = null; slots[j].transform.GetChild(0).gameObject.SetActive(false); } for (int i = 0; i < sprites.Length; i++) { if (slots[i].transform.GetChild(0).gameObject.activeInHierarchy == false) { slots[i].transform.GetChild(0).gameObject.SetActive(true); slots[i].transform.GetChild(0).gameObject.GetComponent<Image>().sprite = sprites[i]; } } } public void ImagesDic() { dic.Clear(); for (int i = 0; i < sprites.Length; i++) { dic.Add(screenshotNames[i], sprites[i].name); } } public void DeleteTextures() { slot = GameObject.Find(slotname); string slotspritename = slot.transform.GetChild(0).gameObject.GetComponent<Image>().sprite.name; string key = dic.FirstOrDefault(item => item.Value == slotspritename).Key; string texturepath = folderPath + key; slot.transform.GetChild(0).gameObject.GetComponent<Image>().sprite = null; slot.transform.GetChild(0).gameObject.SetActive(false); File.Delete(texturepath); #if UNITY_EDITOR UnityEditor.AssetDatabase.Refresh(); #endif ReplaceImages(); } public void ShowOrHideAlbum() { isOpen = !isOpen; album.SetActive(isOpen); } public void CloseAlertWindow() { alertWindow.SetActive(false); } }
SlotHolder.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; using System; public class SlotHolder : MonoBehaviour, IPointerClickHandler { public GameObject confirmPanel; public GameObject albumManager; GameObject selectedSlot; String selectedSlotName; public Button confirmButton; public Button closePicture; void Start() { confirmButton.onClick.AddListener(CloseConfirmWindow); cancelButton.onClick.AddListener(CloseConfirmWindow); closePicture.onClick.AddListener(ClosePicture); } public void OnPointerClick(PointerEventData eventData) { if (eventData.button == PointerEventData.InputButton.Right && this.transform.GetChild(0).gameObject.activeInHierarchy == true) { selectedSlotName = name; albumManager.GetComponent<AlbumManager>().slotname = name; selectedSlot = GameObject.Find(selectedSlotName); OpenConfirmWindow(); } if (eventData.button == PointerEventData.InputButton.Left && this.transform.GetChild(0).gameObject.activeInHierarchy == true) { selectedSlotName = name; albumManager.GetComponent<AlbumManager>().slotname = name; selectedSlot = GameObject.Find(selectedSlotName); albumManager.GetComponent<AlbumManager>().ShowOrHideAlbum(); largePicture.SetActive(true); largePicture.transform.GetChild(0).gameObject.GetComponent<Image>().sprite = selectedSlot.transform.GetChild(0).gameObject.GetComponent<Image>().sprite; } } void OpenConfirmWindow() { confirmPanel.SetActive(true); } void CloseConfirmWindow() { confirmPanel.SetActive(false); } void ClosePicture() { largePicture.SetActive(false); } }
Logo

分享前沿Unity技术干货和开发经验,精彩的Unity活动和社区相关信息

更多推荐