項目需要做一個安卓端的圖片輪播小程序。然後猛然發現一萬年過去了安卓端自己還在用www讀取本地圖片,Assetbundle雖然好用讀取也快……但不方便客戶自己進行替換圖片操作,一個輪播圖小程序還要配置一個安卓本地服務器並寫一個小工具給客戶用來打包,操作就過於繁瑣了。
試着用www和文件讀取二進制兩種方式來讀取,讀取速度差不多……下面來介紹兩種方式。
安卓端路徑
安卓端PersistentDataPath的路徑具體位置在:/storage/emulated/0/com.companyName.productName/files/底下,將文件複製到對於文件夾即可。
從文件中用二進制直接讀取
public void LoadFile(string path)
{
DirectoryInfo direction = new DirectoryInfo(path);
FileInfo[] files = direction.GetFiles("*");
List<string> imageNames = new List<string>();
for (int i = 0; i < files.Length; i++)
{
if (!files[i].Name.EndsWith(".meta"))
{
imageNames.Add(files[i].FullName);
}
}
Total = imageNames.Count;
for(int j = 0; j < imageNames.Count; j++)
{
//StartCoroutine(DownLoadPic("file:///" + path + "/" + files[j].Name));
byte[] binaryImageData = File.ReadAllBytes(imageNames[j]);
Texture2D imageTex = new Texture2D(Screen.width,Screen.height);
imageTex.LoadImage(binaryImageData);
GameObject ImageObj = Instantiate<GameObject>(prefab, Content);
ImageObj.name = j.ToString();
Image image = ImageObj.GetComponent<Image>();
int width = imageTex.width;
int height = imageTex.height;
Sprite sprite = Sprite.Create(imageTex, new Rect(0, 0, width, height), Vector2.zero);
image.sprite = sprite;
RectTransform imgTrans = image.GetComponent<RectTransform>();
float radio = (float)width / height;
Debug.Log(radio);
if (height >= width)
{
imgTrans.sizeDelta = new Vector2(Screen.height * radio, Screen.height);
}
else{
imgTrans.sizeDelta = new Vector2(Screen.width, Screen.width/radio);
}
Draggable draggable = ImageObj.GetComponent<Draggable>();
draggable.BeginDrag += OnBeginDrag;
draggable.Dragged += OnDrag;
draggable.Dragging += OnDragging;
ImageList.Add(imgTrans);
imgTrans.anchoredPosition = new Vector2((j - imageNames.Count / 2) * Screen.width, 0);
}
OnLoadCompelete();
}
用www讀取
IEnumerator DownLoadPic(string url) {
WWW picdownloader = new WWW(url);
yield return picdownloader;
if (picdownloader.error != null) {
Debug.LogError(picdownloader.error);
}
else if (picdownloader.isDone) {
Texture2D imageTex = picdownloader.texture;
GameObject ImageObj = Instantiate<GameObject>(prefab, Content);
ImageObj.name = ImageCount.ToString();
Image image = ImageObj.GetComponent<Image>();
int width = imageTex.width;
int height = imageTex.height;
Sprite sprite = Sprite.Create(imageTex, new Rect(0, 0, width, height), Vector2.zero);
image.sprite = sprite;
RectTransform imgTrans = image.GetComponent<RectTransform>();
float radio = (float)width / height;
if (height >= width)
{
imgTrans.sizeDelta = new Vector2(Screen.height * radio, Screen.height);
}
else
{
imgTrans.sizeDelta = new Vector2(Screen.width, Screen.width / radio);
}
Draggable draggable = ImageObj.GetComponent<Draggable>();
draggable.BeginDrag += OnBeginDrag;
draggable.Dragged += OnDrag;
draggable.Dragging += OnDragging;
ImageList.Add(imgTrans);
imgTrans.anchoredPosition = new Vector2((ImageCount-Total / 2) *Screen.width,0);
ImageCount++;
if (ImageCount == Total) {
OnLoadCompelete();
}
}
}
輪播圖核心思想:
在每個子元件上綁上拖拽代碼,在拖拽完成後將末尾的圖放在最初始。可以用雙鏈表算法優化,這裏就直接遍歷子節點,寫的簡單一些。在預製件上綁上Draggable
public class Draggable : MonoBehaviour,IBeginDragHandler, IDragHandler, IEndDragHandler
{
public UnityAction<PointerEventData> BeginDrag;
public UnityAction<PointerEventData> Dragging;
public UnityAction<PointerEventData> Dragged;
public void OnBeginDrag(PointerEventData eventData)
{
if (BeginDrag != null)
{
BeginDrag(eventData);
}
}
public void OnDrag(PointerEventData eventData)
{
if (Dragging != null)
{
Dragging(eventData);
}
}
public void OnEndDrag(PointerEventData eventData)
{
if (Dragged != null)
{
Dragged(eventData);
}
}
}