求助,AE怎么ae渲染gif为GIF动态图片

1601人阅读
android(3)
1.首先描述下自定义控件的一般方法:
自定义控件是被创造出来,所以先要复写它三个的构造方法,根据需求决定复写哪个,若没有自定义属性,复写只有一个参数的即可。若有自定义属性,则可以通过obtainStyledAttributes获得TypedArray对象,通过该对象获得属性并进行相应操作。然后下面的过程和画画差不多,我们在画一样东西的时候,首先要知道物品大概的样子,也就是需要复写onMeasure()方法,测量控件以及其子布局的大小。知道物品的大概后,我们需要对其里面的细节精雕细琢,也就是调用onLayout()方法,决定其子View的位置。最后就是将图整体勾勒出来,即是调用onDraw()方法。这样子控件大概的样子就出来了,再根据需求增加相应借口,回调方法。
2.Android显示gif的三种方式:
(1)使用Android自带的Movie对象,将Gif当成视频。随着时间的变化,通过setTime方法设置需要显示的图片,然后onDraw方法不断将新的画画出来。实例代码如下:
MainActivity:
public class MainActivity extends Activity {
private GifV
private ListView lv_
private int[] gifResource={R.drawable.car,R.drawable.rick,R.drawable.car,R.drawable.mm,R.drawable.qq};
private MyAdapter adapter=
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lv_content=(ListView) findViewById(R.id.lv_content);
adapter = new MyAdapter();
lv_content.setAdapter(adapter);
lv_content.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView&?& parent, View view,
int position, long id) {
if(adapter!=null)
adapter.notifyDataSetChanged();
// 去掉listView的item点击的效果
lv_content.setEnabled(false);
lv_content.setSelector(color.transparent);
private class MyAdapter extends BaseAdapter{
public int getCount() {
// TODO Auto-generated method stub
return gifResource.
public Object getItem(int position) {
public long getItemId(int position) {
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder=
if(convertView == null)
convertView=View.inflate(getApplicationContext(), R.layout.item_gif, null);
holder=new ViewHolder();
holder.tv_username=(TextView) convertView.findViewById(R.id.tv_username);
holder.tv_comemnt=(TextView) convertView.findViewById(R.id.tv_comment);
holder.gv=(GifView) convertView.findViewById(R.id.gv);
convertView.setTag(holder);
holder=(ViewHolder) convertView.getTag();
holder.tv_username.setText(&username&+position);
holder.tv_comemnt.setText(&comment&+position);
holder.gv.setMovieResource(gifResource[position]);
holder.gv.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
GifView view=(GifView)
view.setPaused(!view.isPause());
return convertV
class ViewHolder{
public TextView tv_
public TextView tv_
public GifV
自定义组件GifView:
package com.example.gifdemo.
import com.example.gifdemo.R;
import android.annotation.SuppressL
import android.content.C
import android.content.res.TypedA
import android.graphics.C
import android.graphics.M
import android.os.B
import android.os.SystemC
import android.util.AttributeS
import android.view.V
/**使用Android自定义的movie实现**/
public class GifView extends View{
private static final int DEFAULT_GIF_DURATION=1000;
// the reference for gif
private int mMovieResourceId;
private Movie mM
private long mS
private int mCurrentAnimationTime=0;
private boolean mPause=
private boolean mVisible=
private long mW
private long mH
private float mS
private float mL
private float mT
private int mMeasuredW
private int mMeasureH
public GifView(Context context) {
this(context,null);
public GifView(Context context, AttributeSet attrs) {
this(context, attrs,R.styleable.CustomTheme_gifMoviewViewStyle);
public GifView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setViewAttributes(context, attrs, defStyleAttr);
private void setViewAttributes(Context context, AttributeSet attrs, int defStyleAttr)
* Starting from HONEYCOMB have to turn off HW acceleration to draw
* Movie on Canvas.
if(Build.VERSION.SDK_INT&=Build.VERSION_CODES.HONEYCOMB)
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
//?? TODO get the collection of the attrs
final TypedArray array=context.obtainStyledAttributes(attrs, R.styleable.GifView, defStyleAttr, R.style.Widget_GifMoviewView);
mPause=array.getBoolean(R.styleable.GifView_paused, true);
mMovieResourceId=array.getResourceId(R.styleable.GifView_gif, -1);
// recycle TypedArray
array.recycle();
if(mMovieResourceId!=-1)
mMovie=Movie.decodeStream(getResources().openRawResource(mMovieResourceId));
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if(mMovie!=null)
int mWidth=mMovie.width();
int mHeight=mMovie.height();
float scaleX=1f;
int measureModeWidth=MeasureSpec.getMode(widthMeasureSpec);
if(measureModeWidth!=MeasureSpec.UNSPECIFIED)
int maximumWidth=MeasureSpec.getSize(widthMeasureSpec);
if(mWidth&maximumWidth)
scaleX=(float)mWidth/(float)maximumW
float scaleY=1f;
int measureModeHeight=MeasureSpec.getMode(heightMeasureSpec);
if(measureModeHeight!=MeasureSpec.UNSPECIFIED)
int maximumHeight=MeasureSpec.getSize(heightMeasureSpec);
if(mHeight&maximumHeight)
scaleY=(float)mHeight/(float)maximumH
mScale=1f/Math.max(scaleX, scaleY);
mMeasuredWidth=(int) (mWidth*mScale);
mMeasureHeight=(int) (mHeight*mScale);
setMeasuredDimension(mMeasuredWidth,mMeasureHeight);
setMeasuredDimension(getSuggestedMinimumWidth(), getSuggestedMinimumHeight());
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
super.onLayout(changed, left, top, right, bottom);
/** Calculate left / top for drawing in center **/
mLeft=(getWidth()-mMeasuredWidth)/2f;
mTop=(getHeight()-mMeasureHeight)/2f;
mVisible= getVisibility() == View.VISIBLE;
protected void onDraw(Canvas canvas) {
if(mMovie!=null)
if(!mPause)
updateCurrentTime();
drawFrame(canvas);
invalidateView();
drawFrame(canvas);
private void updateCurrentTime()
long now=SystemClock.uptimeMillis();
if(mStart==0)
int dur=mMovie.duration();
if(dur==0)
dur=DEFAULT_GIF_DURATION;
mCurrentAnimationTime=(int)((now-mStart)%dur);
private void drawFrame(Canvas canvas)
mMovie.setTime(mCurrentAnimationTime);
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.scale(mScale, mScale);
mMovie.draw(canvas, mLeft/mScale, mTop/mScale);
mMovie.draw(canvas, 0, 0);
canvas.restore();
* Invalidates view only if it is visible.
* {@link #postInvalidateOnAnimation()} is used for Jelly Bean and higher.
@SuppressLint(&NewApi&)
private void invalidateView() {
if(mVisible) {
if (Build.VERSION.SDK_INT &= Build.VERSION_CODES.JELLY_BEAN) {
postInvalidateOnAnimation();
invalidate();
// the methods of the important attribute
public void setPaused(boolean pause)
this.mPause=
// retrieve the StartTime
if(!mPause)
mStart=SystemClock.uptimeMillis()-mCurrentAnimationT
invalidate();
public boolean isPause()
public void setMovieResource(int movieResourceId)
this.mMovieResourceId=movieResourceId;
mMovie=Movie.decodeStream(getResources().openRawResource(movieResourceId));
// important Call this when something has changed which has invalidated the
//layout of this view.
requestLayout();
public void setMovie(Movie movie)
this.mMovie=
requestLayout();
public Movie getMovie()
public void setMovieTime(int time)
this.mCurrentAnimationTime=
invalidate();
(2)自定义TextView显示Gif,先使用GifDecoder将Gif文件解析成一张张图片,然后通过ImageSpan将图片显示在TextView中,定义一个线程不断刷新图片。
自定义TextView:
package com.yyg.gifdemo3.
public class MyTextView extends TextView{
private Context mC
private SpannableStringBuilder mSb=new SpannableStringBuilder();
private String dummyStr=&dummy&;
private SimpleImageMemCache mC
private List&AnimatedImageSpan& mGifSpanList=new ArrayList&AnimatedImageSpan&();
public MyTextView(Context context) {
super(context);
public MyTextView(Context context, AttributeSet attrs) {
super(context, attrs);
public MyTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
public void setImageCache(SimpleImageMemCache pImageCache)
this.mCache=pImageC
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
Log.d(this.getClass().getName(), &onDetachedFromWindow &);
for (AnimatedImageSpan ais : mGifSpanList) {
Log.d(this.getClass().getName(), &animation playing & + ais.isPlaying());
if (ais.isPlaying()) {
ais.stopRendering();
mGifSpanList.clear();
mSb.clearSpans();
mSb.clear();
public void appendText(String text)
mSb.append(text);
public void appendAnimation(GifResource pAssetsSet,AnimationSettings pSettings)
mSb.append(dummyStr);
AnimatedImageSpan ais=new AnimatedImageSpan(mContext);
ais.setAssetsSet(pAssetsSet);
ais.setBitmapCache(mCache);
mSb.setSpan(ais, mSb.length()-dummyStr.length(), mSb.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
AnimationClickableSpan clickableSpan=new AnimationClickableSpan(this, ais, pSettings);
mSb.setSpan(clickableSpan, mSb.length()-dummyStr.length(), mSb.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
mGifSpanList.add(ais);
public void finishAddContent()
this.setText(mSb);
// setMovementMethod,此方法在需要响应用户事件时使用,如点击一个电话号码就跳转到拨号页面。如果不执行这个方法是不会响应事件的,即便文本看着已经是下划线蓝色字了。
this.setMovementMethod(LinkMovementMethod.getInstance());
private static class AnimationClickableSpan extends ClickableSpan
private AnimatedImageSpan mImageS
private AnimationSettings mS
private AnimatedImageUpdateHandler updateH
public AnimationClickableSpan(MyTextView pTextView ,AnimatedImageSpan pAnimatedImageSpan,AnimationSettings pSettings)
this.mImageSpan=pAnimatedImageS
this.mSettings=pS
this.updateHandler=new AnimatedImageUpdateHandler(pTextView);
public void onClick(View widget) {
if(this.mImageSpan.isPlaying())
this.mImageSpan.stopRendering();
this.mImageSpan.playGif(this.mSettings,this.updateHandler);
完整项目链接:
(3)使用WebView加载Gif:
package com.example.gifdemo3;
import android.os.B
import android.os.B
import android.app.A
import android.view.M
import android.webkit.WebV
public class MainActivity extends Activity {
private WebView wv_
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
wv_gif=(WebView) findViewById(R.id.wv_gif);
if(Build.VERSION.SDK_INT&=Build.VERSION_CODES.KITKAT)
wv_gif.loadUrl(&/data/uploadfile/0.gif&);
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:12326次
排名:千里之外
原创:15篇
(2)(13)(1)(1)(2)(1)(1)(1)分享给朋友:通用代码: <input id="link4" type="text" class="form_input form_input_s" value="" />复 制flash地址: 复 制html代码: <input type="text" class="form_input form_input_s" id="link3" value="" />复 制分享视频到站外获取收益&&手机扫码分享视频二维码2小时内有效教你如何从视频里截动态GIF动态图片下载至电脑扫码用手机看用或微信扫码在手机上继续观看二维码2小时内有效教你如何从视频里截动态GIF动态图片扫码用手机继续看用或微信扫码在手机上继续观看二维码2小时内有效,扫码后可分享给好友没有优酷APP?立即下载请根据您的设备选择下载版本
药品服务许可证(京)-经营-
节目制作经营许可证京字670号
请使用者仔细阅读优酷、、
Copyright(C)2017 优酷
不良信息举报电话:有了它,AE终于可以直接导出gif动图啦! - 简书
有了它,AE终于可以直接导出gif动图啦!
AE不能直接导出gif动图,真的很烦诶。
AME堪称神器
话说还在远古时代的AE CS时代,AE的渲染是有gif动图格式可选的,这样无论是把视频内容生成gif,还是MG动画生成gif,又或者是制作完表情包后直接出gif,都非常方便。然而,从CS5之后,Adobe大魔王不知道为什么取消了这个格式,甩!自此之后,CS6、CC、CC2014、CC2015、CC2015.3、CC2017,这七代AE都要忍受着先渲染导出视频或者序列图片,然后再通过PS等二次创作来生成gif的麻烦,好烦啊!!!随便放下截图,感受下没有gif动图格式可选的尴尬。
如图操作,合成&添加到渲染队列,点击无损去打开下图设置
如图所示,真的很忧伤
比如,我们在AE中完成了以下这些图,在生成视频前想迅速给小伙伴看一下,或者我们就是为了做gif动画而已,却不能在AE中一波流完成。你说恼人不恼人啊,抓狂.gif。
比如做好了一MG风格的字母A动画
比如字母B的MG动画
比如生日氛围的文字动画
比如音频可视化的酷炫动画
比如粒子动画
PS:AE能做的很多啦,绝不止上述举例这几个小玩意的。当然,在这些年中,也有很多第三方脚本开发者,写了直接生成gif的脚本,比较有名的像GifGun、像Gif-Magick等,虽然看起来很美好,奈何在中文版AE中的兼容效果总是有些欠缺,反正阿随君就没顺利得用上过他们。直到它的出现
AME终于更新支持了导出gif动图!!
直到新版的Adobe Media Encoder问世后,阿随君突然发现在渲染导出的格式选项里突然多了“动画 GIF”这个选项,真是太好了,要知道此前有的gif格式,导出的也是图像格式啊。话不多说,赶快来跟小伙伴们展示一下如何使用这家伙了。首先在时间轴面板上,选定要导出动画的合成作为当前合成,然后如下图所示,选择菜单栏的“合成&添加到Adobe Media Encoder队列”,或者直接按键盘快捷键Ctrl+Alt+M,即可打开AME软件了。
AME稍等片刻即打开
AME软件打开后,如下图所示,在界面上点击红圈3处的“匹配源 高比特率”即可弹出“导出设置”面板,在该面板上点击红圈4所在的格式下拉菜单,即可看到“动画gif”格式,选择它即可。
格式N多哦,满足多平台需求
选定格式后,如下动图所示,还可以对gif的质量、宽高尺寸等进行二度设置,以满足我们更细致的需求,比如对gif大小有限制时,就可以通过更改质量、尺寸等来实现。
AME都设置好之后,如下图所示,点击开始渲染按钮,稍等片刻即好。
如图操作,导出gif
AME的妖孽之处不仅在于解决了AE对的导出gif不能问题,而且更为懒人们、为格式选择迷惘者们提供了丰富的格式选项,比如现在微信都支持发本地视频了,那么我们就可以制作符合AE尺寸的视频出来,而AME的导出格式预设里准备内置了手机设备的尺寸选项,安卓苹果设备都有,当然了,从影院级视频、蓝光级、Facebook等大网站的视频尺寸等等都有预设,点开下面动图,直接预览感受之。
感受下针对各平台的视频预设
AME是不是很好用呢?而它这套导出算法,在非编软件Pr中是同样适用的,也就是说如果我们想从视频中截取一段做表情包,那么把视频放到Pr中剪辑、加简单包装就可以直接导出gif表情包使用了。如果需要做更多好玩的特效,也可以结合着AE一起使用。而不用再走PS这一道程序了,真的是高效了不少呢。对gif感兴趣的小伙伴们,阿随君强烈推荐大家操练起来,是时候更新自己的武器库。
OK,我就是那个爱折腾软件的策划君阿随,没事搞搞视频、听听Nirvana、读读陶渊明、看看戈达尔的电影,生活就很美好。
如果还是不了解的话,推荐来阅读阿随君用简书半年后的感想文,每一次小进步,都是崭新的。
如果亲爱的小伙伴喜欢这篇文章,阿随这里卖萌求点赞求支持哦,么么哒。
微信公众号:阿随向前冲
PS重度爱好者
影视圈边缘文字工作者
曾任《看电影》编辑}

我要回帖

更多关于 ae渲染成gif 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信