I have an Android application that shows a screen with an animated GIF image while it's loading. The image gets displayed forever or shown only a blank screen if I use a timer. I just want to show it for 5 seconds. How can I displaying the GIF only by 5 seconds?
With this code the image gets displayed forever:
public class MainActivity extends AppCompatActivity {
public GifImageView gifImageView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
gifImageView = (GifImageView) findViewById(R.id.GifImageView);
gifImageView.setGifImageResource(R.drawable.gif2);
}
}
With this code the gif image is not shown only a blank screen is shown but after 5 seconds the application closes:
public class MainActivity extends AppCompatActivity {
public GifImageView gifImageView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
gifImageView = (GifImageView) findViewById(R.id.GifImageView);
startCountDownTimer();
}
private void startCountDownTimer() {
new CountDownTimer( 5000, 5000 ) {
public void onTick(long millisUntilFinished) {
gifImageView.setGifImageResource(R.drawable.gif2);
}
public void onFinish() {
finish();
}
}.start();
}
}
Here is the GifImageView code:
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();
}
You can use a CountDownTimer, set the time to 5000 milliseconds. When onFinish() is called you can stop displaying the GIF. Use this code:
new CountDownTimer(5000, 5000) {
public void onTick(long millisUntilFinished) {
// You don't need to use this.
}
public void onFinish() {
// Put the code to stop the GIF here.
}
}.start();
You can read more about CountDownTimers in the documentation.
With what #AmeerTaweel told, you can use a CountDownTimer. Another simple approach would be to use a Handler for that in the onCreate() method like this:
new Handle().postDelayed(new Runnable(
#Override
public void run() {
ImageView.setVisibility(View.GONE); //Or the GIF View
}
), 5000); //5 sec
Related
I want to play a video in full screen in a videoview and after some time I want to crop to a circular view?
How can I achieve that ?
There is a better way.
You can create a custom SurfaceView. Which actually clips the view in circular shape. And from this custom view you can set display to MediaPlayer object.
public class VideoSurfaceView extends SurfaceView {
private final static String TAG = "VideoSurfaceView";
private Path clipPath;
private boolean isCircular;
public VideoSurfaceView(Context context) {
super(context);
init();
}
public VideoSurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public VideoSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
clipPath = new Path();
}
#Override
protected void dispatchDraw(Canvas canvas) {
if (this.isCircular)
canvas.clipPath(clipPath);
super.dispatchDraw(canvas);
}
/**
* Crops the view in circular shape
* #param centerX
* #param centerY
* #param radius
*/
public void cropCircle(float centerX, float centerY, int radius) {
Log.i(TAG, "cropCircle: x=" + centerX + " ,y= " + centerY + ", radius=" + radius);
clipPath.addCircle(centerX, centerY, radius, Path.Direction.CW);
}
/**
* Sets the flag for cropping the view in circular shape
* #param isCircular
*/
public void setCircular(boolean isCircular) {
this.isCircular = isCircular;
invalidate();
}
}
In your activity you can implement SurfaceHolder.Callback & set MediaPlayer's display in overridden method.
public class MainActivity extends AppCompatActivity implements MediaPlayer.OnCompletionListener, SurfaceHolder.Callback {
private final static String TAG = "MainActivity";
#BindView(R.id.activity_main_video_surface_view)
protected VideoSurfaceView videoView;
private Handler handler;
private boolean inCircleMode;
private final static int CIRCULAR_INTERVAL = 5000;
private final static int MINIMUM_CARD_HEIGHT = 300;
private final static int MAXIMUM_CARD_HEIGHT = 500;
//Parameters for video view.
private int cropCenterX;
private int cropCenterY;
private int cropRadius;
private int croppedLayoutWidth;
private int croppedLayoutHeight;
private int fullLayoutWidth;
private int fullLayoutHeight;
private MediaPlayer player;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
initParameters();
}
/**
* Initialise the parameters used.
*/
private void initParameters() {
SurfaceHolder holder = videoView.getHolder();
holder.addCallback(this);
player = MediaPlayer.create(this, R.raw.bird_s);
player.setOnCompletionListener(this);
//Setting the video with proper aspect ratio.
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int height = displayMetrics.heightPixels;
int width = displayMetrics.widthPixels;
int dimenFull[] = Utility.getVideoDimensions(player, width, height);
fullLayoutWidth = dimenFull[0];
fullLayoutHeight = dimenFull[1];
setVideoLayout();
}
//Runnable for switching the views from circular video to full screen video.
private Runnable runnable = new Runnable() {
#Override
public void run() {
inCircleMode = !inCircleMode;
setVideoLayout();
handler.postDelayed(runnable, CIRCULAR_INTERVAL);
}
};
/**
* Calculates the dimensions required for cropped video view.
*/
private void calculateCroppedParams() {
int dimen[] = Utility.getVideoDimensions(player, 100, 100);
croppedLayoutWidth = dimen[0];
croppedLayoutHeight = dimen[1];
cropRadius = croppedLayoutWidth / 2;
cropCenterX = cropRadius;
cropCenterY = cropRadius;
}
/**
* Change the layout dimensions for video view.
*/
private void setVideoLayout() {
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) videoView.getLayoutParams();
//Changing the margin, width & height of videoView.
layoutParams.setMargins(0, inCircleMode ? cardView.getVideoMargin() : 0, 0, 0);
layoutParams.width = inCircleMode ? croppedLayoutWidth : fullLayoutWidth;
layoutParams.height = inCircleMode ? croppedLayoutHeight : fullLayoutHeight;
layoutParams.addRule(inCircleMode ? RelativeLayout.CENTER_HORIZONTAL : RelativeLayout.CENTER_IN_PARENT);
videoView.cropCircle(cropCenterX, cropCenterY, cropRadius);
videoView.setCircular(inCircleMode);
videoView.setLayoutParams(layoutParams);
}
#Override
public void onCompletion(MediaPlayer mediaPlayer) {
}
#Override
public void onLayout() {
Log.i(TAG, "onLayout: starting runnable");
calculateCroppedParams();
player.start();
}
#Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
player.setDisplay(surfaceHolder);
}
#Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
}
#Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
}
#Override
protected void onStop() {
Log.i(TAG, "onStop");
super.onStop();
}
#Override
protected void onRestart() {
super.onRestart();
}
#Override
protected void onPause() {
super.onPause();
if (player != null && player.isPlaying())
player.pause();
}
#Override
protected void onResume() {
super.onResume();
if (player != null && !player.isPlaying())
player.start();
}
}
For more details on how to crop the video in different shapes, please check my blog post VideoInShapes.
Another way is put this type of image overlay on your videoview Relative or FrameLayout (Circuler is transprent so videoview will visible only in circle)
By default make visibility GONE this imageView and Change VISIBLE it runtime when you want.
I want to expand the view on clicking the + button and this + sign changes to - when the view expanded.Again when i click the - button the view should be shrink.
Inside the view i have some TextView field.Please anyone suggest me.I am new to android.
This answer solves the question.
public class ExpandableTextView extends TextView implements OnClickListener
{
private static final int MAX_LINES = 5;
private int currentMaxLines = Integer.MAX_VALUE;
public ExpandableTextView(Context context)
{
super(context);
setOnClickListener(this);
}
public ExpandableTextView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
setOnClickListener(this);
}
public ExpandableTextView(Context context, AttributeSet attrs)
{
super(context, attrs);
setOnClickListener(this);
}
#Override
protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter)
{
/* If text longer than MAX_LINES set DrawableBottom - I'm using '...' icon */
post(new Runnable()
{
public void run()
{
if (getLineCount()>MAX_LINES)
setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, R.drawable.icon_more_text);
else
setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
setMaxLines(MAX_LINES);
}
});
}
#Override
public void setMaxLines(int maxLines)
{
currentMaxLines = maxLines;
super.setMaxLines(maxLines);
}
/* Custom method because standard getMaxLines() requires API > 16 */
public int getMyMaxLines()
{
return currentMaxLines;
}
#Override
public void onClick(View v)
{
/* Toggle between expanded collapsed states */
if (getMyMaxLines() == Integer.MAX_VALUE)
setMaxLines(MAX_LINES);
else
setMaxLines(Integer.MAX_VALUE);
}
}
You can visible or gone particular layout on button click event at runtime like below code:
findViewById(R.id.yourButtonId).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mainView.setVisibility(View.GONE);
}
});
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'm trying to make a customview that displays multiple images into one view with Fresco. I've read the docs and went through some steps but my implementation doesn't seem to work. Here's the code:
public class MultiDraweeView extends View {
private static final int MAX_COUNT = 4;
private MultiDraweeHolder<GenericDraweeHierarchy> multiDraweeHolder;
private ArrayList<GenericDraweeHierarchy> hierarchies;
public MultiDraweeView(Context context) {
super(context);
init();
}
public MultiDraweeView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public MultiDraweeView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
multiDraweeHolder = new MultiDraweeHolder<>();
hierarchies = new ArrayList<>();
for (int i = 0; i < MAX_COUNT; i++) {
hierarchies.add(new GenericDraweeHierarchyBuilder(getResources())
.build());
}
}
public void setImageUris(Uri... uris) {
multiDraweeHolder.clear();
for (int i = 0; i < (uris.length < MAX_COUNT ? uris.length : MAX_COUNT); i++) {
final int j = i;
final DraweeHolder<GenericDraweeHierarchy> draweeHolder = DraweeHolder.create(hierarchies.get(i), getContext());
DraweeController controller = Fresco.newDraweeControllerBuilder()
.setUri(Uri.parse("http://www.thewrap.com/wp-content/uploads/2015/11/Donald-Trump.jpg"))
.setOldController(draweeHolder.getController())
.setControllerListener(new ControllerListener<ImageInfo>() {
#Override
public void onSubmit(String id, Object callerContext) {
Log.e("fresco" + j, "onSubmit");
}
#Override
public void onFinalImageSet(String id, ImageInfo imageInfo, Animatable animatable) {
Log.e("fresco" + j, "onFinalImageset");
invalidate();
}
#Override
public void onIntermediateImageSet(String id, ImageInfo imageInfo) {
Log.e("fresco" + j, "onIntermediateImageSet");
}
#Override
public void onIntermediateImageFailed(String id, Throwable throwable) {
Log.e("fresco" + j, "onIntermediateImageFailed");
}
#Override
public void onFailure(String id, Throwable throwable) {
Log.e("fresco" + j, "onFailure");
}
#Override
public void onRelease(String id) {
Log.e("fresco" + j, "onRelease");
}
})
.build();
draweeHolder.setController(controller);
multiDraweeHolder.add(draweeHolder);
}
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.e("fresco", "ondraw");
for (int i = 0; i < multiDraweeHolder.size(); i++) {
Drawable drawable = multiDraweeHolder.get(i).getTopLevelDrawable();
drawable.setBounds(50 * i, 50 * i, 50 * (i + 1), 50 * (i + 1));
drawable.draw(canvas);
}
}
#Override
protected boolean verifyDrawable(#NonNull Drawable who) {
return multiDraweeHolder.verifyDrawable(who);
}
#Override
public void onDetachedFromWindow() {
super.onDetachedFromWindow();
multiDraweeHolder.onDetach();
}
#Override
public void onStartTemporaryDetach() {
super.onStartTemporaryDetach();
multiDraweeHolder.onDetach();
}
#Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
multiDraweeHolder.onAttach();
}
#Override
public void onFinishTemporaryDetach() {
super.onFinishTemporaryDetach();
multiDraweeHolder.onAttach();
}
}
The logic behind my code is to invalidate the view as soon as the image downloads inonFinalImageSetso it redraws. But the Drawables are not drawing. If then i send the app to the background and open it again so onStart is called again, the Drawables show. Am I missing something here, or is there any example of a custom DraweView that extends View and not ImageView?
You need to set the Drawable.Callback as described here: http://frescolib.org/docs/writing-custom-views.html
Also, make sure that the callback actually invalidates the correct are. If you invalidate the wrong one, it won't work either.
I click dice button in arenalayout.xml (this xml is displayed by 'ArenaLayout' class). But canvas doesn't draw char 2.I want to... if I click dice button then I draw char 2.
Note : After I click dice button, value of 'haveFirstDiced' variable in Arena class change to TRUE. There's condition inside of onDraw in 'Arena' class. . . if 'haveFirstDiced' variable have TRUE value then drawing char 2.
public class ArenaLayout extends Activity {
private Arena arena;
ImageButton diceButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.arena_layout);
diceButton = (ImageButton) findViewById(R.id.dice);
dice();
}
private void dice() {
diceButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
arena.dicing();
}
});
}
}
This is 'Arena' class :
public class Arena extends View{
private Paint p;
private Handler threadHandler = new Handler();
private Bitmap char1;
private float x = 20, y = 300;
Canvas c;
boolean haveFirstDiced = false;
public Arena(Context context, AttributeSet aSet) {
super(context, aSet);
p = new Paint();
}
public void dicing() {
new Thread(new XXX()).start();
}
#Override
synchronized public void onDraw(Canvas canvas) {
char2 = BitmapFactory.decodeResource(getResources(), R.drawable.char_2);
if(haveFirstDiced == true) {
canvas.drawBitmap(char2,x,y,null);
}
}
class XXX implements Runnable {
#Override
public void run() {
threadHandler.post(new Runnable() {
#Override
public void run() {
haveFirstDiced = true;
}
});
}
}
}
This is the most convoluted solution I've ever seen. There's no need for a thread, a runnable, or for onDraw to be synchronized. Here's what it should be:
private void dice() {
diceButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
arena.dicing();
}
});
}
public class Arena extends View{
private Paint p;
private Handler threadHandler = new Handler();
private Bitmap char2;
private float x = 20, y = 300;
Canvas c;
boolean haveFirstDiced = false;
public Arena(Context context, AttributeSet aSet) {
super(context, aSet);
p = new Paint();
char2 = BitmapFactory.decodeResource(getResources(), R.drawable.char_2);
}
public void dicing() {
haveFirstDiced = true;
invalidate();
}
#Override
public void onDraw(Canvas canvas) {
if(haveFirstDiced == true) {
canvas.drawBitmap(char2,x,y,null);
}
}
}