Package pl.droidsonroids.gif
Class GifDrawable
java.lang.Object
android.graphics.drawable.Drawable
pl.droidsonroids.gif.GifDrawable
- All Implemented Interfaces:
Animatable,MediaController.MediaPlayerControl
public class GifDrawable extends Drawable implements Animatable, MediaController.MediaPlayerControl
A
Drawable which can be used to hold GIF images, especially animations.
Basic GIF metadata can also be examined.-
Nested Class Summary
Nested classes/interfaces inherited from class android.graphics.drawable.Drawable
Drawable.Callback, Drawable.ConstantState -
Field Summary
-
Constructor Summary
Constructors Modifier Constructor Description GifDrawable(byte[] bytes)Creates drawable from byte array.
It can be larger than size of the GIF data.GifDrawable(ContentResolver resolver, Uri uri)Creates drawable fromUriwhich is resolved usingresolver.GifDrawable(AssetFileDescriptor afd)Creates drawable from AssetFileDescriptor.GifDrawable(AssetManager assets, String assetName)Creates drawable from asset.GifDrawable(Resources res, int id)Creates drawable from resource.GifDrawable(File file)Equivalent to GifDrawable(file.getPath())}GifDrawable(FileDescriptor fd)Creates drawable from FileDescriptorGifDrawable(InputStream stream)Creates drawable from InputStream.GifDrawable(String filePath)Constructs drawable from given file path.
Only metadata is read, no graphic data is decoded here.GifDrawable(ByteBuffer buffer)Creates drawable fromByteBuffer.protectedGifDrawable(InputSource inputSource, GifDrawable oldDrawable, ScheduledThreadPoolExecutor executor, boolean isRenderingTriggeredOnDraw, GifOptions options)Creates drawable fromInputSource. -
Method Summary
Modifier and Type Method Description voidaddAnimationListener(AnimationListener listener)Adds a new animation listenerbooleancanPause()Checks whether pause is supported.booleancanSeekBackward()Checks whether seeking backward can be performed.booleancanSeekForward()Checks whether seeking forward can be performed.static GifDrawablecreateFromResource(Resources res, int resourceId)AnGifDrawable(Resources, int)wrapper but returns null instead of throwing exception if creation fails.voiddraw(Canvas canvas)Reads and renders new frame if needed then draws last rendered frame.longgetAllocationByteCount()Returns size of the memory needed to store pixels of this object.intgetAlpha()intgetAudioSessionId()Used by MediaPlayer.intgetBufferPercentage()Used by MediaPlayer for secondary progress bars.ColorFiltergetColorFilter()StringgetComment()Returns GIF commentfloatgetCornerRadius()BitmapgetCurrentFrame()Retrieves a copy of currently buffered frame.intgetCurrentFrameIndex()Returns zero-based index of recently rendered frame in given loop or -1 when drawable is recycled.intgetCurrentLoop()Returns zero-based index of currently played animation loop.intgetCurrentPosition()Retrieves elapsed time from the beginning of a current loop of animation.intgetDuration()Retrieves duration of one loop of the animation.GifErrorgetError()Retrieves last error which is also the indicator of current GIF status.intgetFrameByteCount()Returns the minimum number of bytes that can be used to store pixels of the single frame.intgetFrameDuration(int index)Returns duration of the given frame (in milliseconds).longgetInputSourceByteCount()Returns length of the input source obtained at the opening time or -1 if length cannot be determined.intgetIntrinsicHeight()intgetIntrinsicWidth()intgetLoopCount()Returns loop count previously read from GIF's application extension block.longgetMetadataAllocationByteCount()Returns the maximum possible size of the allocated memory used to store pixels and metadata of this object.intgetNumberOfFrames()intgetOpacity()PaintgetPaint()intgetPixel(int x, int y)Returns theColorat the specified location.voidgetPixels(int[] pixels)Returns in pixels[] a copy of the data in the current frame.TransformgetTransform()voidinvalidateSelf()booleanisAnimationCompleted()Returns whether all animation loops has ended.booleanisPlaying()Equivalent ofisRunning()booleanisRecycled()booleanisRunning()booleanisStateful()protected voidonBoundsChange(Rect bounds)protected booleanonStateChange(int[] stateSet)voidpause()Equivalent ofstop()voidrecycle()Frees any memory allocated native way.booleanremoveAnimationListener(AnimationListener listener)Removes an animation listenervoidreset()Causes the animation to start over.voidseekTo(int position)Seeks animation to given absolute position (within given loop) and refreshes the canvas.
Ifpositionis greater than duration of the loop of animation (or whole animation if there is no loop) then animation will be sought to the end, no exception will be thrown.
NOTE: all frames from current (or first one if seeking backward) to desired one must be rendered sequentially to perform seeking.voidseekToBlocking(int position)LikeseekTo(int)but performs operation synchronously on current threadvoidseekToFrame(int frameIndex)LikeseekTo(int)but uses index of the frame instead of time.BitmapseekToFrameAndGet(int frameIndex)LikeseekToFrame(int)but performs operation synchronously and returns that frame.BitmapseekToPositionAndGet(int position)LikeseekTo(int)but performs operation synchronously and returns that frame.voidsetAlpha(int alpha)voidsetColorFilter(ColorFilter cf)voidsetCornerRadius(float cornerRadius)Sets the corner radius to be applied when drawing the bitmap.voidsetDither(boolean dither)voidsetFilterBitmap(boolean filter)voidsetLoopCount(int loopCount)Sets loop count of the animation.voidsetSpeed(float factor)Sets new animation speed factor.
Note: If animation is in progress (draw(Canvas)) was already called) then effects will be visible starting from the next frame.voidsetTintList(ColorStateList tint)voidsetTintMode(PorterDuff.Mode tintMode)voidsetTransform(Transform transform)Specify aTransformimplementation to customize how the GIF's current Bitmap is drawn.booleansetVisible(boolean visible, boolean restart)Sets whether this drawable is visible.voidstart()Starts the animation.voidstop()Stops the animation.StringtoString()Methods inherited from class android.graphics.drawable.Drawable
applyTheme, canApplyTheme, clearColorFilter, copyBounds, copyBounds, createFromPath, createFromResourceStream, createFromResourceStream, createFromStream, createFromXml, createFromXml, createFromXmlInner, createFromXmlInner, getBounds, getCallback, getChangingConfigurations, getConstantState, getCurrent, getDirtyBounds, getHotspotBounds, getLayoutDirection, getLevel, getMinimumHeight, getMinimumWidth, getOpticalInsets, getOutline, getPadding, getState, getTransparentRegion, hasFocusStateSpecified, inflate, inflate, isAutoMirrored, isFilterBitmap, isProjected, isVisible, jumpToCurrentState, mutate, onLayoutDirectionChanged, onLevelChange, resolveOpacity, scheduleSelf, setAutoMirrored, setBounds, setBounds, setCallback, setChangingConfigurations, setColorFilter, setHotspot, setHotspotBounds, setLayoutDirection, setLevel, setState, setTint, setTintBlendMode, unscheduleSelf
-
Field Details
-
mPaint
Paint used to draw on a Canvas
-
-
Constructor Details
-
GifDrawable
public GifDrawable(@NonNull Resources res, @RawRes @DrawableRes int id) throws Resources.NotFoundException, IOExceptionCreates drawable from resource.- Parameters:
res- Resources to read fromid- resource id (raw or drawable)- Throws:
Resources.NotFoundException- if the given ID does not exist.IOException- when opening failedNullPointerException- if res is null
-
GifDrawable
Creates drawable from asset.- Parameters:
assets- AssetManager to read fromassetName- name of the asset- Throws:
IOException- when opening failedNullPointerException- if assets or assetName is null
-
GifDrawable
Constructs drawable from given file path.
Only metadata is read, no graphic data is decoded here. In practice can be called from main thread. However it will violateStrictModepolicy if disk reads detection is enabled.- Parameters:
filePath- path to the GIF file- Throws:
IOException- when opening failedNullPointerException- if filePath is null
-
GifDrawable
Equivalent to GifDrawable(file.getPath())}- Parameters:
file- the GIF file- Throws:
IOException- when opening failedNullPointerException- if file is null
-
GifDrawable
Creates drawable from InputStream. InputStream must support marking, IllegalArgumentException will be thrown otherwise.- Parameters:
stream- stream to read from- Throws:
IOException- when opening failedIllegalArgumentException- if stream does not support markingNullPointerException- if stream is null
-
GifDrawable
Creates drawable from AssetFileDescriptor. Convenience wrapper forGifDrawable(FileDescriptor)- Parameters:
afd- source- Throws:
NullPointerException- if afd is nullIOException- when opening failed
-
GifDrawable
Creates drawable from FileDescriptor- Parameters:
fd- source- Throws:
IOException- when opening failedNullPointerException- if fd is null
-
GifDrawable
Creates drawable from byte array.
It can be larger than size of the GIF data. Bytes beyond GIF terminator are not accessed.- Parameters:
bytes- raw GIF bytes- Throws:
IOException- if bytes does not contain valid GIF dataNullPointerException- if bytes are null
-
GifDrawable
Creates drawable fromByteBuffer. Only direct buffers are supported. Buffer can be larger than size of the GIF data. Bytes beyond GIF terminator are not accessed.- Parameters:
buffer- buffer containing GIF data- Throws:
IOException- if buffer does not contain valid GIF data or is indirectNullPointerException- if buffer is null
-
GifDrawable
Creates drawable fromUriwhich is resolved usingresolver.ContentResolver.openAssetFileDescriptor(android.net.Uri, String)is used to open an Uri.- Parameters:
uri- GIF Uri, cannot be null.resolver- resolver used to queryuri, can be null for file:// scheme Uris- Throws:
IOException- if resolution fails or destination is not a GIF.
-
GifDrawable
protected GifDrawable(@NonNull InputSource inputSource, @Nullable GifDrawable oldDrawable, @Nullable ScheduledThreadPoolExecutor executor, boolean isRenderingTriggeredOnDraw, @NonNull GifOptions options) throws IOExceptionCreates drawable fromInputSource.- Parameters:
inputSource- TheInputSourceconcrete subclass used to constructGifDrawable.oldDrawable- The old drawable that will be reused to save the memory. Can be null.executor- The executor for rendering tasks. Can be null.isRenderingTriggeredOnDraw- True if rendering of the next frame is scheduled after drawing current one, false otherwise.options- Options controlling various GIF parameters.- Throws:
IOException- if input source is invalid.
-
-
Method Details
-
recycle
public void recycle()Frees any memory allocated native way. Operation is irreversible. After this call, nothing will be drawn. This method is idempotent, subsequent calls have no effect. LikeBitmap.recycle()this is an advanced call and is invoked implicitly by finalizer. -
isRecycled
public boolean isRecycled()- Returns:
- true if drawable is recycled
-
invalidateSelf
public void invalidateSelf()- Overrides:
invalidateSelfin classDrawable
-
getIntrinsicHeight
public int getIntrinsicHeight()- Overrides:
getIntrinsicHeightin classDrawable
-
getIntrinsicWidth
public int getIntrinsicWidth()- Overrides:
getIntrinsicWidthin classDrawable
-
setAlpha
public void setAlpha(@IntRange(from=0L,to=255L) int alpha) -
setColorFilter
- Specified by:
setColorFilterin classDrawable
-
getOpacity
public int getOpacity()- Specified by:
getOpacityin classDrawable- Returns:
- either
PixelFormat.TRANSPARENTorPixelFormat.OPAQUEdepending on currentPaintandGifOptions.setInIsOpaque(boolean)used to construct this Drawable
-
start
public void start()Starts the animation. Does nothing if GIF is not animated. This method is thread-safe.- Specified by:
startin interfaceAnimatable- Specified by:
startin interfaceMediaController.MediaPlayerControl
-
reset
public void reset()Causes the animation to start over. If rewinding input source fails then state is not affected. This method is thread-safe. -
stop
public void stop()Stops the animation. Does nothing if GIF is not animated. This method is thread-safe.- Specified by:
stopin interfaceAnimatable
-
isRunning
public boolean isRunning()- Specified by:
isRunningin interfaceAnimatable
-
getComment
Returns GIF comment- Returns:
- comment or null if there is no one defined in file
-
getLoopCount
public int getLoopCount()Returns loop count previously read from GIF's application extension block. Defaults to 1 if there is no such extension.- Returns:
- loop count, 0 means that animation is infinite
-
setLoopCount
public void setLoopCount(@IntRange(from=0L,to=65535L) int loopCount)Sets loop count of the animation. Loop count must be in range<0 ,65535>- Parameters:
loopCount- loop count, 0 means infinity
-
toString
-
getNumberOfFrames
public int getNumberOfFrames()- Returns:
- number of frames in GIF, at least one
-
getError
Retrieves last error which is also the indicator of current GIF status.- Returns:
- current error or
GifError.NO_ERRORif there was no error or drawable is recycled
-
createFromResource
@Nullable public static GifDrawable createFromResource(@NonNull Resources res, @RawRes @DrawableRes int resourceId)AnGifDrawable(Resources, int)wrapper but returns null instead of throwing exception if creation fails.- Parameters:
res- resources to read fromresourceId- resource id- Returns:
- correct drawable or null if creation failed
-
setSpeed
public void setSpeed(@FloatRange(from=0.0,fromInclusive=false) float factor)Sets new animation speed factor.
Note: If animation is in progress (draw(Canvas)) was already called) then effects will be visible starting from the next frame. Duration of the currently rendered frame is not affected.- Parameters:
factor- new speed factor, eg. 0.5f means half speed, 1.0f - normal, 2.0f - double speed- Throws:
IllegalArgumentException- if factor<=0
-
pause
public void pause()Equivalent ofstop()- Specified by:
pausein interfaceMediaController.MediaPlayerControl
-
getDuration
public int getDuration()Retrieves duration of one loop of the animation. If there is no data (no Graphics Control Extension blocks) 0 is returned. Note that one-frame GIFs can have non-zero duration defined in Graphics Control Extension block, usegetNumberOfFrames()to determine if there is one or more frames.- Specified by:
getDurationin interfaceMediaController.MediaPlayerControl- Returns:
- duration of of one loop the animation in milliseconds. Result is always multiple of 10.
-
getCurrentPosition
public int getCurrentPosition()Retrieves elapsed time from the beginning of a current loop of animation. If there is only 1 frame or drawable is recycled 0 is returned.- Specified by:
getCurrentPositionin interfaceMediaController.MediaPlayerControl- Returns:
- elapsed time from the beginning of a loop in ms
-
seekTo
public void seekTo(@IntRange(from=0L,to=2147483647L) int position)Seeks animation to given absolute position (within given loop) and refreshes the canvas.
Ifpositionis greater than duration of the loop of animation (or whole animation if there is no loop) then animation will be sought to the end, no exception will be thrown.
NOTE: all frames from current (or first one if seeking backward) to desired one must be rendered sequentially to perform seeking. It may take a lot of time if number of such frames is large. Method is thread-safe. Decoding is performed in background thread and drawable is invalidated automatically afterwards.- Specified by:
seekToin interfaceMediaController.MediaPlayerControl- Parameters:
position- position to seek to in milliseconds- Throws:
IllegalArgumentException- ifposition<0
-
seekToBlocking
public void seekToBlocking(@IntRange(from=0L,to=2147483647L) int position)LikeseekTo(int)but performs operation synchronously on current thread- Parameters:
position- position to seek to in milliseconds- Throws:
IllegalArgumentException- ifposition<0
-
seekToFrame
public void seekToFrame(@IntRange(from=0L,to=2147483647L) int frameIndex)LikeseekTo(int)but uses index of the frame instead of time. IfframeIndexexceeds number of frames, seek stops at the end, no exception is thrown.- Parameters:
frameIndex- index of the frame to seek to (zero based)- Throws:
IllegalArgumentException- ifframeIndex<0
-
seekToFrameAndGet
LikeseekToFrame(int)but performs operation synchronously and returns that frame.- Parameters:
frameIndex- index of the frame to seek to (zero based)- Returns:
- frame at desired index
- Throws:
IndexOutOfBoundsException- if frameIndex<0
-
seekToPositionAndGet
LikeseekTo(int)but performs operation synchronously and returns that frame.- Parameters:
position- position to seek to in milliseconds- Returns:
- frame at desired position
- Throws:
IndexOutOfBoundsException- if position<0
-
isPlaying
public boolean isPlaying()Equivalent ofisRunning()- Specified by:
isPlayingin interfaceMediaController.MediaPlayerControl- Returns:
- true if animation is running
-
getBufferPercentage
public int getBufferPercentage()Used by MediaPlayer for secondary progress bars. There is no buffer in GifDrawable, so buffer is assumed to be always full.- Specified by:
getBufferPercentagein interfaceMediaController.MediaPlayerControl- Returns:
- always 100
-
canPause
public boolean canPause()Checks whether pause is supported.- Specified by:
canPausein interfaceMediaController.MediaPlayerControl- Returns:
- always true, even if there is only one frame
-
canSeekBackward
public boolean canSeekBackward()Checks whether seeking backward can be performed.- Specified by:
canSeekBackwardin interfaceMediaController.MediaPlayerControl- Returns:
- true if GIF has at least 2 frames
-
canSeekForward
public boolean canSeekForward()Checks whether seeking forward can be performed.- Specified by:
canSeekForwardin interfaceMediaController.MediaPlayerControl- Returns:
- true if GIF has at least 2 frames
-
getAudioSessionId
public int getAudioSessionId()Used by MediaPlayer. GIFs contain no sound, so 0 is always returned.- Specified by:
getAudioSessionIdin interfaceMediaController.MediaPlayerControl- Returns:
- always 0
-
getFrameByteCount
public int getFrameByteCount()Returns the minimum number of bytes that can be used to store pixels of the single frame. Returned value is the same for all the frames since it is based on the size of GIF screen.This method should not be used to calculate the memory usage of the bitmap. Instead see
getAllocationByteCount().- Returns:
- the minimum number of bytes that can be used to store pixels of the single frame
-
getAllocationByteCount
public long getAllocationByteCount()Returns size of the memory needed to store pixels of this object. It counts possible length of all frame buffers. Returned value may be lower than amount of actually allocated memory if GIF uses dispose to previous method but frame requiring it has never been needed yet. Returned value does not change during runtime.- Returns:
- possible size of the memory needed to store pixels of this object
-
getMetadataAllocationByteCount
public long getMetadataAllocationByteCount()Returns the maximum possible size of the allocated memory used to store pixels and metadata of this object. It counts length of all frame buffers. Returned value does not change over time.- Returns:
- maximum possible size of the allocated memory needed to store metadata of this object
-
getInputSourceByteCount
public long getInputSourceByteCount()Returns length of the input source obtained at the opening time or -1 if length cannot be determined. Returned value does not change during runtime. If GifDrawable is constructed fromInputStream-1 is always returned. In case of byte array andByteBufferlength is always known. In other cases length -1 can be returned if length cannot be determined.- Returns:
- number of bytes backed by input source or -1 if it is unknown
-
getPixels
public void getPixels(@NonNull int[] pixels)Returns in pixels[] a copy of the data in the current frame. Each value is a packed int representing aColor.- Parameters:
pixels- the array to receive the frame's colors- Throws:
ArrayIndexOutOfBoundsException- if the pixels array is too small to receive required number of pixels
-
getPixel
public int getPixel(@IntRange(from=0L) int x, @IntRange(from=0L) int y)Returns theColorat the specified location. Throws an exception if x or y are out of bounds (negative or >= to the width or height respectively). The returned color is a non-premultiplied ARGB value.- Parameters:
x- The x coordinate (0...width-1) of the pixel to returny- The y coordinate (0...height-1) of the pixel to return- Returns:
- The argb
Colorat the specified coordinate - Throws:
IllegalArgumentException- if x, y exceed the drawable's boundsIllegalStateException- if drawable is recycled
-
onBoundsChange
- Overrides:
onBoundsChangein classDrawable
-
draw
Reads and renders new frame if needed then draws last rendered frame. -
getPaint
- Returns:
- the paint used to render this drawable
-
getAlpha
public int getAlpha() -
setFilterBitmap
public void setFilterBitmap(boolean filter)- Overrides:
setFilterBitmapin classDrawable
-
setDither
public void setDither(boolean dither) -
addAnimationListener
Adds a new animation listener- Parameters:
listener- animation listener to be added, not null- Throws:
NullPointerException- if listener is null
-
removeAnimationListener
Removes an animation listener- Parameters:
listener- animation listener to be removed- Returns:
- true if listener collection has been modified
-
getColorFilter
- Overrides:
getColorFilterin classDrawable
-
getCurrentFrame
Retrieves a copy of currently buffered frame.- Returns:
- current frame
-
setTintList
- Overrides:
setTintListin classDrawable
-
setTintMode
- Overrides:
setTintModein classDrawable
-
onStateChange
protected boolean onStateChange(int[] stateSet)- Overrides:
onStateChangein classDrawable
-
isStateful
public boolean isStateful()- Overrides:
isStatefulin classDrawable
-
setVisible
public boolean setVisible(boolean visible, boolean restart)Sets whether this drawable is visible. If rendering of next frame is scheduled on draw current one (the default) then this method only calls through to the super class's implementation.
Otherwise (ifGifDrawableInit.setRenderingTriggeredOnDraw(boolean)was used withtrue) when the drawable becomes invisible, it will pause its animation. A subsequent change to visible withrestartset to true will restart the animation from the first frame. Ifrestartis false, the animation will resume from the most recent frame.- Overrides:
setVisiblein classDrawable- Parameters:
visible- true if visible, false otherwiserestart- when visible and rendering is triggered on draw, true to force the animation to restart from the first frame- Returns:
- true if the new visibility is different than its previous state
-
getCurrentFrameIndex
public int getCurrentFrameIndex()Returns zero-based index of recently rendered frame in given loop or -1 when drawable is recycled.- Returns:
- index of recently rendered frame or -1 when drawable is recycled
-
getCurrentLoop
public int getCurrentLoop()Returns zero-based index of currently played animation loop. If animation is infinite or drawable is recycled 0 is returned.- Returns:
- index of currently played animation loop
-
isAnimationCompleted
public boolean isAnimationCompleted()Returns whether all animation loops has ended. If drawable is recycled false is returned.- Returns:
- true if all animation loops has ended
-
getFrameDuration
public int getFrameDuration(@IntRange(from=0L) int index)Returns duration of the given frame (in milliseconds). If there is no data (no Graphics Control Extension blocks or drawable is recycled) 0 is returned.- Parameters:
index- index of the frame- Returns:
- duration of the given frame in milliseconds
- Throws:
IndexOutOfBoundsException- if index < 0 or index >= number of frames
-
setCornerRadius
public void setCornerRadius(@FloatRange(from=0.0) float cornerRadius)Sets the corner radius to be applied when drawing the bitmap. Note that changing corner radius will cause replacing currentPaintshader byBitmapShader. Transform set bysetTransform(Transform)will also be replaced.- Parameters:
cornerRadius- corner radius or 0 to remove rounding
-
getCornerRadius
@FloatRange(from=0.0) public float getCornerRadius()- Returns:
- The corner radius applied when drawing this drawable. 0 when drawable is not rounded.
-
setTransform
Specify aTransformimplementation to customize how the GIF's current Bitmap is drawn.- Parameters:
transform- newTransformor null to remove current one
-
getTransform
- Returns:
- The current
Transformimplementation that customizes how the GIF's current Bitmap is drawn or null if nothing has been set.
-