I make gif Files animated then, I put this one in the Application's imageview.
GlideDrawableImageViewTarget imageViewTarget = new GlideDrawableImageViewTarget(character6);
Glide.with(this).load(R.raw.company_normal8).into(imageViewTarget);
here's code and I have no problem with apply this one.
But I have serious issue that The image have afterimage.
I made this gif file with photoshop and It have 2 frame
There's A frame and B frame.
But at android app,
A -> B -> A -> B (this is the normal one)
But My app
A -> A+B -> A -> A+b (like this afterimage)
You can use asGif
Glide.with(context)
.load(imgUrl)
.asGif()
.placeholder(R.drawable.img)
.crossFade()
.into(imageView);
OR
Try this if Glide is not working for you,Its working for me
public class GIFView extends View{
Movie movie;
long moviestart;
public GIFView(Context context) throws IOException {
super(context);
}
public GIFView(Context context, AttributeSet attrs) throws IOException{
super(context, attrs);
}
public GIFView(Context context, AttributeSet attrs, int defStyle) throws IOException {
super(context, attrs, defStyle);
}
public void loadGIFResource(Context context, int id)
{
//turn off hardware acceleration
this.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
InputStream is=context.getResources().openRawResource(id);
movie = Movie.decodeStream(is);
}
public void loadGIFAsset(Context context, String filename)
{
InputStream is;
try {
is = context.getResources().getAssets().open(filename);
movie = Movie.decodeStream(is);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (movie == null) {
return;
}
long now=android.os.SystemClock.uptimeMillis();
if (moviestart == 0) moviestart = now;
int relTime;
relTime = (int)((now - moviestart) % movie.duration());
movie.setTime(relTime);
movie.draw(canvas,10,10);
this.invalidate();
}
}
XML
<yourpackagename.GIFView
android:id="#+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginBottom="50dp"
android:layout_marginTop="110dp"
android:src="#drawable/yourgifimage"/>
To set the image
imagevw.loadGIFResource(this, R.drawable.yourgifimage);
Related
I want to save a Lottie animation as video (mp4 or any other video format).
Here's a list of what I've tried:
How to save Lottie Animation as Video (.mp4) and GIF (.gif) in Android?
I tried with this Lottie Recorder Test lib. But I'm still getting issue with this lib also
Someone told me to record surfaceview using this lib. but How to draw each frame of lottie onto the canvas?
I really do know know how to draw each frame in surfaceview from Lottie
public class MyLottieAnimationView extends LottieAnimationView {
SurfaceHolder holder;
public void setHolder(SurfaceHolder holder) {
this.holder = holder;
}
public MyLottieAnimationView(Context context) {
super(context);
}
public MyLottieAnimationView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyLottieAnimationView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
protected void onDraw(Canvas canvas) {
Canvas c = holder.lockCanvas();
if (c == null) {
Log.e(TAG, "Cannot draw onto the canvas as it's null");
} else {
Bitmap myBitmap = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), Bitmap.Config.RGB_565);
canvas.setBitmap(myBitmap);
c.drawBitmap(myBitmap, 0, 0, new Paint());
// c.
// drawMyStuff(canvas);
holder.unlockCanvasAndPost(canvas);
}
super.onDraw(canvas);
}
}
val lottieComposition = LottieCompositionFactory.fromRawResSync(this, R.raw.android_wave) // your lottie json file
val lottieDrawable = LottieDrawable()
lottieDrawable.composition = lottieComposition.value
val path = getExternalFilesDir(Environment.DIRECTORY_PICTURES) ?: File(cacheDir, Environment.DIRECTORY_PICTURES).apply { mkdirs() }
val videoFile = File(path, "lottie_in_video.mp4")
val recordingOperation = RecordingOperation(Recorder(videoOutput = videoFile), FrameCreator(lottieDrawable))
{
textView.text = getString(R.string.recording_finished)
openCreatedVideo(videoFile)
}
then call on save button
recordingOperation.start()
refrence : https://github.com/rogererill/LottieRecorderTest
I want to create animated splash screen using gif image. I have used Glide library because it supports gif images.
I have done following things to achieve this:
Created splash.xml with an imageview in it.
<ImageView
android:id="#+id/iv_gif_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
Inside SplashActivity.java
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
ImageView ivImage = (ImageView) findViewById(R.id.iv_gif_view);
Glide.with(this).load(R.drawable.splash_xxhdpi_2)
.asGif().into(ivImage);
}
But when I run the application screen goes black nothing appears on the screen. I'm using Glide compile 'com.github.bumptech.glide:glide:3.6.1'
You can try this way
public class GifImageView extends View {
private InputStream mInputStream;
private Movie mMovie;
private int mWidth, mHeight;
private long mStart;
private Context mContext;
public GifImageView(Context context) {
super(context);
this.mContext = context;
}
public GifImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public GifImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.mContext = context;
if (attrs.getAttributeName(1).equals("background")) {
int id = Integer.parseInt(attrs.getAttributeValue(1).substring(1));
setGifImageResource(id);
}
}
private void init() {
setFocusable(true);
mMovie = Movie.decodeStream(mInputStream);
mWidth = mMovie.width();
mHeight = mMovie.height();
requestLayout();
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(mWidth, mHeight);
}
#Override
protected void onDraw(Canvas canvas) {
long now = SystemClock.uptimeMillis();
if (mStart == 0) {
mStart = now;
}
if (mMovie != null) {
int duration = mMovie.duration();
if (duration == 0) {
duration = 1000;
}
int relTime = (int) ((now - mStart) % duration);
mMovie.setTime(relTime);
mMovie.draw(canvas, 0, 0);
invalidate();
}
}
public void setGifImageResource(int id) {
mInputStream = mContext.getResources().openRawResource(id);
init();
}
public void setGifImageUri(Uri uri) {
try {
mInputStream = mContext.getContentResolver().openInputStream(uri);
init();
} catch (FileNotFoundException e) {
Log.e("GIfImageView", "File not found");
}
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
GifImageView gifImageView = (GifImageView) findViewById(R.id.GifImageView);
gifImageView.setGifImageResource(R.drawable.android);
}
}
http://www.mavengang.com/2016/05/02/gif-animation-android/
http://www.geeks.gallery/how-to-display-the-animated-gif-image-in-android/
Android does not support GIF so avoid using it since it is memory consuming. Glide is nice image caching library and luckily it supports gif images.
I'm sharing alternate and efficient way to achieve animated splash screen.
Create splash.xml as usual with an image view.
Take out each frame from your gif image. I have used splash_hdpi_1, splash_hdpi_2, splash_hdpi_3 for example.
create splash_gif_animation.xml in drawable with below code
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false" >
<item
android:drawable="#drawable/splash_hdpi_1"
android:duration="150"/>
<item
android:drawable="#drawable/splash_hdpi_2"
android:duration="150"/>
<item
android:drawable="#drawable/splash_hdpi_3"
android:duration="150"/>
</animation-list>
In your SplashActivity.java put below code
ImageView ivImage = (ImageView) findViewById(R.id.your_image_view);
ivImage.setBackgroundResource(R.drawable.splash_gif_animation);
AnimationDrawable splashAnimation = (AnimationDrawable) ivImage.getBackground();
splashAnimation.start();
You are done:)
Try this:
ImageView ivImage= (ImageView) findViewById(R.id.iv_gif_view);
GlideDrawableImageViewTarget imageViewTarget = new GlideDrawableImageViewTarget(ivImage);
Glide.with(this)
.load(R.drawable.splash_xxhdpi_2)
.into(imageViewTarget);
I created a custom ImageView - it's purpose is to fetch image from internet. It's declaration looks as below:
public class WebImageView extends ImageView {
private String mUrl;
private Bitmap mCachedBitmap;
public String getUrl() { return mUrl; }
public void setUrl(String url) {
mUrl = url;
if (mCachedImage == null) {
new ImageDownloader(this).execute(mUrl);
} else {
setImageBitmap(mCachedImage);
}
}
public WebImageView(Context context) {
super(context);
}
public WebImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public WebImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public WebImageView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
private class ImageDownloader extends AsyncTask<String, Void, Bitmap> {
private final ImageView mView;
public ImageDownloader(ImageView view) {
mView = view;
}
#Override
protected Bitmap doInBackground(String... params) {
String url = params[0];
Bitmap image = null;
try {
InputStream in = new java.net.URL(url).openStream();
image = BitmapFactory.decodeStream(in);
} catch (Exception e) {
Log.e("Error Message", e.getMessage());
e.printStackTrace();
}
return image;
}
protected void onPostExecute(Bitmap result) {
mView.setImageBitmap(result);
}
}
}
And it's usage is pretty straightforward:
<com.myapp.views.controls.WebImageView
android:layout_width="#dimen/restaurantLogoWidth"
android:layout_height="#dimen/restaurantLogoHeight"
url="#{restaurant.model.logoUrl}"
style="#style/ImageView" />
The above xml is placed inside a android.support.v7.widget.RecyclerView. The problem is that when I scroll (or perform some animation) on my items list it performs horribly bad, meaning that scrolling (or animating) is not smooth. Any advice what can I change here to make it perform better?
Don't build a custom view to do this. Just use Glide image loading library.
https://github.com/bumptech/glide
ImageView targetImageView = (ImageView) findViewById(R.id.imageView);
String internetUrl = "http://i.imgur.com/DvpvklR.png";
Glide
.with(context)
.load(internetUrl)
.into(targetImageView);
https://futurestud.io/tutorials/glide-getting-started
Recyclerview Adapter and Glide - same image every 4-5 rows
I got a bunch of drawables that I want to load using fresco, I want to use wrap_content size for those images, how can I do it in xml with fresco? Or if xml is not possible how do you do it in code?
<com.facebook.drawee.view.SimpleDraweeView
android:id="#+id/myImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
fresco:placeholderImage="#mipmap/myImage"/>
The above code is not working unless I set a fixed size.
I am part of the Fresco team and I was the one who made the design decision to not support wrap-content. The rationale is explained in the documentation. But in short, the problem is that you can't guarantee that the image will be available immediately (you may need to fetch it first) and that means that the view size would have to change once the image arrives. This is in most cases not desirable and you should probably rethink your UI.
Anyways, if you really really need/want to do that, you can do it like this:
void updateViewSize(#Nullable ImageInfo imageInfo) {
if (imageInfo != null) {
draweeView.getLayoutParams().width = imageInfo.getWidth();
draweeView.getLayoutParams().height = ViewGroup.LayoutParams.WRAP_CONTENT;
draweeView.setAspectRatio((float) imageInfo.getWidth() / imageInfo.getHeight());
}
}
ControllerListener listener = new BaseControllerListener {
#Override
public void onIntermediateImageSet(String id, #Nullable ImageInfo imageInfo) {
updateViewSize(imageInfo);
}
#Override
public void onFinalImageSet(String id, #Nullable ImageInfo imageInfo, #Nullable Animatable animatable) {
updateViewSize(imageInfo);
}
};
DraweeController controller = draweeControllerBuilder
.setUri(uri)
.setControllerListener(listener)
.build();
draweeView.setController(controller);
I wrote this code from the top of my head, I haven't actually tested it. But the idea should be clear, and it should work with minor adjustments.
Based on #plamenko's answer, I made a custom view as follows:
/**
* Works when either height or width is set to wrap_content
* The view is resized based on the image fetched
*/
public class WrapContentDraweeView extends SimpleDraweeView {
// we set a listener and update the view's aspect ratio depending on the loaded image
private final ControllerListener listener = new BaseControllerListener<ImageInfo>() {
#Override
public void onIntermediateImageSet(String id, #Nullable ImageInfo imageInfo) {
updateViewSize(imageInfo);
}
#Override
public void onFinalImageSet(String id, #Nullable ImageInfo imageInfo, #Nullable Animatable animatable) {
updateViewSize(imageInfo);
}
};
public WrapContentDraweeView(Context context, GenericDraweeHierarchy hierarchy) {
super(context, hierarchy);
}
public WrapContentDraweeView(Context context) {
super(context);
}
public WrapContentDraweeView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public WrapContentDraweeView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public WrapContentDraweeView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
#Override
public void setImageURI(Uri uri, Object callerContext) {
DraweeController controller = ((PipelineDraweeControllerBuilder)getControllerBuilder())
.setControllerListener(listener)
.setCallerContext(callerContext)
.setUri(uri)
.setOldController(getController())
.build();
setController(controller);
}
void updateViewSize(#Nullable ImageInfo imageInfo) {
if (imageInfo != null) {
setAspectRatio((float) imageInfo.getWidth() / imageInfo.getHeight());
}
}
}
You can include this class in the XML, an example usage:
<com.example.ui.views.WrapContentDraweeView
android:id="#+id/simple_drawee_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
In Kotlin you can try something like this :
val listener = object : BaseControllerListener<ImageInfo>() {
override fun onFinalImageSet(id: String?, imageInfo: ImageInfo?, animatable: Animatable?) {
super.onFinalImageSet(id, imageInfo, animatable)
itemView.draweeGif.layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT
itemView.draweeGif.aspectRatio = (imageInfo?.width?.toFloat() ?: 0.toFloat()) / (imageInfo?.height?.toFloat() ?: 0.toFloat())
}
}
val controller = Fresco.newDraweeControllerBuilder()
.setUri(uriGif)
.setControllerListener(listener)
.setAutoPlayAnimations(true)
.build()
itemView.draweeGif.controller = controller
For me it was a solution in my RecyclerView because I was looking to set the layoutParams directly in my ViewHolder.
Found a solution by extending SimpleDraweeView, it allows me to use wrap_content and it works just fine! How ever I prevent you from setting the size in setContentView and the preview is not working, I be glad if could edit this answer to fix those.
Usage
<com.gazman.WrapContentDraweeView
android:id="#+id/myImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
fresco:placeholderImage="#mipmap/myImage"/>
Source code
public class WrapContentDraweeView extends SimpleDraweeView {
private int outWidth;
private int outHeight;
public WrapContentDraweeView(Context context, GenericDraweeHierarchy hierarchy) {
super(context, hierarchy);
}
public WrapContentDraweeView(Context context) {
super(context);
}
public WrapContentDraweeView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public WrapContentDraweeView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context, attrs);
}
public WrapContentDraweeView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
if (attrs == null) {
return;
}
TypedArray gdhAttrs = context.obtainStyledAttributes(
attrs,
R.styleable.GenericDraweeView);
try {
int placeholderId = gdhAttrs.getResourceId(
R.styleable.GenericDraweeView_placeholderImage,
0);
if(placeholderId != 0){
if(isInEditMode()){
setImageResource(placeholderId);
}
else {
loadSize(placeholderId, context.getResources());
}
}
} finally {
gdhAttrs.recycle();
}
}
private void loadSize(int placeholderId, Resources resources) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(resources, placeholderId, options);
outWidth = options.outWidth;
outHeight = options.outHeight;
}
#Override
public void setLayoutParams(ViewGroup.LayoutParams params) {
params.width = outWidth;
params.height = outHeight;
super.setLayoutParams(params);
}
}
invoke updateWrapSize in onFinalImageSet
void updateWrapSize(#Nullable ImageInfo imageInfo) {
if (imageInfo != null) {
boolean wrapH = getLayoutParams().height == ViewGroup.LayoutParams.WRAP_CONTENT;
boolean wrapW = getLayoutParams().width == ViewGroup.LayoutParams.WRAP_CONTENT;
if (wrapH || wrapW) {
if (wrapW && !wrapH) {
getLayoutParams().width = (int) (imageInfo.getWidth() * (float) getLayoutParams().height / imageInfo.getHeight());
} else if (wrapH && !wrapW) {
getLayoutParams().height = (int) (imageInfo.getHeight() * (float) getLayoutParams().width / imageInfo.getWidth());
} else {
getLayoutParams().width = ViewGroup.LayoutParams.WRAP_CONTENT;
getLayoutParams().height = ViewGroup.LayoutParams.WRAP_CONTENT;
}
setAspectRatio((float) imageInfo.getWidth() / imageInfo.getHeight());
}
}
}
I am developing a GifView class, extending android.view.ImageView to show an animation gif in Android.
The problem is getting android:src="#drawable/myGif" from XML layout to load it in Movie automatically. When I override setImageDrawable(Drawable drawable) to intercept default android behaviour, I have two differents ways to do it: getting the id resource from #drawable/myGif and save it for later use, or load it on demand in Movie. But with the latter option I need to convert Drawable in InputStream unused compress method from Bitmap class to can safe GIF layers.
How can I do it?
public class GifView extends ImageView {
...
private Movie movie;
private int resId;
public GifView(Context context) {
super(context);
this.context = context;
}
public GifView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
}
public GifView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.context = context;
}
#Override
public void setImageDrawable(Drawable drawable) {
// ONE OF THOSE WAYS TO DO
// this.redId = ...
// this.movie = Movie.decodeStream(...);
}
...
}
ok, you can do it automatically, but does it really pay of?
public class GifImageView extends ImageView {
private final static String TAG = "GifImageView";
public GifImageView(Context context, AttributeSet attrs) {
super(context, attrs);
int[] attrArray = {
android.R.attr.src
};
TypedArray a = context.obtainStyledAttributes(attrs, attrArray);
int id = a.getResourceId(0, 0);
a.recycle();
if (id != 0) {
try {
Drawable d = new GifDrawable(getResources(), id);
setImageDrawable(d);
} catch (Exception e) {
Log.d(TAG, "GifImageView " + e.getMessage());
}
}
}
class GifDrawable extends Drawable implements Runnable {
...
}
}