在Silverlight中我们可以使用ImageTools库的AnimatedImage控件来播放GIF图片,但是AnimatedImage目前还不支持WinRT应用,所以我实现了一个简单的控件来播放本地GIF文件。原理很蛋疼,首先用各种工具把GIF拆成单独的PNG文件,然后放到同一个文件夹下面,加载到内存中后用Timer来控制循环显示。
代码实现
public sealed class GifImage : ContentControl
{
private readonly Image _image = new Image();
private BitmapImage[] _bitmapList;
private int _bitmapIndex;
private readonly DispatcherTimer _timerController = new DispatcherTimer();
public GifImage()
{
_timerController.Tick += timerController_Tick;
_image.Stretch = Stretch.None;
Content = _image;
}
public async void Init(string msappxPath, string extension, uint count, uint intervalMs)
{
_bitmapList = new BitmapImage[count];
if (!extension.StartsWith("."))
extension = "." + extension;
string[] pathList = msappxPath.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
StorageFolder installFolder = Package.Current.InstalledLocation;
StorageFolder sfImage = installFolder;
for (int i = 0; i < pathList.Length; i++)
sfImage = await sfImage.GetFolderAsync(pathList[i]);
for (int i = 0; i < count; i++)
{
StorageFile fileImage = await sfImage.GetFileAsync(i + extension);
using (var stream = await fileImage.OpenReadAsync())
{
_bitmapList[i] = new BitmapImage();
_bitmapList[i].SetSource(stream);
}
}
_timerController.Interval = TimeSpan.FromMilliseconds(intervalMs);
_timerController.Start();
}
public void Unload()
{
_timerController.Tick -= timerController_Tick;
_timerController.Stop();
_image.Source = null;
for (int i = 0; i < _bitmapList.Length; i++)
_bitmapList[i] = null;
}
public void Pause()
{
_timerController.Stop();
}
public void Resume()
{
_timerController.Start();
}
private void timerController_Tick(object sender, object e)
{
if (_bitmapIndex == _bitmapList.Length - 1)
_bitmapIndex = 0;
else
_bitmapIndex++;
_image.Source = _bitmapList[_bitmapIndex];
}
}
{
private readonly Image _image = new Image();
private BitmapImage[] _bitmapList;
private int _bitmapIndex;
private readonly DispatcherTimer _timerController = new DispatcherTimer();
public GifImage()
{
_timerController.Tick += timerController_Tick;
_image.Stretch = Stretch.None;
Content = _image;
}
public async void Init(string msappxPath, string extension, uint count, uint intervalMs)
{
_bitmapList = new BitmapImage[count];
if (!extension.StartsWith("."))
extension = "." + extension;
string[] pathList = msappxPath.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
StorageFolder installFolder = Package.Current.InstalledLocation;
StorageFolder sfImage = installFolder;
for (int i = 0; i < pathList.Length; i++)
sfImage = await sfImage.GetFolderAsync(pathList[i]);
for (int i = 0; i < count; i++)
{
StorageFile fileImage = await sfImage.GetFileAsync(i + extension);
using (var stream = await fileImage.OpenReadAsync())
{
_bitmapList[i] = new BitmapImage();
_bitmapList[i].SetSource(stream);
}
}
_timerController.Interval = TimeSpan.FromMilliseconds(intervalMs);
_timerController.Start();
}
public void Unload()
{
_timerController.Tick -= timerController_Tick;
_timerController.Stop();
_image.Source = null;
for (int i = 0; i < _bitmapList.Length; i++)
_bitmapList[i] = null;
}
public void Pause()
{
_timerController.Stop();
}
public void Resume()
{
_timerController.Start();
}
private void timerController_Tick(object sender, object e)
{
if (_bitmapIndex == _bitmapList.Length - 1)
_bitmapIndex = 0;
else
_bitmapIndex++;
_image.Source = _bitmapList[_bitmapIndex];
}
}
使用方法
把PNG图片用Content方式加到项目中后,在对应页面的构造函数中调用Init()方法:
_gifImg.Init("/Assets/Gif/", "png", 5, 100);
在必要的地方调用Pause()和Resume()方法来控制播放,调用Unload()方法来释放资源。
» 转载请注明来源及链接:未来代码研究所
可以参考一下这个:http://www.henrikbrinch.dk/Blog/2013/02/21/Windows-8—GIF-animations–the-RIGHT-way
我试过这个,他这个不支持背景透明的GIF图片,放起来会花掉。
换这个怎么样?wpf时期效果还不错,wp就不太清楚了。
https://github.com/thomaslevesque/XamlAnimatedGif
实际上真要实现解析并播放gif文件并不难,研究一下gif的格式就行,但是需要考虑一下性能问题。我因为需求简单就直接抄近路了。。。
还有一个最简单粗暴的方法:WebView。
WebView可能导致内存泄漏问题,不建议大量用