项目需要做一个安卓端的图片轮播小程序。然后猛然发现一万年过去了安卓端自己还在用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);
}
}
}