KenBurnsView Splash creen

This is the second part of  How to add Splash Screen in Android With KenBurnsView. If you didn’t read Part I please read it HERE before proceeding to Part II.

NOTE: In this post we deal with mostly Java files. When copying code please remove entire code in your java files before pasting codes from here. And also change package names when ever needed. you may see errors after pasting the codes, don’t worry by the end all errors will be gone. You just follow the procedure here ignoring the errors.

  • Now create a new java file in you project with Name IncompatibleRatioException.java and paste below code
package com.karthik.kenburnsview;

public class IncompatibleRatioException extends RuntimeException {

private static final long serialVersionUID = 234608108593115395L;

public IncompatibleRatioException() {
super("Can't perform Ken Burns effect on rects with distinct aspect ratios!");
}
}
  • In above code change Package Name com.karthik.kenburnsview in first line to your package name
  • Next create KenBurnsView.java file and add below code to that file.
package com.karthik.kenburnsview;

/**
* Created by Karthik's on 27-02-2016.
*/
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.util.AttributeSet;
import android.widget.ImageView;

/**
* {@link ImageView} extension that animates its image with the
* <a href="http://en.wikipedia.org/wiki/Ken_Burns_effect">Ken Burns Effect</a>.
* @author Flavio Faria
* @see Transition
* @see TransitionGenerator
*/
public class KenBurnsView extends ImageView {

/** Delay between a pair of frames at a 60 FPS frame rate. */
private static final long FRAME_DELAY = 1000 / 60;

/** Matrix used to perform all the necessary transition transformations. */
private final Matrix mMatrix = new Matrix();

/** The {@link TransitionGenerator} implementation used to perform the transitions between
* rects. The default {@link TransitionGenerator} is {@link RandomTransitionGenerator}. */
private TransitionGenerator mTransGen = new RandomTransitionGenerator();

/** A {@link TransitionListener} to be notified when
* a transition starts or ends. */
private TransitionListener mTransitionListener;

/** The ongoing transition. */
private Transition mCurrentTrans;

/** The rect that holds the bounds of this view. */
private final RectF mViewportRect = new RectF();
/** The rect that holds the bounds of the current {@link Drawable}. */
private RectF mDrawableRect;

/** The progress of the animation, in milliseconds. */
private long mElapsedTime;

/** The time, in milliseconds, of the last animation frame.
* This is useful to increment {@link #mElapsedTime} regardless
* of the amount of time the animation has been paused. */
private long mLastFrameTime;

/** Controls whether the the animation is running. */
private boolean mPaused;

/** Indicates whether the parent constructor was already called.
* This is needed to distinguish if the image is being set before
* or after the super class constructor returns. */
private boolean mInitialized;


public KenBurnsView(Context context) {
this(context, null);
}


public KenBurnsView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}


public KenBurnsView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mInitialized = true;
// Attention to the super call here!
super.setScaleType(ScaleType.MATRIX);
}


@Override
public void setScaleType(ScaleType scaleType) {
// It'll always be center-cropped by default.
}


@Override
public void setVisibility(int visibility) {
super.setVisibility(visibility);
/* When not visible, onDraw() doesn't get called,
but the time elapses anyway. */
switch (visibility) {
case VISIBLE:
resume();
break;
default:
pause();
break;
}
}


@Override
public void setImageBitmap(Bitmap bm) {
super.setImageBitmap(bm);
handleImageChange();
}


@Override
public void setImageResource(int resId) {
super.setImageResource(resId);
handleImageChange();
}


@Override
public void setImageURI(Uri uri) {
super.setImageURI(uri);
handleImageChange();
}


@Override
public void setImageDrawable(Drawable drawable) {
super.setImageDrawable(drawable);
handleImageChange();
}


@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
restart();
}


@Override
protected void onDraw(Canvas canvas) {
Drawable d = getDrawable();
if (!mPaused && d != null) {
if (mDrawableRect.isEmpty()) {
updateDrawableBounds();
} else if (hasBounds()) {
if (mCurrentTrans == null) { // Starting the first transition.
startNewTransition();
}

if (mCurrentTrans.getDestinyRect() != null) { // If null, it's supposed to stop.
mElapsedTime += System.currentTimeMillis() - mLastFrameTime;
RectF currentRect = mCurrentTrans.getInterpolatedRect(mElapsedTime);

float widthScale = mDrawableRect.width() / currentRect.width();
float heightScale = mDrawableRect.height() / currentRect.height();
// Scale to make the current rect match the smallest drawable dimension.
float currRectToDrwScale = Math.min(widthScale, heightScale);
// Scale to make the current rect match the viewport bounds.
float currRectToVpScale = mViewportRect.width() / currentRect.width();
// Combines the two scales to fill the viewport with the current rect.
float totalScale = currRectToDrwScale * currRectToVpScale;

float translX = totalScale * (mDrawableRect.centerX() - currentRect.left);
float translY = totalScale * (mDrawableRect.centerY() - currentRect.top);

/* Performs matrix transformations to fit the content
of the current rect into the entire view. */
mMatrix.reset();
mMatrix.postTranslate(-mDrawableRect.width() / 2, -mDrawableRect.height() / 2);
mMatrix.postScale(totalScale, totalScale);
mMatrix.postTranslate(translX, translY);

setImageMatrix(mMatrix);

// Current transition is over. It's time to start a new one.
if (mElapsedTime >= mCurrentTrans.getDuration()) {
fireTransitionEnd(mCurrentTrans);
startNewTransition();
}
} else { // Stopping? A stop event has to be fired.
fireTransitionEnd(mCurrentTrans);
}
}
mLastFrameTime = System.currentTimeMillis();
postInvalidateDelayed(FRAME_DELAY);
}
super.onDraw(canvas);
}


/**
* Generates and starts a transition.
*/
private void startNewTransition() {
if (!hasBounds()) {
throw new UnsupportedOperationException("Can't start transition if the " +
"drawable has no bounds!");
}
mCurrentTrans = mTransGen.generateNextTransition(mDrawableRect, mViewportRect);
mElapsedTime = 0;
mLastFrameTime = System.currentTimeMillis();
fireTransitionStart(mCurrentTrans);
}


/**
* Creates a new transition and starts over.
*/
public void restart() {
int width = getWidth();
int height = getHeight();

if (width == 0 || height == 0) {
throw new UnsupportedOperationException("Can't call restart() when view area is zero!");
}

updateViewport(width, height);
updateDrawableBounds();

if (hasBounds()) {
startNewTransition();
}
}


/**
* Checks whether this view has bounds.
* @return
*/
private boolean hasBounds() {
return !mViewportRect.isEmpty();
}


/**
* Fires a start event on {@link #mTransitionListener};
* @param transition the transition that just started.
*/
private void fireTransitionStart(Transition transition) {
if (mTransitionListener != null && transition != null) {
mTransitionListener.onTransitionStart(transition);
}
}


/**
* Fires an end event on {@link #mTransitionListener};
* @param transition the transition that just ended.
*/
private void fireTransitionEnd(Transition transition) {
if (mTransitionListener != null && transition != null) {
mTransitionListener.onTransitionEnd(transition);
}
}


/**
* Sets the {@link TransitionGenerator} to be used in animations.
* @param transgen the {@link TransitionGenerator} to be used in animations.
*/
public void setTransitionGenerator(TransitionGenerator transgen) {
mTransGen = transgen;
if (hasBounds()) {
startNewTransition();
}
}


/**
* Updates the viewport rect. This must be called every time the size of this view changes.
* @param width the new viewport with.
* @param height the new viewport height.
*/
private void updateViewport(float width, float height) {
mViewportRect.set(0, 0, width, height);
}


/**
* Updates the drawable bounds rect. This must be called every time the drawable
* associated to this view changes.
*/
private void updateDrawableBounds() {
if (mDrawableRect == null) {
mDrawableRect = new RectF();
}
Drawable d = getDrawable();
if (d != null) {
mDrawableRect.set(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
}
}


/**
* This method is called every time the underlying image
* is changed.
*/
private void handleImageChange() {
updateDrawableBounds();
/* Don't start a new transition if this event
was fired during the super constructor execution.
The view won't be ready at this time. Also,
don't start it if this view size is still unknown. */
if (mInitialized && hasBounds()) {
startNewTransition();
}
}


public void setTransitionListener(TransitionListener transitionListener) {
mTransitionListener = transitionListener;
}


/**
* Pauses the Ken Burns Effect animation.
*/
public void pause() {
mPaused = true;
}


/**
* Resumes the Ken Burns Effect animation.
*/
public void resume() {
mPaused = false;
// This will make the animation to continue from where it stopped.
mLastFrameTime = System.currentTimeMillis();
invalidate();
}


/**
* A transition listener receives notifications when a transition starts or ends.
*/
public interface TransitionListener {
/**
* Notifies the start of a transition.
* @param transition the transition that just started.
*/
public void onTransitionStart(Transition transition);

/**
* Notifies the end of a transition.
* @param transition the transition that just ended.
*/
public void onTransitionEnd(Transition transition);
}
}
  • In above code Change Package name in first line com.karthik.kenburnsview to your package name
  • Next create another java file with Name MathUtils.java and add below code.
package com.karthik.kenburnsview;

/*
* Copyright 2014 Flavio Faria
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/


import android.graphics.RectF;

/**
* Helper class to perform math computations.
*/
public final class MathUtils {

/**
* Truncates a float number {@code f} to {@code decimalPlaces}.
* @param f the number to be truncated.
* @param decimalPlaces the amount of decimals that {@code f}
* will be truncated to.
* @return a truncated representation of {@code f}.
*/
protected static float truncate(float f, int decimalPlaces) {
float decimalShift = (float) Math.pow(10, decimalPlaces);
return Math.round(f * decimalShift) / decimalShift;
}


/**
* Checks whether two {@link RectF} have the same aspect ratio.
* @param r1 the first rect.
* @param r2 the second rect.
* @return {@code true} if both rectangles have the same aspect ratio,
* {@code false} otherwise.
*/
protected static boolean haveSameAspectRatio(RectF r1, RectF r2) {
// Reduces precision to avoid problems when comparing aspect ratios.
float srcRectRatio = MathUtils.truncate(MathUtils.getRectRatio(r1), 2);
float dstRectRatio = MathUtils.truncate(MathUtils.getRectRatio(r2), 2);

// Compares aspect ratios that allows for a tolerance range of [0, 0.01] 
return (Math.abs(srcRectRatio - dstRectRatio) <= 0.01f);
}


/**
* Computes the aspect ratio of a given rect.
* @param rect the rect to have its aspect ratio computed.
* @return the rect aspect ratio.
*/
protected static float getRectRatio(RectF rect) {
return rect.width() / rect.height();
}
}
  • In above code Change Package name in first line com.karthik.kenburnsview to your package name
  • Next create another java file with Name RandomTransitionGenerator.java and add below code.
package com.karthik.kenburnsview;
/*
* Copyright 2014 Flavio Faria
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/


import android.graphics.RectF;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Interpolator;

import java.util.Random;

public class RandomTransitionGenerator implements com.kenburnsview.TransitionGenerator {

/** Default value for the transition duration in milliseconds. */
public static final int DEFAULT_TRANSITION_DURATION = 10000;

/** Minimum rect dimension factor, according to the maximum one. */
private static final float MIN_RECT_FACTOR = 0.75f;

/** Random object used to generate arbitrary rects. */
private final Random mRandom = new Random(System.currentTimeMillis());

/** The duration, in milliseconds, of each transition. */
private long mTransitionDuration;

/** The {@link Interpolator} to be used to create transitions. */
private Interpolator mTransitionInterpolator;

/** The last generated transition. */
private Transition mLastGenTrans;

/** The bounds of the drawable when the last transition was generated. */
private RectF mLastDrawableBounds;


public RandomTransitionGenerator() {
this(DEFAULT_TRANSITION_DURATION, new AccelerateDecelerateInterpolator());
}


public RandomTransitionGenerator(long transitionDuration, Interpolator transitionInterpolator) {
setTransitionDuration(transitionDuration);
setTransitionInterpolator(transitionInterpolator);
}


@Override
public Transition generateNextTransition(RectF drawableBounds, RectF viewport) {
boolean firstTransition = mLastGenTrans == null;
boolean drawableBoundsChanged = true;
boolean viewportRatioChanged = true;

RectF srcRect = null;
RectF dstRect = null;

if (!firstTransition) {
dstRect = mLastGenTrans.getDestinyRect();
drawableBoundsChanged = !drawableBounds.equals(mLastDrawableBounds);
viewportRatioChanged = !MathUtils.haveSameAspectRatio(dstRect, viewport);
}

if (dstRect == null || drawableBoundsChanged || viewportRatioChanged) {
srcRect = generateRandomRect(drawableBounds, viewport);
} else {
/* Sets the destiny rect of the last transition as the source one
if the current drawable has the same dimensions as the one of
the last transition. */
srcRect = dstRect;
}
dstRect = generateRandomRect(drawableBounds, viewport);

mLastGenTrans = new Transition(srcRect, dstRect, mTransitionDuration,
mTransitionInterpolator);

mLastDrawableBounds = drawableBounds;

return mLastGenTrans;
}


/**
* Generates a random rect that can be fully contained within {@code drawableBounds} and
* has the same aspect ratio of {@code viewportRect}. The dimensions of this random rect
* won't be higher than the largest rect with the same aspect ratio of {@code viewportRect}
* that {@code drawableBounds} can contain. They also won't be lower than the dimensions
* of this upper rect limit weighted by {@code MIN_RECT_FACTOR}.
* @param drawableBounds the bounds of the drawable that will be zoomed and panned.
* @param viewportRect the bounds of the view that the drawable will be shown.
* @return an arbitrary generated rect with the same aspect ratio of {@code viewportRect}
* that will be contained within {@code drawableBounds}.
*/
private RectF generateRandomRect(RectF drawableBounds, RectF viewportRect) {
float drawableRatio = MathUtils.getRectRatio(drawableBounds);
float viewportRectRatio = MathUtils.getRectRatio(viewportRect);
RectF maxCrop;

if (drawableRatio > viewportRectRatio) {
float r = (drawableBounds.height() / viewportRect.height()) * viewportRect.width();
float b = drawableBounds.height();
maxCrop = new RectF(0, 0, r, b);
} else {
float r = drawableBounds.width();
float b = (drawableBounds.width() / viewportRect.width()) * viewportRect.height();
maxCrop = new RectF(0, 0, r, b);
}

float randomFloat = MathUtils.truncate(mRandom.nextFloat(), 2);
float factor = MIN_RECT_FACTOR + ((1 - MIN_RECT_FACTOR) * randomFloat);

float width = factor * maxCrop.width();
float height = factor * maxCrop.height();
int widthDiff = (int) (drawableBounds.width() - width);
int heightDiff = (int) (drawableBounds.height() - height);
int left = widthDiff > 0 ? mRandom.nextInt(widthDiff) : 0;
int top = heightDiff > 0 ? mRandom.nextInt(heightDiff) : 0;
return new RectF(left, top, left + width, top + height);
}


/**
* Sets the duration, in milliseconds, for each transition generated.
* @param transitionDuration the transition duration.
*/
public void setTransitionDuration(long transitionDuration) {
mTransitionDuration = transitionDuration;
}


/**
* Sets the {@link Interpolator} for each transition generated.
* @param interpolator the transition interpolator.
*/
public void setTransitionInterpolator(Interpolator interpolator) {
mTransitionInterpolator = interpolator;
}
}
  • In above code Change Package name in first line com.karthik.kenburnsview to your package name.
  • Next create another java file with Name RobotoTextView.java and add below code.
package com.karthik.kenburnsview;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.widget.TextView;

import com.karthik.kenburnsview.R;


public class RobotoTextView extends TextView {

public RobotoTextView(Context context) {
super(context);
if (isInEditMode()) return;
parseAttributes(null);
}

public RobotoTextView(Context context, AttributeSet attrs) {
super(context, attrs);
if (isInEditMode()) return;
parseAttributes(attrs);
}

public RobotoTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
if (isInEditMode()) return;
parseAttributes(attrs);
}

public static Typeface getRoboto(Context context, int typeface) {
switch (typeface) {
case Roboto.ROBOTO_BLACK:
if (Roboto.sRobotoBlack == null) {
Roboto.sRobotoBlack = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Black.ttf");
}
return Roboto.sRobotoBlack;
case Roboto.ROBOTO_BLACK_ITALIC:
if (Roboto.sRobotoBlackItalic == null) {
Roboto.sRobotoBlackItalic = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-BlackItalic.ttf");
}
return Roboto.sRobotoBlackItalic;
case Roboto.ROBOTO_BOLD:
if (Roboto.sRobotoBold == null) {
Roboto.sRobotoBold = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Bold.ttf");
}
return Roboto.sRobotoBold;
case Roboto.ROBOTO_BOLD_CONDENSED:
if (Roboto.sRobotoBoldCondensed == null) {
Roboto.sRobotoBoldCondensed = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-BoldCondensed.ttf");
}
return Roboto.sRobotoBoldCondensed;
case Roboto.ROBOTO_BOLD_CONDENSED_ITALIC:
if (Roboto.sRobotoBoldCondensedItalic == null) {
Roboto.sRobotoBoldCondensedItalic = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-BoldCondensedItalic.ttf");
}
return Roboto.sRobotoBoldCondensedItalic;
case Roboto.ROBOTO_BOLD_ITALIC:
if (Roboto.sRobotoBoldItalic == null) {
Roboto.sRobotoBoldItalic = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-BoldItalic.ttf");
}
return Roboto.sRobotoBoldItalic;
case Roboto.ROBOTO_CONDENSED:
if (Roboto.sRobotoCondensed == null) {
Roboto.sRobotoCondensed = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Condensed.ttf");
}
return Roboto.sRobotoCondensed;
case Roboto.ROBOTO_CONDENSED_ITALIC:
if (Roboto.sRobotoCondensedItalic == null) {
Roboto.sRobotoCondensedItalic = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-CondensedItalic.ttf");
}
return Roboto.sRobotoCondensedItalic;
case Roboto.ROBOTO_ITALIC:
if (Roboto.sRobotoItalic == null) {
Roboto.sRobotoItalic = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Italic.ttf");
}
return Roboto.sRobotoItalic;
case Roboto.ROBOTO_LIGHT:
if (Roboto.sRobotoLight == null) {
Roboto.sRobotoLight = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Light.ttf");
}
return Roboto.sRobotoLight;
case Roboto.ROBOTO_LIGHT_ITALIC:
if (Roboto.sRobotoLightItalic == null) {
Roboto.sRobotoLightItalic = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-LightItalic.ttf");
}
return Roboto.sRobotoLightItalic;
case Roboto.ROBOTO_MEDIUM:
if (Roboto.sRobotoMedium == null) {
Roboto.sRobotoMedium = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Medium.ttf");
}
return Roboto.sRobotoMedium;
case Roboto.ROBOTO_MEDIUM_ITALIC:
if (Roboto.sRobotoMediumItalic == null) {
Roboto.sRobotoMediumItalic = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-MediumItalic.ttf");
}
return Roboto.sRobotoMediumItalic;
default:
case Roboto.ROBOTO_REGULAR:
if (Roboto.sRobotoRegular == null) {
Roboto.sRobotoRegular = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Regular.ttf");
}
return Roboto.sRobotoRegular;
case Roboto.ROBOTO_THIN:
if (Roboto.sRobotoThin == null) {
Roboto.sRobotoThin = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Thin.ttf");
}
return Roboto.sRobotoThin;
case Roboto.ROBOTO_THIN_ITALIC:
if (Roboto.sRobotoThinItalic == null) {
Roboto.sRobotoThinItalic = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-ThinItalic.ttf");
}
return Roboto.sRobotoThinItalic;
}
}

private void parseAttributes(AttributeSet attrs) {
int typeface;
if (attrs == null) { //Not created from xml
typeface = Roboto.ROBOTO_REGULAR;
} else {
TypedArray values = getContext().obtainStyledAttributes(attrs, R.styleable.RobotoTextView);
typeface = values.getInt(R.styleable.RobotoTextView_typeface, Roboto.ROBOTO_REGULAR);
values.recycle();
}
setTypeface(getRoboto(typeface));
}

public void setRobotoTypeface(int typeface) {
setTypeface(getRoboto(typeface));
}

private Typeface getRoboto(int typeface) {
return getRoboto(getContext(), typeface);
}

public static class Roboto {
/* From attrs.xml file:
<enum name="robotoBlack" value="0" />
<enum name="robotoBlackItalic" value="1" />
<enum name="robotoBold" value="2" />
<enum name="robotoBoldItalic" value="3" />
<enum name="robotoBoldCondensed" value="4" />
<enum name="robotoBoldCondensedItalic" value="5" />
<enum name="robotoCondensed" value="6" />
<enum name="robotoCondensedItalic" value="7" />
<enum name="robotoItalic" value="8" />
<enum name="robotoLight" value="9" />
<enum name="robotoLightItalic" value="10" />
<enum name="robotoMedium" value="11" />
<enum name="robotoMediumItalic" value="12" />
<enum name="robotoRegular" value="13" />
<enum name="robotoThin" value="14" />
<enum name="robotoThinItalic" value="15" />
*/
public static final int ROBOTO_BLACK = 0;
public static final int ROBOTO_BLACK_ITALIC = 1;
public static final int ROBOTO_BOLD = 2;
public static final int ROBOTO_BOLD_ITALIC = 3;
public static final int ROBOTO_BOLD_CONDENSED = 4;
public static final int ROBOTO_BOLD_CONDENSED_ITALIC = 5;
public static final int ROBOTO_CONDENSED = 6;
public static final int ROBOTO_CONDENSED_ITALIC = 7;
public static final int ROBOTO_ITALIC = 8;
public static final int ROBOTO_LIGHT = 9;
public static final int ROBOTO_LIGHT_ITALIC = 10;
public static final int ROBOTO_MEDIUM = 11;
public static final int ROBOTO_MEDIUM_ITALIC = 12;
public static final int ROBOTO_REGULAR = 13;
public static final int ROBOTO_THIN = 14;
public static final int ROBOTO_THIN_ITALIC = 15;

private static Typeface sRobotoBlack;
private static Typeface sRobotoBlackItalic;
private static Typeface sRobotoBold;
private static Typeface sRobotoBoldItalic;
private static Typeface sRobotoBoldCondensed;
private static Typeface sRobotoBoldCondensedItalic;
private static Typeface sRobotoCondensed;
private static Typeface sRobotoCondensedItalic;
private static Typeface sRobotoItalic;
private static Typeface sRobotoLight;
private static Typeface sRobotoLightItalic;
private static Typeface sRobotoMedium;
private static Typeface sRobotoMediumItalic;
private static Typeface sRobotoRegular;
private static Typeface sRobotoThin;
private static Typeface sRobotoThinItalic;
}
}
  • In above code Change Package name in first line & 7th line  com.karthik.kenburnsview to your package name.
  • Next create another java file with Name SplashActivity.java and add below code.
package com.karthik.kenburnsview;

/**
* Created by Karthik's on 27-02-2016.
*/
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;

import com.karthik.kenburnsview.R;
import com.karthik.kenburnsview.KenBurnsView;

public class SplashActivity extends Activity {

// Splash screen timer
private static int SPLASH_TIME_OUT = 20000;
private KenBurnsView mKenBurns;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
setAnimation();

getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);

mKenBurns = (KenBurnsView) findViewById(R.id.ken_burns_images);
mKenBurns.setImageResource(R.drawable.splash_background);

new Handler().postDelayed(new Runnable() {

@Override
public void run() {
Intent i = new Intent(SplashActivity.this, MainActivity.class);
startActivity(i);

finish();
}
}, SPLASH_TIME_OUT);
}

private void setAnimation() {
ObjectAnimator scaleXAnimation = ObjectAnimator.ofFloat(findViewById(R.id.welcome_text), "scaleX", 5.0F, 1.0F);
scaleXAnimation.setInterpolator(new AccelerateDecelerateInterpolator());
scaleXAnimation.setDuration(1200);
ObjectAnimator scaleYAnimation = ObjectAnimator.ofFloat(findViewById(R.id.welcome_text), "scaleY", 5.0F, 1.0F);
scaleYAnimation.setInterpolator(new AccelerateDecelerateInterpolator());
scaleYAnimation.setDuration(1200);
ObjectAnimator alphaAnimation = ObjectAnimator.ofFloat(findViewById(R.id.welcome_text), "alpha", 0.0F, 1.0F);
alphaAnimation.setInterpolator(new AccelerateDecelerateInterpolator());
alphaAnimation.setDuration(1200);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.play(scaleXAnimation).with(scaleYAnimation).with(alphaAnimation);
animatorSet.setStartDelay(500);
animatorSet.start();

findViewById(R.id.imagelogo).setAlpha(1.0F);
Animation anim = AnimationUtils.loadAnimation(this, R.anim.translate_top_to_center);
findViewById(R.id.imagelogo).startAnimation(anim);
}
}
  • In above code Change Package name in first line, 15th & 16 lines com.karthik.kenburnsview to your package name.
  • Next create another java file with Name Transition.java and add below code.
package com.karthik.kenburnsview;

/*
* Copyright 2014 Flavio Faria
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/


import android.graphics.RectF;
import android.view.animation.Interpolator;

public class Transition {

/** The rect the transition will start from. */
private RectF mSrcRect;

/** The rect the transition will end at. */
private RectF mDstRect;

/** An intermediary rect that changes in every frame according to the transition progress. */
private final RectF mCurrentRect = new RectF();

/** Precomputed width difference between {@link #mSrcRect} and {@link #mSrcRect}. */
private float mWidthDiff;
/** Precomputed height difference between {@link #mSrcRect} and {@link #mSrcRect}. */
private float mHeightDiff;
/** Precomputed X offset between the center points of
* {@link #mSrcRect} and {@link #mSrcRect}. */
private float mCenterXDiff;
/** Precomputed Y offset between the center points of
* {@link #mSrcRect} and {@link #mSrcRect}. */
private float mCenterYDiff;

/** The duration of the transition in milliseconds. The default duration is 5000 ms. */
private long mDuration;

/** The {@link Interpolator} used to perform the transitions between rects. */
private Interpolator mInterpolator;


public Transition(RectF srcRect, RectF dstRect, long duration, Interpolator interpolator) {
if (!MathUtils.haveSameAspectRatio(srcRect, dstRect)) {
throw new com.karthik.kenburnsview.IncompatibleRatioException();
}
mSrcRect = srcRect;
mDstRect = dstRect;
mDuration = duration;
mInterpolator = interpolator;

// Precomputes a few variables to avoid doing it in onDraw().
mWidthDiff = dstRect.width() - srcRect.width();
mHeightDiff = dstRect.height() - srcRect.height();
mCenterXDiff = dstRect.centerX() - srcRect.centerX();
mCenterYDiff = dstRect.centerY() - srcRect.centerY();
}


/**
* Gets the rect that will take the scene when a Ken Burns transition starts.
* @return the rect that starts the transition.
*/
public RectF getSourceRect() {
return mSrcRect;
}


/**
* Gets the rect that will take the scene when a Ken Burns transition ends.
* @return the rect that ends the transition.
*/
public RectF getDestinyRect() {
return mDstRect;
}


/**
* Gets the current rect that represents the part of the image to take the scene
* in the current frame.
* @param elapsedTime the elapsed time since this transition started.
*/
public RectF getInterpolatedRect(long elapsedTime) {
float elapsedTimeFraction = elapsedTime / (float) mDuration;
float interpolationProgress = Math.min(elapsedTimeFraction, 1);
float interpolation = mInterpolator.getInterpolation(interpolationProgress);
float currentWidth = mSrcRect.width() + (interpolation * mWidthDiff);
float currentHeight = mSrcRect.height() + (interpolation * mHeightDiff);

float currentCenterX = mSrcRect.centerX() + (interpolation * mCenterXDiff);
float currentCenterY = mSrcRect.centerY() + (interpolation * mCenterYDiff);

float left = currentCenterX - (currentWidth / 2);
float top = currentCenterY - (currentHeight / 2);
float right = left + currentWidth;
float bottom = top + currentHeight;

mCurrentRect.set(left, top, right, bottom);
return mCurrentRect;
}


/**
* Gets the duration of this transition.
* @return the duration, in milliseconds.
*/
public long getDuration() {
return mDuration;
}

}
  • In above code Change Package name at two places first line and some where in the middle com.karthik.kenburnsview to your package name.
  • Next create another java file with Name TransitionGenerator.java and add below code.
package com.karthik.kenburnsview;
/*
* Copyright 2014 Flavio Faria
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/


import android.graphics.RectF;

public interface TransitionGenerator {

/**
* Generates the next transition to be played by the {@link KenBurnsView}.
* @param drawableBounds the bounds of the drawable to be shown in the {@link KenBurnsView}.
* @param viewport the rect that represents the viewport where
* the transition will be played in. This is usually the bounds of the
* {@link KenBurnsView}.
* @return a {@link Transition} object to be played by the {@link KenBurnsView}.
*/
public Transition generateNextTransition(RectF drawableBounds, RectF viewport);

}
  • In above code Change Package name in first line com.karthik.kenburnsview to your package name.
  • Final step is add our SplashScreen actvity to your AndroidManifest.xml using below code.
<activity
android:name=".SplashActivity"
android:label="@string/app_name"
android:launchMode="standard"
android:screenOrientation="portrait"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
  • And change intent-filter of your main activity from LAUNCHER to DEFUALT.
  • Now rebuild your project in Android Studio using option Build->Rebuild Project.
  • After rebuilding your project generate signed Apk and test your app in Emulator or Android Device.

If  you like my post and website please share the content with your friends and help my website to grow.

Click on below link to download source code.

[ihc-hide-content ihc_mb_type=”show” ihc_mb_who=”reg” ihc_mb_template=”1″ ]Download[/ihc-hide-content]