五、删除相册中的图片

(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活动和社区相关信息

更多推荐