1)Constant.java
===========
package com.mrs.xyz;
public class Constant {
public static int Index=0;
public static final String TAG="ABCDFunLite";
public static final String NO_IMAGE="Image Not Found In Gallery";
public static final String EXIT = "Exit?";
public static final String EXIT_MESSAGE = "Do you want to exit?";
public static final String YES = "Yes";
public static final String NO = "No";
public static final int[] ATOZSMALLIMAGES={R.drawable.apple,
R.drawable.butterfly,
R.drawable.cat,
R.drawable.dog,
R.drawable.elephant,
R.drawable.fox,
R.drawable.giraff,
R.drawable.hen,
R.drawable.ice_cream,
R.drawable.jug,
R.drawable.kite,
R.drawable.lion,
R.drawable.monkey,
R.drawable.nest,
R.drawable.owl,
R.drawable.peacock,
R.drawable.queen,
R.drawable.rat,
R.drawable.snack,
R.drawable.tiger,
R.drawable.umbrella,
R.drawable.van,
R.drawable.watch,
R.drawable.xmas,
R.drawable.yawk,
R.drawable.zibra};
// public static final int[] ATOZ_BIGIMAGES={R.drawable.apple_tablet,
// R.drawable.butterfly_tablet,
// R.drawable.cat_tablet,
// R.drawable.dog_tablet,
// R.drawable.elephant_tablet,
// R.drawable.fox_tablet,
// R.drawable.giraff_tablet,
// R.drawable.hen_tablet,
// R.drawable.ice_cream_tablet,
// R.drawable.jug_tablet,
// R.drawable.kite_tablet,
// R.drawable.lion_tablet,
// R.drawable.monkey_tablet,
// R.drawable.nest_tablet,
// R.drawable.owl_tablet,
// R.drawable.peacock_tablet,
// R.drawable.queen_tablet,
// R.drawable.rat_tablet,
// R.drawable.snack_tablet,
// R.drawable.tiger_tablet,
// R.drawable.umbrella_tablet,
// R.drawable.van_tablet,
// R.drawable.watch_tablet,
// R.drawable.xmas_tablet,
// R.drawable.yawk_tablet,
// R.drawable.zibra_tablet};
//
//
public static final int[] AToZSound={R.raw.a,
R.raw.b,
R.raw.c,
R.raw.d,
R.raw.e,
R.raw.f,
R.raw.g,
R.raw.h,
R.raw.i,
R.raw.j,
R.raw.k,
R.raw.l,
R.raw.m,
R.raw.n,
R.raw.o,
R.raw.p,
R.raw.q,
R.raw.r,
R.raw.s,
R.raw.t,
R.raw.u,
R.raw.v,
R.raw.w,
R.raw.x,
R.raw.y,
R.raw.z};
public static final String[] AToZText={"APPLE",
"BUTTERFLY",
"CAT",
"DOG",
"ELEPHANT",
"FOX",
"GIRAFF",
"HEN",
"ICE-CREAM",
"JUG",
"KITE",
"LION",
"MONKEY",
"NEST",
"OWL",
"PEACOCK",
"QUEEN",
"RAT",
"SNAKE",
"TIGER",
"UMBRELLA",
"VAN",
"WATCH",
"X-MAS",
"YAK",
"ZEBRA"};
}
2)IntMap.java
==========
package com.mrs.xyz;
import java.util.Iterator;
import com.drc.abcdfunlite.IntMap.Entry;
/**
* Taken from http://code.google.com/p/skorpios/
*
* @author Nate
*/
public final class IntMap<T> implements Iterable<Entry<T>>, Cloneable {
private Entry<T>[] table;
private final float loadFactor;
private int size, mask, capacity, threshold;
public IntMap() {
this(16, 0.75f);
}
public IntMap(int initialCapacity) {
this(initialCapacity, 0.75f);
}
@SuppressWarnings("unchecked")
public IntMap(int initialCapacity, float loadFactor) {
if (initialCapacity > 1 << 30){
throw new IllegalArgumentException("initialCapacity is too large.");
}
if (initialCapacity < 0){
throw new IllegalArgumentException("initialCapacity must be greater than zero.");
}
if (loadFactor <= 0){
throw new IllegalArgumentException("initialCapacity must be greater than zero.");
}
capacity = 1;
while (capacity < initialCapacity){
capacity <<= 1;
}
this.loadFactor = loadFactor;
this.threshold = (int) (capacity * loadFactor);
this.table = new Entry[capacity];
this.mask = capacity - 1;
}
@SuppressWarnings("unchecked")
public IntMap<T> clone(){
try{
IntMap<T> clone = (IntMap<T>) super.clone();
Entry<T>[] newTable = new Entry[table.length];
for (int i = table.length - 1; i >= 0; i--){
if (table[i] != null)
newTable[i] = table[i].clone();
}
clone.table = newTable;
return clone;
}catch (CloneNotSupportedException ex){
}
return null;
}
public boolean containsValue(Object value) {
Entry<T>[] table = this.table;
for (int i = table.length; i-- > 0;){
for (Entry<T> e = table[i]; e != null; e = e.next){
if (e.value.equals(value)){
return true;
}
}
}
return false;
}
public boolean containsKey(int key) {
int index = ((int) key) & mask;
for (Entry<T> e = table[index]; e != null; e = e.next){
if (e.key == key){
return true;
}
}
return false;
}
public T get(int key) {
int index = key & mask;
for (Entry<T> e = table[index]; e != null; e = e.next){
if (e.key == key){
return e.value;
}
}
return null;
}
@SuppressWarnings("unchecked")
public T put(int key, T value) {
int index = key & mask;
// Check if key already exists.
for (Entry<T> e = table[index]; e != null; e = e.next){
if (e.key != key){
continue;
}
T oldValue = e.value;
e.value = value;
return oldValue;
}
table[index] = new Entry<T>(key, value, table[index]);
if (size++ >= threshold){
// Rehash.
int newCapacity = 2 * capacity;
Entry<T>[] newTable = new Entry[newCapacity];
Entry<T>[] src = table;
int bucketmask = newCapacity - 1;
for (int j = 0; j < src.length; j++){
Entry<T> e = src[j];
if (e != null){
src[j] = null;
do{
Entry<T> next = e.next;
index = e.key & bucketmask;
e.next = newTable[index];
newTable[index] = e;
e = next;
}while (e != null);
}
}
table = newTable;
capacity = newCapacity;
threshold = (int) (newCapacity * loadFactor);
mask = capacity - 1;
}
return null;
}
public T remove(int key) {
int index = key & mask;
Entry<T> prev = table[index];
Entry<T> e = prev;
while (e != null){
Entry<T> next = e.next;
if (e.key == key){
size--;
if (prev == e){
table[index] = next;
}else{
prev.next = next;
}
return (T) e.value;
}
prev = e;
e = next;
}
return null;
}
public int size() {
return size;
}
public void clear() {
Entry<T>[] table = this.table;
for (int index = table.length; --index >= 0;){
table[index] = null;
}
size = 0;
}
public Iterator<Entry<T>> iterator() {
return new IntMapIterator();
}
final class IntMapIterator implements Iterator<Entry<T>> {
/**
* Current entry.
*/
private Entry<T> cur;
/**
* Entry in the table
*/
private int idx = 0;
/**
* Element in the entry
*/
private int el = 0;
public IntMapIterator() {
cur = table[0];
}
public boolean hasNext() {
return el < size;
}
public Entry<T> next() {
if (el >= size)
throw new IllegalStateException("No more elements!");
if (cur != null){
Entry<T> e = cur;
cur = cur.next;
el++;
return e;
}
// if (cur != null && cur.next != null){
// if we have a current entry, continue to the next entry in the list
// cur = cur.next;
// el++;
// return cur;
// }
do {
// either we exhausted the current entry list, or
// the entry was null. find another non-null entry.
cur = table[++idx];
} while (cur == null);
Entry<T> e = cur;
cur = cur.next;
el ++;
return e;
}
public void remove() {
}
}
public static final class Entry<T> implements Cloneable {
final int key;
T value;
Entry<T> next;
Entry(int k, T v, Entry<T> n) {
key = k;
value = v;
next = n;
}
public int getKey(){
return key;
}
public T getValue(){
return value;
}
public String toString(){
return key + " => " + value;
}
@SuppressWarnings("unchecked")
public Entry<T> clone(){
try{
Entry<T> clone = (Entry<T>) super.clone();
clone.next = next != null ? next.clone() : null;
return clone;
}catch (CloneNotSupportedException ex){
}
return null;
}
}
}
3)MainActivity.java
============
package com.mrs.xyz;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Canvas;
import android.graphics.Typeface;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Window;
import android.widget.FrameLayout;
import android.widget.TextView;
public class MainActivity extends Activity {
private static int intTotalimage=0;
private static TextView txtspelling=null;
private static Context mContext = null;
private PageCurlView mPageCurlView=null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.xatoz);
mContext = this;
txtspelling=(TextView)findViewById(R.id.txtspelling);
txtspelling.setTypeface(setFontNormal());
Previous_SoundId=0;
Previous_SoundId_Position=0;
intTotalimage=Constant.ATOZSMALLIMAGES.length;
if(intTotalimage > 0)
{
txtspelling.setText(Constant.AToZText[Constant.Index]);
}
//this code write for first time init sound
if(sound_status){
sound_status=false;
Previous_SoundId=Constant.AToZSound[Constant.Index];
InitSound();
}
FrameLayout frmlayout=(FrameLayout)findViewById(R.id.frmlayout);
mPageCurlView=new PageCurlView(this,Constant.Index);
mPageCurlView.SetCurlSpeed(70);
mPageCurlView.SetUpdateRate(60);
mPageCurlView.SetInitialEdgeOffset(30);
txtspelling.setTextSize(30);
mPageCurlView.SetCurlMode(PageCurlView.FOCUS_BACKWARD);
//}
frmlayout.addView(mPageCurlView);
}
@Override
public void onDestroy(){
Constant.Index=mPageCurlView.GetIndex();
mPageCurlView.Recycle_Images();
mPageCurlView=null;
super.onDestroy();
}
private void InitSound(){
for(int i=0;i < Constant.AToZSound.length ;i++){
Sound_PlayAction(this,Constant.AToZSound[i]);
}
}
private Typeface setFontNormal(){
return Typeface.createFromAsset(getResources().getAssets(), "font/ovte.ttf");
}
private static boolean sound_status=true;
private static int Previous_SoundId=0;
private static int Previous_SoundId_Position=0;
private static void Sound_PlayAction(Context context,int sound_id){
if(sound_id > 0){
SoundEngine.sharedEngine().playEffect(context, sound_id);
}
}
private static void Sound_StopAction(Context context,int sound_id){
if(sound_id > 0){
SoundEngine.sharedEngine().stopEffect(context, sound_id);
}
}
public static int Previous_Position=-1;
public static void drawPageNum(Canvas canvas, int position)
{
if(Previous_Position!=position){
//Log.d("abc", "switched to screen: " + position);
Constant.Index=position;
//this code for previous sound stop
Previous_SoundId = Constant.AToZSound[Previous_SoundId_Position];
Sound_StopAction(mContext,Previous_SoundId);
Previous_SoundId_Position=Constant.Index;
// this code for play sound file
Sound_PlayAction(mContext,Constant.AToZSound[Constant.Index]);
txtspelling.setText(Constant.AToZText[Constant.Index]);
}
Previous_Position=position;
Log.i("Index",""+position);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
//Handle the back button
if(keyCode == KeyEvent.KEYCODE_BACK) {
//Ask the user if they want to quit
new AlertDialog.Builder(this)
.setIcon(R.drawable.icmenuexit)
.setTitle(Constant.EXIT)
.setMessage(Constant.EXIT_MESSAGE)
.setPositiveButton(Constant.YES, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
//Stop the activity
//maintenancetabs.this.finish();
int pid = android.os.Process.myPid();
android.os.Process.killProcess(pid);
}
})
.setNegativeButton(Constant.NO, null)
.show();
return true;
} else {
return super.onKeyDown(keyCode, event);
}
}
}
4)PageCurlView.java
============
package com.mrs.xyz;
import java.lang.ref.WeakReference;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.Rect;
import android.os.Handler;
import android.os.Message;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
public class PageCurlView extends View {
/** Our Log tag */
private final static String TAG = "PageCurlView";
// Debug text paint stuff
private Paint mTextPaint;
private TextPaint mTextPaintShadow;
/** Px / Draw call */
private int mCurlSpeed;
/** Fixed update time used to create a smooth curl animation */
private int mUpdateRate;
/** The initial offset for x and y axis movements */
private int mInitialEdgeOffset;
/** The mode we will use */
private int mCurlMode;
/** Simple curl mode. Curl target will move only in one axis. */
public static final int CURLMODE_SIMPLE = 0;
/** Dynamic curl mode. Curl target will move on both X and Y axis. */
public static final int CURLMODE_DYNAMIC = 1;
/** Enable/Disable debug mode */
private boolean bEnableDebugMode = false;
/** The context which owns us */
private WeakReference<Context> mContext;
/** Handler used to auto flip time based */
private FlipAnimationHandler mAnimationHandler;
/** Maximum radius a page can be flipped, by default it's the width of the view */
private float mFlipRadius;
/** Point used to move */
private Vector2D mMovement;
/** The finger position */
private Vector2D mFinger;
/** Movement point form the last frame */
private Vector2D mOldMovement;
/** Page curl edge */
private Paint mCurlEdgePaint;
/** Our points used to define the current clipping paths in our draw call */
private Vector2D mA, mB, mC, mD, mE, mF, mOldF, mOrigin;
/** Left and top offset to be applied when drawing */
private int mCurrentLeft, mCurrentTop;
/** If false no draw call has been done */
private boolean bViewDrawn;
/** Defines the flip direction that is currently considered */
private boolean bFlipRight;
/** If TRUE we are currently auto-flipping */
private boolean bFlipping;
/** TRUE if the user moves the pages */
private boolean bUserMoves;
/** Used to control touch input blocking */
private boolean bBlockTouchInput = false;
/** Enable input after the next draw event */
private boolean bEnableInputAfterDraw = false;
/** LAGACY The current foreground */
private Bitmap mForeground;
/** LAGACY The current background */
private Bitmap mBackground;
/** LAGACY List of pages, this is just temporal */
// private ArrayList<Bitmap> mPages;
/** LAGACY Current selected page */
private int mIndex = 0;
/**
* Inner class used to represent a 2D point.
*/
private class Vector2D
{
public float x,y;
public Vector2D(float x, float y)
{
this.x = x;
this.y = y;
}
@Override
public String toString() {
// TODO Auto-generated method stub
return "("+this.x+","+this.y+")";
}
public float length() {
return (float) Math.sqrt(x * x + y * y);
}
public float lengthSquared() {
return (x * x) + (y * y);
}
public boolean equals(Object o) {
if (o instanceof Vector2D) {
Vector2D p = (Vector2D) o;
return p.x == x && p.y == y;
}
return false;
}
public Vector2D reverse() {
return new Vector2D(-x,-y);
}
public Vector2D sum(Vector2D b) {
return new Vector2D(x+b.x,y+b.y);
}
public Vector2D sub(Vector2D b) {
return new Vector2D(x-b.x,y-b.y);
}
public float dot(Vector2D vec) {
return (x * vec.x) + (y * vec.y);
}
public float cross(Vector2D vec) {
return x * vec.y - y * vec.x;
}
public float distanceSquared(Vector2D other) {
float dx = other.x - x;
float dy = other.y - y;
return (dx * dx) + (dy * dy);
}
public float distance(Vector2D other) {
return (float) Math.sqrt(distanceSquared(other));
}
public float dotProduct(Vector2D other) {
return other.x * x + other.y * y;
}
public Vector2D normalize() {
float magnitude = (float) Math.sqrt(dotProduct(this));
return new Vector2D(x / magnitude, y / magnitude);
}
public Vector2D mult(float scalar) {
return new Vector2D(x*scalar,y*scalar);
}
}
/**
* Inner class used to make a fixed timed animation of the curl effect.
*/
class FlipAnimationHandler extends Handler {
@Override
public void handleMessage(Message msg) {
PageCurlView.this.FlipAnimationStep();
}
public void sleep(long millis) {
this.removeMessages(0);
sendMessageDelayed(obtainMessage(0), millis);
}
}
/**
* Base
* @param context
*/
public PageCurlView(Context context,int Index) {
super(context);
init(context,Index);
ResetClipEdge();
}
/**
* Construct the object from an XML file. Valid Attributes:
*
* @see android.view.View#View(android.content.Context, android.util.AttributeSet)
*/
public PageCurlView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context,0);
// Get the data from the XML AttributeSet
{
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PageCurlView);
// Get data
bEnableDebugMode = a.getBoolean(R.styleable.PageCurlView_enableDebugMode, bEnableDebugMode);
mCurlSpeed = a.getInt(R.styleable.PageCurlView_curlSpeed, mCurlSpeed);
mUpdateRate = a.getInt(R.styleable.PageCurlView_updateRate, mUpdateRate);
mInitialEdgeOffset = a.getInt(R.styleable.PageCurlView_initialEdgeOffset, mInitialEdgeOffset);
mCurlMode = a.getInt(R.styleable.PageCurlView_curlMode, mCurlMode);
// Log.i(TAG, "mCurlSpeed: " + mCurlSpeed);
// Log.i(TAG, "mUpdateRate: " + mUpdateRate);
// Log.i(TAG, "mInitialEdgeOffset: " + mInitialEdgeOffset);
// Log.i(TAG, "mCurlMode: " + mCurlMode);
// recycle object (so it can be used by others)
a.recycle();
}
ResetClipEdge();
}
/**
* Initialize the view
*/
private final void init(Context context,int Index) {
try{
// Foreground text paint
mTextPaint = new Paint();
mTextPaint.setDither(true);
mTextPaint.setAntiAlias(true);
mTextPaint.setTextSize(14);
mTextPaint.setColor(0xFF000000);
// The shadow
mTextPaintShadow = new TextPaint();
mTextPaintShadow.setDither(true);
mTextPaintShadow.setAntiAlias(true);
mTextPaintShadow.setTextSize(14);
mTextPaintShadow.setColor(0x00000000);
// Cache the context
mContext = new WeakReference<Context>(context);
// Base padding
setPadding(3, 3, 3, 3);
// The focus flags are needed
setFocusable(true);
setFocusableInTouchMode(true);
mMovement = new Vector2D(0,0);
mFinger = new Vector2D(0,0);
mOldMovement = new Vector2D(0,0);
// Create our curl animation handler
mAnimationHandler = new FlipAnimationHandler();
// Create our edge paint
mCurlEdgePaint = new Paint();
mCurlEdgePaint.setDither(true);
mCurlEdgePaint.setColor(Color.WHITE);
mCurlEdgePaint.setAntiAlias(true);
mCurlEdgePaint.setStyle(Paint.Style.FILL);
mCurlEdgePaint.setShadowLayer(10, -5, 5, 0x99000000);
// Set the default props, those come from an XML :D
mCurlSpeed = 30;
mUpdateRate = 33;
mInitialEdgeOffset = 20;
mCurlMode = 1;
// Create some sample images
mIndex=Index;
// if(MainActivity.Check_Resolution()){
// mForeground = BitmapFactory.decodeResource(getResources(), Constant.ATOZ_BIGIMAGES[mIndex]);
// mBackground = BitmapFactory.decodeResource(getResources(), Constant.ATOZ_BIGIMAGES[mIndex+1]);
// }
// else{
mForeground = BitmapFactory.decodeResource(getResources(), Constant.ATOZSMALLIMAGES[mIndex]);
mBackground = BitmapFactory.decodeResource(getResources(), Constant.ATOZSMALLIMAGES[mIndex+1]);
// }
}catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
/**
* Get current Index
*/
public int GetIndex() {
return mIndex;
}
/**
* Relese Bitmap Memory
*/
public void Recycle_Images() {
if(mForeground!=null){
if(!mForeground.isRecycled()){
mForeground.recycle();
}
}
if(mBackground!=null){
if(!mBackground.isRecycled()){
mBackground.recycle();
}
}
System.gc();
}
/**
* Reset points to it's initial clip edge state
*/
public void ResetClipEdge()
{
// Set our base movement
mMovement.x = mInitialEdgeOffset;
mMovement.y = mInitialEdgeOffset;
mOldMovement.x = 0;
mOldMovement.y = 0;
// Now set the points
// TODO: OK, those points MUST come from our measures and
// the actual bounds of the view!
mA = new Vector2D(mInitialEdgeOffset, 0);
mB = new Vector2D(this.getWidth(), this.getHeight());
mC = new Vector2D(this.getWidth(), 0);
mD = new Vector2D(0, 0);
mE = new Vector2D(0, 0);
mF = new Vector2D(0, 0);
mOldF = new Vector2D(0, 0);
// The movement origin point
mOrigin = new Vector2D(this.getWidth(), 0);
}
/**
* Return the context which created use. Can return null if the
* context has been erased.
*/
private Context GetContext() {
return mContext.get();
}
/**
* See if the current curl mode is dynamic
* @return TRUE if the mode is CURLMODE_DYNAMIC, FALSE otherwise
*/
public boolean IsCurlModeDynamic()
{
return mCurlMode == CURLMODE_DYNAMIC;
}
/**
* Set the curl speed.
* @param curlSpeed - New speed in px/frame
* @throws IllegalArgumentException if curlspeed < 1
*/
public void SetCurlSpeed(int curlSpeed)
{
if ( curlSpeed < 1 )
throw new IllegalArgumentException("curlSpeed must be greated than 0");
mCurlSpeed = curlSpeed;
}
/**
* Get the current curl speed
* @return int - Curl speed in px/frame
*/
public int GetCurlSpeed()
{
return mCurlSpeed;
}
/**
* Set the update rate for the curl animation
* @param updateRate - Fixed animation update rate in fps
* @throws IllegalArgumentException if updateRate < 1
*/
public void SetUpdateRate(int updateRate)
{
if ( updateRate < 1 )
throw new IllegalArgumentException("updateRate must be greated than 0");
mUpdateRate = updateRate;
}
/**
* Get the current animation update rate
* @return int - Fixed animation update rate in fps
*/
public int GetUpdateRate()
{
return mUpdateRate;
}
/**
* Set the initial pixel offset for the curl edge
* @param initialEdgeOffset - px offset for curl edge
* @throws IllegalArgumentException if initialEdgeOffset < 0
*/
public void SetInitialEdgeOffset(int initialEdgeOffset)
{
if ( initialEdgeOffset < 0 )
throw new IllegalArgumentException("initialEdgeOffset can not negative");
mInitialEdgeOffset = initialEdgeOffset;
}
/**
* Get the initial pixel offset for the curl edge
* @return int - px
*/
public int GetInitialEdgeOffset()
{
return mInitialEdgeOffset;
}
/**
* Set the curl mode.
* <p>Can be one of the following values:</p>
* <table>
* <colgroup align="left" />
* <colgroup align="left" />
* <tr><th>Value</th><th>Description</th></tr>
* <tr><td><code>{@link #CURLMODE_SIMPLE com.dcg.pagecurl:CURLMODE_SIMPLE}</code></td><td>Curl target will move only in one axis.</td></tr>
* <tr><td><code>{@link #CURLMODE_DYNAMIC com.dcg.pagecurl:CURLMODE_DYNAMIC}</code></td><td>Curl target will move on both X and Y axis.</td></tr>
* </table>
* @see #CURLMODE_SIMPLE
* @see #CURLMODE_DYNAMIC
* @param curlMode
* @throws IllegalArgumentException if curlMode is invalid
*/
public void SetCurlMode(int curlMode)
{
if ( curlMode != CURLMODE_SIMPLE &&
curlMode != CURLMODE_DYNAMIC )
throw new IllegalArgumentException("Invalid curlMode");
mCurlMode = curlMode;
}
/**
* Return an integer that represents the current curl mode.
* <p>Can be one of the following values:</p>
* <table>
* <colgroup align="left" />
* <colgroup align="left" />
* <tr><th>Value</th><th>Description</th></tr>
* <tr><td><code>{@link #CURLMODE_SIMPLE com.dcg.pagecurl:CURLMODE_SIMPLE}</code></td><td>Curl target will move only in one axis.</td></tr>
* <tr><td><code>{@link #CURLMODE_DYNAMIC com.dcg.pagecurl:CURLMODE_DYNAMIC}</code></td><td>Curl target will move on both X and Y axis.</td></tr>
* </table>
* @see #CURLMODE_SIMPLE
* @see #CURLMODE_DYNAMIC
* @return int - current curl mode
*/
public int GetCurlMode()
{
return mCurlMode;
}
/**
* Enable debug mode. This will draw a lot of data in the view so you can track what is happening
* @param bFlag - boolean flag
*/
public void SetEnableDebugMode(boolean bFlag)
{
bEnableDebugMode = bFlag;
}
/**
* Check if we are currently in debug mode.
* @return boolean - If TRUE debug mode is on, FALSE otherwise.
*/
public boolean IsDebugModeEnabled()
{
return bEnableDebugMode;
}
/**
* @see android.view.View#measure(int, int)
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int finalWidth, finalHeight;
finalWidth = measureWidth(widthMeasureSpec);
finalHeight = measureHeight(heightMeasureSpec);
setMeasuredDimension(finalWidth, finalHeight);
}
/**
* Determines the width of this view
* @param measureSpec A measureSpec packed into an int
* @return The width of the view, honoring constraints from measureSpec
*/
private int measureWidth(int measureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
// We were told how big to be
result = specSize;
} else {
// Measure the text
result = specSize;
}
return result;
}
/**
* Determines the height of this view
* @param measureSpec A measureSpec packed into an int
* @return The height of the view, honoring constraints from measureSpec
*/
private int measureHeight(int measureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
// We were told how big to be
result = specSize;
} else {
// Measure the text (beware: ascent is a negative number)
result = specSize;
}
return result;
}
/**
* Render the text
*
* @see android.view.View#onDraw(android.graphics.Canvas)
*/
//@Override
//protected void onDraw(Canvas canvas) {
// super.onDraw(canvas);
// canvas.drawText(mText, getPaddingLeft(), getPaddingTop() - mAscent, mTextPaint);
//}
//---------------------------------------------------------------
// Curling. This handles touch events, the actual curling
// implementations and so on.
//---------------------------------------------------------------
@Override
public boolean onTouchEvent(MotionEvent event) {
if (!bBlockTouchInput) {
// Get our finger position
mFinger.x = event.getX();
mFinger.y = event.getY();
int width = getWidth();
// Depending on the action do what we need to
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mOldMovement.x = mFinger.x;
mOldMovement.y = mFinger.y;
// If we moved over the half of the display flip to next
if (mOldMovement.x > (width >> 1)) {
mMovement.x = mInitialEdgeOffset;
mMovement.y = mInitialEdgeOffset;
// Set the right movement flag
bFlipRight = true;
} else {
// Set the left movement flag
bFlipRight = false;
// go to next previous page
previousView();
// Set new movement
mMovement.x = IsCurlModeDynamic()?width<<1:width;
mMovement.y = mInitialEdgeOffset;
}
break;
case MotionEvent.ACTION_UP:
bUserMoves=false;
bFlipping=true;
FlipAnimationStep();
break;
case MotionEvent.ACTION_MOVE:
bUserMoves=true;
// Get movement
mMovement.x -= mFinger.x - mOldMovement.x;
mMovement.y -= mFinger.y - mOldMovement.y;
mMovement = CapMovement(mMovement, true);
// Make sure the y value get's locked at a nice level
if ( mMovement.y <= 1 )
mMovement.y = 1;
// Get movement direction
if (mFinger.x < mOldMovement.x ) {
bFlipRight = true;
} else {
bFlipRight = false;
}
// Save old movement values
mOldMovement.x = mFinger.x;
mOldMovement.y = mFinger.y;
// Force a new draw call
DoPageCurl();
this.invalidate();
break;
}
}
// TODO: Only consume event if we need to.
return true;
}
/**
* Make sure we never move too much, and make sure that if we
* move too much to add a displacement so that the movement will
* be still in our radius.
* @param radius - radius form the flip origin
* @param bMaintainMoveDir - Cap movement but do not change the
* current movement direction
* @return Corrected point
*/
private Vector2D CapMovement(Vector2D point, boolean bMaintainMoveDir)
{
// Make sure we never ever move too much
if (point.distance(mOrigin) > mFlipRadius)
{
if ( bMaintainMoveDir )
{
// Maintain the direction
point = mOrigin.sum(point.sub(mOrigin).normalize().mult(mFlipRadius));
}
else
{
// Change direction
if ( point.x > (mOrigin.x+mFlipRadius))
point.x = (mOrigin.x+mFlipRadius);
else if ( point.x < (mOrigin.x-mFlipRadius) )
point.x = (mOrigin.x-mFlipRadius);
point.y = (float) (Math.sin(Math.acos(Math.abs(point.x-mOrigin.x)/mFlipRadius))*mFlipRadius);
}
}
return point;
}
/**
* Execute a step of the flip animation
*/
public void FlipAnimationStep() {
if ( !bFlipping )
return;
int width = getWidth();
// No input when flipping
bBlockTouchInput = true;
// Handle speed
float curlSpeed = mCurlSpeed;
if ( !bFlipRight )
curlSpeed *= -1;
// Move us
mMovement.x += curlSpeed;
mMovement = CapMovement(mMovement, false);
// Create values
DoPageCurl();
if (mA.x < 1 || mA.x > width - 1) {
bFlipping = false;
if (bFlipRight) {
//SwapViews();
nextView();
}
ResetClipEdge();
// Create values
DoPageCurl();
// Enable touch input after the next draw event
bEnableInputAfterDraw = true;
}
else
{
mAnimationHandler.sleep(mUpdateRate);
}
// Force a new draw call
this.invalidate();
}
/**
* Do the page curl depending on the methods we are using
*/
private void DoPageCurl()
{
if(bFlipping){
if ( IsCurlModeDynamic() )
doDynamicCurl();
else
doSimpleCurl();
} else {
if ( IsCurlModeDynamic() )
doDynamicCurl();
else
doSimpleCurl();
}
}
/**
* Do a simple page curl effect
*/
private void doSimpleCurl() {
int width = getWidth();
int height = getHeight();
// Calculate point A
mA.x = width - mMovement.x;
mA.y = height;
// Calculate point D
mD.x = 0;
mD.y = 0;
if (mA.x > width / 2) {
mD.x = width;
mD.y = height - (width - mA.x) * height / mA.x;
} else {
mD.x = 2 * mA.x;
mD.y = 0;
}
// Now calculate E and F taking into account that the line
// AD is perpendicular to FB and EC. B and C are fixed points.
double angle = Math.atan((height - mD.y) / (mD.x + mMovement.x - width));
double _cos = Math.cos(2 * angle);
double _sin = Math.sin(2 * angle);
// And get F
mF.x = (float) (width - mMovement.x + _cos * mMovement.x);
mF.y = (float) (height - _sin * mMovement.x);
// If the x position of A is above half of the page we are still not
// folding the upper-right edge and so E and D are equal.
if (mA.x > width / 2) {
mE.x = mD.x;
mE.y = mD.y;
}
else
{
// So get E
mE.x = (float) (mD.x + _cos * (width - mD.x));
mE.y = (float) -(_sin * (width - mD.x));
}
}
/**
* Calculate the dynamic effect, that one that follows the users finger
*/
private void doDynamicCurl() {
int width = getWidth();
int height = getHeight();
// F will follow the finger, we add a small displacement
// So that we can see the edge
mF.x = width - mMovement.x+0.1f;
mF.y = height - mMovement.y+0.1f;
// Set min points
if(mA.x==0) {
mF.x= Math.min(mF.x, mOldF.x);
mF.y= Math.max(mF.y, mOldF.y);
}
// Get diffs
float deltaX = width-mF.x;
float deltaY = height-mF.y;
float BH = (float) (Math.sqrt(deltaX * deltaX + deltaY * deltaY) / 2);
double tangAlpha = deltaY / deltaX;
double alpha = Math.atan(deltaY / deltaX);
double _cos = Math.cos(alpha);
double _sin = Math.sin(alpha);
mA.x = (float) (width - (BH / _cos));
mA.y = height;
mD.y = (float) (height - (BH / _sin));
mD.x = width;
mA.x = Math.max(0,mA.x);
if(mA.x==0) {
mOldF.x = mF.x;
mOldF.y = mF.y;
}
// Get W
mE.x = mD.x;
mE.y = mD.y;
// Correct
if (mD.y < 0) {
mD.x = width + (float) (tangAlpha * mD.y);
mE.y = 0;
mE.x = width + (float) (Math.tan(2 * alpha) * mD.y);
}
}
/**
* Swap between the fore and back-ground.
*/
@Deprecated
private void SwapViews() {
Bitmap temp=null;
try{
temp = mForeground;
mForeground = mBackground;
mBackground = temp;
}
catch (Exception e) {
e.printStackTrace();
}
finally{
if(temp!=null){
if(!temp.isRecycled()){
temp.recycle();
}
}
}
}
/**
* Swap to next view
*/
private void nextView() {
int foreIndex = mIndex + 1;
if(foreIndex >= Constant.ATOZSMALLIMAGES.length) {
System.out.println("nextView===="+Constant.ATOZSMALLIMAGES.length);
foreIndex =0;
}
int backIndex = foreIndex + 1;
if(backIndex >= Constant.ATOZSMALLIMAGES.length) {
backIndex =0;
}
mIndex = foreIndex;
setViews(foreIndex, backIndex);
}
/**
* Swap to previous view
*/
private void previousView() {
int backIndex = mIndex;
int foreIndex = backIndex - 1;
if(foreIndex < 0) {
foreIndex = Constant.ATOZSMALLIMAGES.length -1;
}
mIndex = foreIndex;
setViews(foreIndex, backIndex);
}
/**
* Set current fore and background
* @param foreground - Foreground view index
* @param background - Background view index
*/
private void setViews(int foreground, int background) {
if(mForeground!=null){
if(!mForeground.isRecycled()){
mForeground.recycle();
}
}
if(mBackground!=null){
if(!mBackground.isRecycled()){
mBackground.recycle();
}
}
// if(MainActivity.Check_Resolution()){
// mForeground = BitmapFactory.decodeResource(getResources(), Constant.ATOZ_BIGIMAGES[foreground]);
// mBackground = BitmapFactory.decodeResource(getResources(), Constant.ATOZ_BIGIMAGES[background]);
// }
// else{
mForeground = BitmapFactory.decodeResource(getResources(), Constant.ATOZSMALLIMAGES[foreground]);
mBackground = BitmapFactory.decodeResource(getResources(), Constant.ATOZSMALLIMAGES[background]);
//}
}
//---------------------------------------------------------------
// Drawing methods
//---------------------------------------------------------------
@Override
protected void onDraw(Canvas canvas) {
// Always refresh offsets
mCurrentLeft = getLeft();
mCurrentTop = getTop();
// Translate the whole canvas
//canvas.translate(mCurrentLeft, mCurrentTop);
// We need to initialize all size data when we first draw the view
if ( !bViewDrawn ) {
bViewDrawn = true;
onFirstDrawEvent(canvas);
}
canvas.drawColor(Color.WHITE);
// Curl pages
//DoPageCurl();
// TODO: This just scales the views to the current
// width and height. We should add some logic for:
// 1) Maintain aspect ratio
// 2) Uniform scale
// 3) ...
Rect rect = new Rect();
rect.left = 0;
rect.top = 0;
rect.bottom = getHeight();
rect.right = getWidth();
// First Page render
Paint paint = new Paint();
paint.setDither(true);
// Draw our elements
drawForeground(canvas, rect, paint);
drawBackground(canvas, rect, paint);
drawCurlEdge(canvas);
// Draw any debug info once we are done
if ( bEnableDebugMode )
drawDebug(canvas);
// Check if we can re-enable input
if ( bEnableInputAfterDraw )
{
bBlockTouchInput = false;
bEnableInputAfterDraw = false;
}
}
/**
* Called on the first draw event of the view
* @param canvas
*/
protected void onFirstDrawEvent(Canvas canvas) {
mFlipRadius = getWidth();
ResetClipEdge();
DoPageCurl();
}
/**
* Draw the foreground
* @param canvas
* @param rect
* @param paint
*/
private void drawForeground( Canvas canvas, Rect rect, Paint paint ) {
paint.setDither(true);
canvas.drawBitmap(mForeground, null, rect, paint);
// Draw the page number (first page is 1 in real life :D
// there is no page number 0 hehe)
MainActivity.drawPageNum(canvas, mIndex);
}
/**
* Create a Path used as a mask to draw the background page
* @return
*/
private Path createBackgroundPath() {
Path path = new Path();
path.moveTo(mA.x, mA.y);
path.lineTo(mB.x, mB.y);
path.lineTo(mC.x, mC.y);
path.lineTo(mD.x, mD.y);
path.lineTo(mA.x, mA.y);
return path;
}
/**
* Draw the background image.
* @param canvas
* @param rect
* @param paint
*/
private void drawBackground( Canvas canvas, Rect rect, Paint paint ) {
try{
paint.setDither(true);
Path mask = createBackgroundPath();
// Save current canvas so we do not mess it up
canvas.save();
canvas.clipPath(mask);
canvas.drawBitmap(mBackground, null, rect, paint);
// Draw the page number (first page is 1 in real life :D
// there is no page number 0 hehe)
MainActivity.drawPageNum(canvas, mIndex);
canvas.restore();
}catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
/**
* Creates a path used to draw the curl edge in.
* @return
*/
private Path createCurlEdgePath() {
Path path = new Path();
path.moveTo(mA.x, mA.y);
path.lineTo(mD.x, mD.y);
path.lineTo(mE.x, mE.y);
path.lineTo(mF.x, mF.y);
path.lineTo(mA.x, mA.y);
return path;
}
/**
* Draw the curl page edge
* @param canvas
*/
private void drawCurlEdge( Canvas canvas )
{
Path path = createCurlEdgePath();
canvas.drawPath(path, mCurlEdgePaint);
}
/**
* Draw page num (let this be a bit more custom)
* @param canvas
* @param pageNum
*/
//---------------------------------------------------------------
// Debug draw methods
//---------------------------------------------------------------
/**
* Draw a text with a nice shadow
*/
public static void drawTextShadowed(Canvas canvas, String text, float x, float y, Paint textPain, Paint shadowPaint) {
shadowPaint.setDither(true);
textPain.setDither(true);
canvas.drawText(text, x-1, y, shadowPaint);
canvas.drawText(text, x, y+1, shadowPaint);
canvas.drawText(text, x+1, y, shadowPaint);
canvas.drawText(text, x, y-1, shadowPaint);
canvas.drawText(text, x, y, textPain);
}
/**
* Draw a text with a nice shadow centered in the X axis
* @param canvas
* @param text
* @param y
* @param textPain
* @param shadowPaint
*/
public static void drawCentered(Canvas canvas, String text, float y, Paint textPain, Paint shadowPaint)
{
shadowPaint.setDither(true);
textPain.setDither(true);
float posx = (canvas.getWidth() - textPain.measureText(text))/2;
drawTextShadowed(canvas, text, posx, y, textPain, shadowPaint);
}
/**
* Draw debug info
* @param canvas
*/
private void drawDebug(Canvas canvas)
{
float posX = 10;
float posY = 20;
Paint paint = new Paint();
paint.setDither(true);
paint.setStrokeWidth(5);
paint.setStyle(Style.FILL_AND_STROKE);
paint.setColor(Color.BLACK);
canvas.drawCircle(mOrigin.x, mOrigin.y, getWidth(), paint);
paint.setStrokeWidth(3);
paint.setColor(Color.RED);
canvas.drawCircle(mOrigin.x, mOrigin.y, getWidth(), paint);
paint.setStrokeWidth(5);
paint.setColor(Color.BLACK);
canvas.drawLine(mOrigin.x, mOrigin.y, mMovement.x, mMovement.y, paint);
paint.setStrokeWidth(3);
paint.setColor(Color.RED);
canvas.drawLine(mOrigin.x, mOrigin.y, mMovement.x, mMovement.y, paint);
posY = debugDrawPoint(canvas,"A",mA,Color.RED,posX,posY);
posY = debugDrawPoint(canvas,"B",mB,Color.GREEN,posX,posY);
posY = debugDrawPoint(canvas,"C",mC,Color.BLUE,posX,posY);
posY = debugDrawPoint(canvas,"D",mD,Color.CYAN,posX,posY);
posY = debugDrawPoint(canvas,"E",mE,Color.YELLOW,posX,posY);
posY = debugDrawPoint(canvas,"F",mF,Color.LTGRAY,posX,posY);
posY = debugDrawPoint(canvas,"Mov",mMovement,Color.DKGRAY,posX,posY);
posY = debugDrawPoint(canvas,"Origin",mOrigin,Color.MAGENTA,posX,posY);
posY = debugDrawPoint(canvas,"Finger",mFinger,Color.GREEN,posX,posY);
}
private float debugDrawPoint(Canvas canvas, String name, Vector2D point, int color, float posX, float posY) {
return debugDrawPoint(canvas,name+" "+point.toString(),point.x, point.y, color, posX, posY);
}
private float debugDrawPoint(Canvas canvas, String name, float X, float Y, int color, float posX, float posY) {
mTextPaint.setColor(color);
drawTextShadowed(canvas,name,posX , posY, mTextPaint,mTextPaintShadow);
Paint paint = new Paint();
paint.setDither(true);
paint.setStrokeWidth(5);
paint.setColor(color);
canvas.drawPoint(X, Y, paint);
return posY+15;
}
}
5)SoundEngine.java
=============
package com.mrs.xyz;
import java.io.IOException;
import android.content.Context;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.SoundPool;
import com.drc.abcdfunlite.IntMap.Entry;
// TODO: support volume customizations for both effects and background ...
public class SoundEngine {
// effects are sounds that less than 5 seconds, better in 3 seconds
IntMap<Integer> effectsMap = new IntMap<Integer>();
IntMap<Integer> streamsMap = new IntMap<Integer>();
// sounds are background sounds, usually longer than 5 seconds
IntMap<MediaPlayer> soundsMap = new IntMap<MediaPlayer>();
SoundPool sp = new SoundPool(5, AudioManager.STREAM_MUSIC, 0);
int lastSndId = -1;
Float prevEffectsVolume = null;
Float prevSoundsVolume = null;
Float effectsVolume = null;
Float soundsVolume = null;
boolean mute = false;
static SoundEngine _sharedEngine = null;
public static SoundEngine sharedEngine() {
synchronized(SoundEngine.class) {
if (_sharedEngine == null) {
_sharedEngine = new SoundEngine();
}
}
return _sharedEngine;
}
public static void purgeSharedEngine() {
synchronized(SoundEngine.class) {
_sharedEngine = null;
}
}
public void setEffectsVolume(Float volume) {
if (mute)
return;
effectsVolume = volume;
}
public Float getEffectsVolume() {
return effectsVolume;
}
public void setSoundVolume(Float volume) {
if (mute)
return;
soundsVolume = volume;
for (Entry<MediaPlayer> each : soundsMap)
{
each.getValue().setVolume(soundsVolume, soundsVolume);
}
}
public Float getSoundsVolume() {
return soundsVolume;
}
public void mute() {
if (mute)
return;
prevEffectsVolume = effectsVolume;
prevSoundsVolume = soundsVolume;
effectsVolume = 0f;
setSoundVolume(0f);
mute = true;
}
public void unmute() {
if (!mute)
return;
effectsVolume = prevEffectsVolume;
mute = false;
setSoundVolume(prevSoundsVolume);
}
public boolean isMute() {
return mute;
}
public void preloadEffect(Context app, int resId){
synchronized(effectsMap) {
Integer sndId = effectsMap.get(resId);
if (sndId != null)
return;
sndId = sp.load(app, resId, 0);
effectsMap.put(resId, sndId);
}
}
public void playEffect(Context app, int resId) {
Integer sndId = -1;
synchronized (effectsMap) {
sndId = effectsMap.get(resId);
if (sndId == null) {
sndId = sp.load(app, resId, 0);
effectsMap.put(resId, sndId);
}
}
int streamId = sp.play(sndId, 1.0f, 1.0f, 0, 0, 1.0f);
if (effectsVolume != null) {
sp.setVolume(streamId, effectsVolume, effectsVolume);
}
streamsMap.put(resId, streamId);
}
public void stopEffect(Context app, int resId) {
Integer sid = streamsMap.get(resId);
if (sid != null) {
sp.stop(sid);
}
}
public void preloadSound(Context ctxt, int resId) {
synchronized(soundsMap) {
MediaPlayer mp = soundsMap.get(resId);
if (mp != null)
return;
mp = MediaPlayer.create(ctxt, resId);
// mp.prepareAsync();
soundsMap.put(resId, mp);
}
}
public void playSound(Context ctxt, int resId, boolean loop) {
if (lastSndId != -1) {
pauseSound();
}
MediaPlayer mp = null;
synchronized(soundsMap) {
mp = soundsMap.get(resId);
if (mp == null) {
mp = MediaPlayer.create(ctxt, resId);
// failed to create
if(mp == null)
return;
soundsMap.put(resId, mp);
try {
mp.prepare();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
lastSndId = resId;
mp.start();
if (soundsVolume != null)
mp.setVolume(soundsVolume, soundsVolume);
if (loop)
mp.setLooping(true);
}
public void pauseSound() {
if (lastSndId == -1)
return;
MediaPlayer mp = null;
synchronized(soundsMap) {
mp = soundsMap.get(lastSndId);
if (mp == null)
return;
}
mp.pause();
}
public void resumeSound() {
if (lastSndId == -1)
return;
MediaPlayer mp = null;
synchronized(soundsMap) {
mp = soundsMap.get(lastSndId);
if (mp == null)
return;
}
mp.start();
}
public void realesSound(int resId)
{
MediaPlayer mp = null;
synchronized(soundsMap) {
mp = soundsMap.get(resId);
if (mp != null) {
mp.release();
soundsMap.remove(resId);
}
}
}
public void realesAllSounds() {
for(Entry<MediaPlayer> mp : soundsMap) {
mp.getValue().release();
}
soundsMap.clear();
}
public void realesAllEffects() {
sp.release();
}
}
6)SplashScreen.java
============
package com.mrs.xyz;
import android.app.Activity;
import android.app.Dialog;
import android.content.Intent;
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
public class SplashScreen extends Activity {
private Dialog mDialog = null;
private float X1=0,X2=0,Y1=0,Y2=0;
public ImageView imgArrow;
private ImageView animation;
private LinearLayout lytSplash;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.xsplashscreen);
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
Constant.Index=0;
lytSplash = (LinearLayout)findViewById(R.id.lytSplash);
lytSplash.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
NextActivity();
}
});
animation = (ImageView)findViewById(R.id.imageAnimation);
// if(MainActivity.Check_Resolution()){
// animation.setBackgroundResource(R.drawable.animation_tablet);
// animation.setOnClickListener(new OnClickListener() {
//
// public void onClick(View v) {
// // TODO Auto-generated method stub
// //mDialog = new Dialog(NewSplashScreen.this,android.R.style.Theme_Translucent_NoTitleBar_Fullscreen);
//
// mDialog = new Dialog(SplashScreen.this);
// mDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
// mDialog.setContentView(R.layout.xslashscreenplaydialog);
// mDialog.getWindow().setBackgroundDrawable(new ColorDrawable(0));
//
// Button btnSwip = (Button)mDialog.findViewById(R.id.btnSwip);
// btnSwip.setBackgroundResource(R.drawable.swap_tablet);
// btnSwip.setOnClickListener(new OnClickListener() {
//
// public void onClick(View v) {
// mDialog.dismiss();
// NextActivity();
// }
// });
// mDialog.setCancelable(false);
// mDialog.setCanceledOnTouchOutside(false);
// mDialog.show();
// }
// });
// }
// else{
animation.setBackgroundResource(R.drawable.animation);
animation.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
//mDialog = new Dialog(NewSplashScreen.this,android.R.style.Theme_Translucent_NoTitleBar_Fullscreen);
mDialog = new Dialog(SplashScreen.this);
mDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
mDialog.setContentView(R.layout.xslashscreenplaydialog);
mDialog.getWindow().setBackgroundDrawable(new ColorDrawable(0));
Button btnSwip = (Button)mDialog.findViewById(R.id.btnSwip);
btnSwip.setBackgroundResource(R.drawable.swap);
btnSwip.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
mDialog.dismiss();
NextActivity();
}
});
mDialog.setCancelable(false);
mDialog.setCanceledOnTouchOutside(false);
mDialog.show();
}
});
// }
}
@Override
/**
* This method is called whenever the Activity becomes visible or invisible to the user.
* During this method call its possible to start the animation.
*/
public void onWindowFocusChanged (boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
AnimationDrawable frameAnimation =
(AnimationDrawable) animation.getBackground();
if(hasFocus) {
frameAnimation.start();
} else {
frameAnimation.stop();
}
}
private void NextActivity(){
Intent mIntent=new Intent(this,MainActivity.class);
startActivity(mIntent);
finish();
// overridePendingTransition(R.anim.fade_in,R.anim.fade_out);
}
// This Is run when key down
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
return true;
}
return super.onKeyDown(keyCode, event);
}
}
7)xatoz.xml
===========
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@android:color/white"
android:orientation="vertical" >
<RelativeLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<FrameLayout
android:id="@+id/frmlayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
</FrameLayout>
</RelativeLayout>
<RelativeLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:gravity="top"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:id="@+id/txtspelling"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dip"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
android:textSize="24dip"
android:textStyle="bold"
android:textColor="@android:color/white"
android:layout_weight="1">
</TextView>
<!-- <ImageView -->
<!-- android:id="@+id/imgalphabet" -->
<!-- android:layout_width="100dip" -->
<!-- android:layout_height="100dip"> -->
<!-- </ImageView> -->
</LinearLayout>
</RelativeLayout>
</RelativeLayout>
</LinearLayout>
8)xslashscreenplaydialog.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:id="@+id/lytSplash"
android:background="@android:color/transparent"
android:layout_width="fill_parent"
android:layout_gravity="center"
android:gravity="center"
android:layout_height="fill_parent">
<Button
android:id="@+id/btnSwip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
</Button>
<!-- <TextView -->
<!-- android:layout_width="fill_parent" -->
<!-- android:layout_height="fill_parent" -->
<!-- android:layout_marginLeft= "15dip" -->
<!-- android:layout_marginRight="15dip" -->
<!-- android:textSize="16dip" -->
<!-- android:textStyle="bold" -->
<!-- android:textColor="#FFFFFF" -->
<!-- android:text="@string/splashscreen_text"/> -->
</LinearLayout>
9)xsplashscreen.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/lytSplash"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:background="@drawable/imgsplash_screen">
<ImageView
android:id="@+id/imageAnimation"
android:layout_marginTop="5dip"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_gravity="right"
android:adjustViewBounds="true" />
</LinearLayout>
9)in raw folder add mp3 files for a to z
=========================
10_manifest.xml
============
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.drc.abcdfunlite"
android:installLocation="auto"
android:versionCode="4"
android:versionName="1.3" >
<uses-sdk android:minSdkVersion="7" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" android:vmSafeMode="true">
<activity android:label="@string/app_name"
android:name="SplashScreen"
android:screenOrientation="portrait"
android:configChanges="orientation|keyboardHidden"
android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:label="@string/app_name"
android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"
android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</application>
</manifest>
11) in anim folder add 3 files
1)fadein.xml
===========
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:fromAlpha="0.0"
android:toAlpha="1.0"
android:duration="1200"
android:fillAfter="true"
android:fillEnabled="true"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
/>
2)fadout.xml
========
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:fromAlpha="0.0"
android:toAlpha="1.0"
android:duration="1200"
android:fillAfter="true"
android:fillEnabled="true"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
/>
3)scalingbig.xml
=========
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<scale
android:duration="800"
android:fromXScale="0.0"
android:fromYScale="0.0"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1.0"
android:toYScale="1.0"
android:startOffset="0"
android:fillAfter="true"
android:fillBefore="false"/>
</set>
12)in drawable add file name
1)animation.xml
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">
<item android:drawable="@drawable/img1" android:duration="50" />
<item android:drawable="@drawable/img2" android:duration="50" />
<item android:drawable="@drawable/img3" android:duration="50" />
<item android:drawable="@drawable/img4" android:duration="50" />
<item android:drawable="@drawable/img5" android:duration="50" />
<item android:drawable="@drawable/img6" android:duration="50" />
<item android:drawable="@drawable/img7" android:duration="50" />
<item android:drawable="@drawable/img8" android:duration="50" />
<item android:drawable="@drawable/img9" android:duration="50" />
<item android:drawable="@drawable/img10" android:duration="50" />
<item android:drawable="@drawable/img12" android:duration="50" />
<item android:drawable="@drawable/img13" android:duration="50" />
<item android:drawable="@drawable/img14" android:duration="50" />
<item android:drawable="@drawable/img15" android:duration="50" />
<item android:drawable="@drawable/img16" android:duration="50" />
<item android:drawable="@drawable/img17" android:duration="50" />
<item android:drawable="@drawable/img18" android:duration="50" />
<item android:drawable="@drawable/img19" android:duration="50" />
<item android:drawable="@drawable/img20" android:duration="50" />
<item android:drawable="@drawable/img21" android:duration="50" />
<item android:drawable="@drawable/img20" android:duration="50" />
<item android:drawable="@drawable/img19" android:duration="50" />
<item android:drawable="@drawable/img18" android:duration="50" />
<item android:drawable="@drawable/img17" android:duration="50" />
<item android:drawable="@drawable/img16" android:duration="50" />
<item android:drawable="@drawable/img15" android:duration="50" />
<item android:drawable="@drawable/img14" android:duration="50" />
<item android:drawable="@drawable/img13" android:duration="50" />
<item android:drawable="@drawable/img12" android:duration="50" />
<item android:drawable="@drawable/img11" android:duration="50" />
<item android:drawable="@drawable/img10" android:duration="50" />
<item android:drawable="@drawable/img9" android:duration="50" />
<item android:drawable="@drawable/img8" android:duration="50" />
<item android:drawable="@drawable/img7" android:duration="50" />
<item android:drawable="@drawable/img6" android:duration="50" />
<item android:drawable="@drawable/img5" android:duration="50" />
<item android:drawable="@drawable/img4" android:duration="50" />
<item android:drawable="@drawable/img3" android:duration="50" />
<item android:drawable="@drawable/img2" android:duration="50" />
</animation-list>
===========
package com.mrs.xyz;
public class Constant {
public static int Index=0;
public static final String TAG="ABCDFunLite";
public static final String NO_IMAGE="Image Not Found In Gallery";
public static final String EXIT = "Exit?";
public static final String EXIT_MESSAGE = "Do you want to exit?";
public static final String YES = "Yes";
public static final String NO = "No";
public static final int[] ATOZSMALLIMAGES={R.drawable.apple,
R.drawable.butterfly,
R.drawable.cat,
R.drawable.dog,
R.drawable.elephant,
R.drawable.fox,
R.drawable.giraff,
R.drawable.hen,
R.drawable.ice_cream,
R.drawable.jug,
R.drawable.kite,
R.drawable.lion,
R.drawable.monkey,
R.drawable.nest,
R.drawable.owl,
R.drawable.peacock,
R.drawable.queen,
R.drawable.rat,
R.drawable.snack,
R.drawable.tiger,
R.drawable.umbrella,
R.drawable.van,
R.drawable.watch,
R.drawable.xmas,
R.drawable.yawk,
R.drawable.zibra};
// public static final int[] ATOZ_BIGIMAGES={R.drawable.apple_tablet,
// R.drawable.butterfly_tablet,
// R.drawable.cat_tablet,
// R.drawable.dog_tablet,
// R.drawable.elephant_tablet,
// R.drawable.fox_tablet,
// R.drawable.giraff_tablet,
// R.drawable.hen_tablet,
// R.drawable.ice_cream_tablet,
// R.drawable.jug_tablet,
// R.drawable.kite_tablet,
// R.drawable.lion_tablet,
// R.drawable.monkey_tablet,
// R.drawable.nest_tablet,
// R.drawable.owl_tablet,
// R.drawable.peacock_tablet,
// R.drawable.queen_tablet,
// R.drawable.rat_tablet,
// R.drawable.snack_tablet,
// R.drawable.tiger_tablet,
// R.drawable.umbrella_tablet,
// R.drawable.van_tablet,
// R.drawable.watch_tablet,
// R.drawable.xmas_tablet,
// R.drawable.yawk_tablet,
// R.drawable.zibra_tablet};
//
//
public static final int[] AToZSound={R.raw.a,
R.raw.b,
R.raw.c,
R.raw.d,
R.raw.e,
R.raw.f,
R.raw.g,
R.raw.h,
R.raw.i,
R.raw.j,
R.raw.k,
R.raw.l,
R.raw.m,
R.raw.n,
R.raw.o,
R.raw.p,
R.raw.q,
R.raw.r,
R.raw.s,
R.raw.t,
R.raw.u,
R.raw.v,
R.raw.w,
R.raw.x,
R.raw.y,
R.raw.z};
public static final String[] AToZText={"APPLE",
"BUTTERFLY",
"CAT",
"DOG",
"ELEPHANT",
"FOX",
"GIRAFF",
"HEN",
"ICE-CREAM",
"JUG",
"KITE",
"LION",
"MONKEY",
"NEST",
"OWL",
"PEACOCK",
"QUEEN",
"RAT",
"SNAKE",
"TIGER",
"UMBRELLA",
"VAN",
"WATCH",
"X-MAS",
"YAK",
"ZEBRA"};
}
2)IntMap.java
==========
package com.mrs.xyz;
import java.util.Iterator;
import com.drc.abcdfunlite.IntMap.Entry;
/**
* Taken from http://code.google.com/p/skorpios/
*
* @author Nate
*/
public final class IntMap<T> implements Iterable<Entry<T>>, Cloneable {
private Entry<T>[] table;
private final float loadFactor;
private int size, mask, capacity, threshold;
public IntMap() {
this(16, 0.75f);
}
public IntMap(int initialCapacity) {
this(initialCapacity, 0.75f);
}
@SuppressWarnings("unchecked")
public IntMap(int initialCapacity, float loadFactor) {
if (initialCapacity > 1 << 30){
throw new IllegalArgumentException("initialCapacity is too large.");
}
if (initialCapacity < 0){
throw new IllegalArgumentException("initialCapacity must be greater than zero.");
}
if (loadFactor <= 0){
throw new IllegalArgumentException("initialCapacity must be greater than zero.");
}
capacity = 1;
while (capacity < initialCapacity){
capacity <<= 1;
}
this.loadFactor = loadFactor;
this.threshold = (int) (capacity * loadFactor);
this.table = new Entry[capacity];
this.mask = capacity - 1;
}
@SuppressWarnings("unchecked")
public IntMap<T> clone(){
try{
IntMap<T> clone = (IntMap<T>) super.clone();
Entry<T>[] newTable = new Entry[table.length];
for (int i = table.length - 1; i >= 0; i--){
if (table[i] != null)
newTable[i] = table[i].clone();
}
clone.table = newTable;
return clone;
}catch (CloneNotSupportedException ex){
}
return null;
}
public boolean containsValue(Object value) {
Entry<T>[] table = this.table;
for (int i = table.length; i-- > 0;){
for (Entry<T> e = table[i]; e != null; e = e.next){
if (e.value.equals(value)){
return true;
}
}
}
return false;
}
public boolean containsKey(int key) {
int index = ((int) key) & mask;
for (Entry<T> e = table[index]; e != null; e = e.next){
if (e.key == key){
return true;
}
}
return false;
}
public T get(int key) {
int index = key & mask;
for (Entry<T> e = table[index]; e != null; e = e.next){
if (e.key == key){
return e.value;
}
}
return null;
}
@SuppressWarnings("unchecked")
public T put(int key, T value) {
int index = key & mask;
// Check if key already exists.
for (Entry<T> e = table[index]; e != null; e = e.next){
if (e.key != key){
continue;
}
T oldValue = e.value;
e.value = value;
return oldValue;
}
table[index] = new Entry<T>(key, value, table[index]);
if (size++ >= threshold){
// Rehash.
int newCapacity = 2 * capacity;
Entry<T>[] newTable = new Entry[newCapacity];
Entry<T>[] src = table;
int bucketmask = newCapacity - 1;
for (int j = 0; j < src.length; j++){
Entry<T> e = src[j];
if (e != null){
src[j] = null;
do{
Entry<T> next = e.next;
index = e.key & bucketmask;
e.next = newTable[index];
newTable[index] = e;
e = next;
}while (e != null);
}
}
table = newTable;
capacity = newCapacity;
threshold = (int) (newCapacity * loadFactor);
mask = capacity - 1;
}
return null;
}
public T remove(int key) {
int index = key & mask;
Entry<T> prev = table[index];
Entry<T> e = prev;
while (e != null){
Entry<T> next = e.next;
if (e.key == key){
size--;
if (prev == e){
table[index] = next;
}else{
prev.next = next;
}
return (T) e.value;
}
prev = e;
e = next;
}
return null;
}
public int size() {
return size;
}
public void clear() {
Entry<T>[] table = this.table;
for (int index = table.length; --index >= 0;){
table[index] = null;
}
size = 0;
}
public Iterator<Entry<T>> iterator() {
return new IntMapIterator();
}
final class IntMapIterator implements Iterator<Entry<T>> {
/**
* Current entry.
*/
private Entry<T> cur;
/**
* Entry in the table
*/
private int idx = 0;
/**
* Element in the entry
*/
private int el = 0;
public IntMapIterator() {
cur = table[0];
}
public boolean hasNext() {
return el < size;
}
public Entry<T> next() {
if (el >= size)
throw new IllegalStateException("No more elements!");
if (cur != null){
Entry<T> e = cur;
cur = cur.next;
el++;
return e;
}
// if (cur != null && cur.next != null){
// if we have a current entry, continue to the next entry in the list
// cur = cur.next;
// el++;
// return cur;
// }
do {
// either we exhausted the current entry list, or
// the entry was null. find another non-null entry.
cur = table[++idx];
} while (cur == null);
Entry<T> e = cur;
cur = cur.next;
el ++;
return e;
}
public void remove() {
}
}
public static final class Entry<T> implements Cloneable {
final int key;
T value;
Entry<T> next;
Entry(int k, T v, Entry<T> n) {
key = k;
value = v;
next = n;
}
public int getKey(){
return key;
}
public T getValue(){
return value;
}
public String toString(){
return key + " => " + value;
}
@SuppressWarnings("unchecked")
public Entry<T> clone(){
try{
Entry<T> clone = (Entry<T>) super.clone();
clone.next = next != null ? next.clone() : null;
return clone;
}catch (CloneNotSupportedException ex){
}
return null;
}
}
}
3)MainActivity.java
============
package com.mrs.xyz;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Canvas;
import android.graphics.Typeface;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Window;
import android.widget.FrameLayout;
import android.widget.TextView;
public class MainActivity extends Activity {
private static int intTotalimage=0;
private static TextView txtspelling=null;
private static Context mContext = null;
private PageCurlView mPageCurlView=null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.xatoz);
mContext = this;
txtspelling=(TextView)findViewById(R.id.txtspelling);
txtspelling.setTypeface(setFontNormal());
Previous_SoundId=0;
Previous_SoundId_Position=0;
intTotalimage=Constant.ATOZSMALLIMAGES.length;
if(intTotalimage > 0)
{
txtspelling.setText(Constant.AToZText[Constant.Index]);
}
//this code write for first time init sound
if(sound_status){
sound_status=false;
Previous_SoundId=Constant.AToZSound[Constant.Index];
InitSound();
}
FrameLayout frmlayout=(FrameLayout)findViewById(R.id.frmlayout);
mPageCurlView=new PageCurlView(this,Constant.Index);
mPageCurlView.SetCurlSpeed(70);
mPageCurlView.SetUpdateRate(60);
mPageCurlView.SetInitialEdgeOffset(30);
txtspelling.setTextSize(30);
mPageCurlView.SetCurlMode(PageCurlView.FOCUS_BACKWARD);
//}
frmlayout.addView(mPageCurlView);
}
@Override
public void onDestroy(){
Constant.Index=mPageCurlView.GetIndex();
mPageCurlView.Recycle_Images();
mPageCurlView=null;
super.onDestroy();
}
private void InitSound(){
for(int i=0;i < Constant.AToZSound.length ;i++){
Sound_PlayAction(this,Constant.AToZSound[i]);
}
}
private Typeface setFontNormal(){
return Typeface.createFromAsset(getResources().getAssets(), "font/ovte.ttf");
}
private static boolean sound_status=true;
private static int Previous_SoundId=0;
private static int Previous_SoundId_Position=0;
private static void Sound_PlayAction(Context context,int sound_id){
if(sound_id > 0){
SoundEngine.sharedEngine().playEffect(context, sound_id);
}
}
private static void Sound_StopAction(Context context,int sound_id){
if(sound_id > 0){
SoundEngine.sharedEngine().stopEffect(context, sound_id);
}
}
public static int Previous_Position=-1;
public static void drawPageNum(Canvas canvas, int position)
{
if(Previous_Position!=position){
//Log.d("abc", "switched to screen: " + position);
Constant.Index=position;
//this code for previous sound stop
Previous_SoundId = Constant.AToZSound[Previous_SoundId_Position];
Sound_StopAction(mContext,Previous_SoundId);
Previous_SoundId_Position=Constant.Index;
// this code for play sound file
Sound_PlayAction(mContext,Constant.AToZSound[Constant.Index]);
txtspelling.setText(Constant.AToZText[Constant.Index]);
}
Previous_Position=position;
Log.i("Index",""+position);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
//Handle the back button
if(keyCode == KeyEvent.KEYCODE_BACK) {
//Ask the user if they want to quit
new AlertDialog.Builder(this)
.setIcon(R.drawable.icmenuexit)
.setTitle(Constant.EXIT)
.setMessage(Constant.EXIT_MESSAGE)
.setPositiveButton(Constant.YES, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
//Stop the activity
//maintenancetabs.this.finish();
int pid = android.os.Process.myPid();
android.os.Process.killProcess(pid);
}
})
.setNegativeButton(Constant.NO, null)
.show();
return true;
} else {
return super.onKeyDown(keyCode, event);
}
}
}
4)PageCurlView.java
============
package com.mrs.xyz;
import java.lang.ref.WeakReference;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.Rect;
import android.os.Handler;
import android.os.Message;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
public class PageCurlView extends View {
/** Our Log tag */
private final static String TAG = "PageCurlView";
// Debug text paint stuff
private Paint mTextPaint;
private TextPaint mTextPaintShadow;
/** Px / Draw call */
private int mCurlSpeed;
/** Fixed update time used to create a smooth curl animation */
private int mUpdateRate;
/** The initial offset for x and y axis movements */
private int mInitialEdgeOffset;
/** The mode we will use */
private int mCurlMode;
/** Simple curl mode. Curl target will move only in one axis. */
public static final int CURLMODE_SIMPLE = 0;
/** Dynamic curl mode. Curl target will move on both X and Y axis. */
public static final int CURLMODE_DYNAMIC = 1;
/** Enable/Disable debug mode */
private boolean bEnableDebugMode = false;
/** The context which owns us */
private WeakReference<Context> mContext;
/** Handler used to auto flip time based */
private FlipAnimationHandler mAnimationHandler;
/** Maximum radius a page can be flipped, by default it's the width of the view */
private float mFlipRadius;
/** Point used to move */
private Vector2D mMovement;
/** The finger position */
private Vector2D mFinger;
/** Movement point form the last frame */
private Vector2D mOldMovement;
/** Page curl edge */
private Paint mCurlEdgePaint;
/** Our points used to define the current clipping paths in our draw call */
private Vector2D mA, mB, mC, mD, mE, mF, mOldF, mOrigin;
/** Left and top offset to be applied when drawing */
private int mCurrentLeft, mCurrentTop;
/** If false no draw call has been done */
private boolean bViewDrawn;
/** Defines the flip direction that is currently considered */
private boolean bFlipRight;
/** If TRUE we are currently auto-flipping */
private boolean bFlipping;
/** TRUE if the user moves the pages */
private boolean bUserMoves;
/** Used to control touch input blocking */
private boolean bBlockTouchInput = false;
/** Enable input after the next draw event */
private boolean bEnableInputAfterDraw = false;
/** LAGACY The current foreground */
private Bitmap mForeground;
/** LAGACY The current background */
private Bitmap mBackground;
/** LAGACY List of pages, this is just temporal */
// private ArrayList<Bitmap> mPages;
/** LAGACY Current selected page */
private int mIndex = 0;
/**
* Inner class used to represent a 2D point.
*/
private class Vector2D
{
public float x,y;
public Vector2D(float x, float y)
{
this.x = x;
this.y = y;
}
@Override
public String toString() {
// TODO Auto-generated method stub
return "("+this.x+","+this.y+")";
}
public float length() {
return (float) Math.sqrt(x * x + y * y);
}
public float lengthSquared() {
return (x * x) + (y * y);
}
public boolean equals(Object o) {
if (o instanceof Vector2D) {
Vector2D p = (Vector2D) o;
return p.x == x && p.y == y;
}
return false;
}
public Vector2D reverse() {
return new Vector2D(-x,-y);
}
public Vector2D sum(Vector2D b) {
return new Vector2D(x+b.x,y+b.y);
}
public Vector2D sub(Vector2D b) {
return new Vector2D(x-b.x,y-b.y);
}
public float dot(Vector2D vec) {
return (x * vec.x) + (y * vec.y);
}
public float cross(Vector2D vec) {
return x * vec.y - y * vec.x;
}
public float distanceSquared(Vector2D other) {
float dx = other.x - x;
float dy = other.y - y;
return (dx * dx) + (dy * dy);
}
public float distance(Vector2D other) {
return (float) Math.sqrt(distanceSquared(other));
}
public float dotProduct(Vector2D other) {
return other.x * x + other.y * y;
}
public Vector2D normalize() {
float magnitude = (float) Math.sqrt(dotProduct(this));
return new Vector2D(x / magnitude, y / magnitude);
}
public Vector2D mult(float scalar) {
return new Vector2D(x*scalar,y*scalar);
}
}
/**
* Inner class used to make a fixed timed animation of the curl effect.
*/
class FlipAnimationHandler extends Handler {
@Override
public void handleMessage(Message msg) {
PageCurlView.this.FlipAnimationStep();
}
public void sleep(long millis) {
this.removeMessages(0);
sendMessageDelayed(obtainMessage(0), millis);
}
}
/**
* Base
* @param context
*/
public PageCurlView(Context context,int Index) {
super(context);
init(context,Index);
ResetClipEdge();
}
/**
* Construct the object from an XML file. Valid Attributes:
*
* @see android.view.View#View(android.content.Context, android.util.AttributeSet)
*/
public PageCurlView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context,0);
// Get the data from the XML AttributeSet
{
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PageCurlView);
// Get data
bEnableDebugMode = a.getBoolean(R.styleable.PageCurlView_enableDebugMode, bEnableDebugMode);
mCurlSpeed = a.getInt(R.styleable.PageCurlView_curlSpeed, mCurlSpeed);
mUpdateRate = a.getInt(R.styleable.PageCurlView_updateRate, mUpdateRate);
mInitialEdgeOffset = a.getInt(R.styleable.PageCurlView_initialEdgeOffset, mInitialEdgeOffset);
mCurlMode = a.getInt(R.styleable.PageCurlView_curlMode, mCurlMode);
// Log.i(TAG, "mCurlSpeed: " + mCurlSpeed);
// Log.i(TAG, "mUpdateRate: " + mUpdateRate);
// Log.i(TAG, "mInitialEdgeOffset: " + mInitialEdgeOffset);
// Log.i(TAG, "mCurlMode: " + mCurlMode);
// recycle object (so it can be used by others)
a.recycle();
}
ResetClipEdge();
}
/**
* Initialize the view
*/
private final void init(Context context,int Index) {
try{
// Foreground text paint
mTextPaint = new Paint();
mTextPaint.setDither(true);
mTextPaint.setAntiAlias(true);
mTextPaint.setTextSize(14);
mTextPaint.setColor(0xFF000000);
// The shadow
mTextPaintShadow = new TextPaint();
mTextPaintShadow.setDither(true);
mTextPaintShadow.setAntiAlias(true);
mTextPaintShadow.setTextSize(14);
mTextPaintShadow.setColor(0x00000000);
// Cache the context
mContext = new WeakReference<Context>(context);
// Base padding
setPadding(3, 3, 3, 3);
// The focus flags are needed
setFocusable(true);
setFocusableInTouchMode(true);
mMovement = new Vector2D(0,0);
mFinger = new Vector2D(0,0);
mOldMovement = new Vector2D(0,0);
// Create our curl animation handler
mAnimationHandler = new FlipAnimationHandler();
// Create our edge paint
mCurlEdgePaint = new Paint();
mCurlEdgePaint.setDither(true);
mCurlEdgePaint.setColor(Color.WHITE);
mCurlEdgePaint.setAntiAlias(true);
mCurlEdgePaint.setStyle(Paint.Style.FILL);
mCurlEdgePaint.setShadowLayer(10, -5, 5, 0x99000000);
// Set the default props, those come from an XML :D
mCurlSpeed = 30;
mUpdateRate = 33;
mInitialEdgeOffset = 20;
mCurlMode = 1;
// Create some sample images
mIndex=Index;
// if(MainActivity.Check_Resolution()){
// mForeground = BitmapFactory.decodeResource(getResources(), Constant.ATOZ_BIGIMAGES[mIndex]);
// mBackground = BitmapFactory.decodeResource(getResources(), Constant.ATOZ_BIGIMAGES[mIndex+1]);
// }
// else{
mForeground = BitmapFactory.decodeResource(getResources(), Constant.ATOZSMALLIMAGES[mIndex]);
mBackground = BitmapFactory.decodeResource(getResources(), Constant.ATOZSMALLIMAGES[mIndex+1]);
// }
}catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
/**
* Get current Index
*/
public int GetIndex() {
return mIndex;
}
/**
* Relese Bitmap Memory
*/
public void Recycle_Images() {
if(mForeground!=null){
if(!mForeground.isRecycled()){
mForeground.recycle();
}
}
if(mBackground!=null){
if(!mBackground.isRecycled()){
mBackground.recycle();
}
}
System.gc();
}
/**
* Reset points to it's initial clip edge state
*/
public void ResetClipEdge()
{
// Set our base movement
mMovement.x = mInitialEdgeOffset;
mMovement.y = mInitialEdgeOffset;
mOldMovement.x = 0;
mOldMovement.y = 0;
// Now set the points
// TODO: OK, those points MUST come from our measures and
// the actual bounds of the view!
mA = new Vector2D(mInitialEdgeOffset, 0);
mB = new Vector2D(this.getWidth(), this.getHeight());
mC = new Vector2D(this.getWidth(), 0);
mD = new Vector2D(0, 0);
mE = new Vector2D(0, 0);
mF = new Vector2D(0, 0);
mOldF = new Vector2D(0, 0);
// The movement origin point
mOrigin = new Vector2D(this.getWidth(), 0);
}
/**
* Return the context which created use. Can return null if the
* context has been erased.
*/
private Context GetContext() {
return mContext.get();
}
/**
* See if the current curl mode is dynamic
* @return TRUE if the mode is CURLMODE_DYNAMIC, FALSE otherwise
*/
public boolean IsCurlModeDynamic()
{
return mCurlMode == CURLMODE_DYNAMIC;
}
/**
* Set the curl speed.
* @param curlSpeed - New speed in px/frame
* @throws IllegalArgumentException if curlspeed < 1
*/
public void SetCurlSpeed(int curlSpeed)
{
if ( curlSpeed < 1 )
throw new IllegalArgumentException("curlSpeed must be greated than 0");
mCurlSpeed = curlSpeed;
}
/**
* Get the current curl speed
* @return int - Curl speed in px/frame
*/
public int GetCurlSpeed()
{
return mCurlSpeed;
}
/**
* Set the update rate for the curl animation
* @param updateRate - Fixed animation update rate in fps
* @throws IllegalArgumentException if updateRate < 1
*/
public void SetUpdateRate(int updateRate)
{
if ( updateRate < 1 )
throw new IllegalArgumentException("updateRate must be greated than 0");
mUpdateRate = updateRate;
}
/**
* Get the current animation update rate
* @return int - Fixed animation update rate in fps
*/
public int GetUpdateRate()
{
return mUpdateRate;
}
/**
* Set the initial pixel offset for the curl edge
* @param initialEdgeOffset - px offset for curl edge
* @throws IllegalArgumentException if initialEdgeOffset < 0
*/
public void SetInitialEdgeOffset(int initialEdgeOffset)
{
if ( initialEdgeOffset < 0 )
throw new IllegalArgumentException("initialEdgeOffset can not negative");
mInitialEdgeOffset = initialEdgeOffset;
}
/**
* Get the initial pixel offset for the curl edge
* @return int - px
*/
public int GetInitialEdgeOffset()
{
return mInitialEdgeOffset;
}
/**
* Set the curl mode.
* <p>Can be one of the following values:</p>
* <table>
* <colgroup align="left" />
* <colgroup align="left" />
* <tr><th>Value</th><th>Description</th></tr>
* <tr><td><code>{@link #CURLMODE_SIMPLE com.dcg.pagecurl:CURLMODE_SIMPLE}</code></td><td>Curl target will move only in one axis.</td></tr>
* <tr><td><code>{@link #CURLMODE_DYNAMIC com.dcg.pagecurl:CURLMODE_DYNAMIC}</code></td><td>Curl target will move on both X and Y axis.</td></tr>
* </table>
* @see #CURLMODE_SIMPLE
* @see #CURLMODE_DYNAMIC
* @param curlMode
* @throws IllegalArgumentException if curlMode is invalid
*/
public void SetCurlMode(int curlMode)
{
if ( curlMode != CURLMODE_SIMPLE &&
curlMode != CURLMODE_DYNAMIC )
throw new IllegalArgumentException("Invalid curlMode");
mCurlMode = curlMode;
}
/**
* Return an integer that represents the current curl mode.
* <p>Can be one of the following values:</p>
* <table>
* <colgroup align="left" />
* <colgroup align="left" />
* <tr><th>Value</th><th>Description</th></tr>
* <tr><td><code>{@link #CURLMODE_SIMPLE com.dcg.pagecurl:CURLMODE_SIMPLE}</code></td><td>Curl target will move only in one axis.</td></tr>
* <tr><td><code>{@link #CURLMODE_DYNAMIC com.dcg.pagecurl:CURLMODE_DYNAMIC}</code></td><td>Curl target will move on both X and Y axis.</td></tr>
* </table>
* @see #CURLMODE_SIMPLE
* @see #CURLMODE_DYNAMIC
* @return int - current curl mode
*/
public int GetCurlMode()
{
return mCurlMode;
}
/**
* Enable debug mode. This will draw a lot of data in the view so you can track what is happening
* @param bFlag - boolean flag
*/
public void SetEnableDebugMode(boolean bFlag)
{
bEnableDebugMode = bFlag;
}
/**
* Check if we are currently in debug mode.
* @return boolean - If TRUE debug mode is on, FALSE otherwise.
*/
public boolean IsDebugModeEnabled()
{
return bEnableDebugMode;
}
/**
* @see android.view.View#measure(int, int)
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int finalWidth, finalHeight;
finalWidth = measureWidth(widthMeasureSpec);
finalHeight = measureHeight(heightMeasureSpec);
setMeasuredDimension(finalWidth, finalHeight);
}
/**
* Determines the width of this view
* @param measureSpec A measureSpec packed into an int
* @return The width of the view, honoring constraints from measureSpec
*/
private int measureWidth(int measureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
// We were told how big to be
result = specSize;
} else {
// Measure the text
result = specSize;
}
return result;
}
/**
* Determines the height of this view
* @param measureSpec A measureSpec packed into an int
* @return The height of the view, honoring constraints from measureSpec
*/
private int measureHeight(int measureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
// We were told how big to be
result = specSize;
} else {
// Measure the text (beware: ascent is a negative number)
result = specSize;
}
return result;
}
/**
* Render the text
*
* @see android.view.View#onDraw(android.graphics.Canvas)
*/
//@Override
//protected void onDraw(Canvas canvas) {
// super.onDraw(canvas);
// canvas.drawText(mText, getPaddingLeft(), getPaddingTop() - mAscent, mTextPaint);
//}
//---------------------------------------------------------------
// Curling. This handles touch events, the actual curling
// implementations and so on.
//---------------------------------------------------------------
@Override
public boolean onTouchEvent(MotionEvent event) {
if (!bBlockTouchInput) {
// Get our finger position
mFinger.x = event.getX();
mFinger.y = event.getY();
int width = getWidth();
// Depending on the action do what we need to
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mOldMovement.x = mFinger.x;
mOldMovement.y = mFinger.y;
// If we moved over the half of the display flip to next
if (mOldMovement.x > (width >> 1)) {
mMovement.x = mInitialEdgeOffset;
mMovement.y = mInitialEdgeOffset;
// Set the right movement flag
bFlipRight = true;
} else {
// Set the left movement flag
bFlipRight = false;
// go to next previous page
previousView();
// Set new movement
mMovement.x = IsCurlModeDynamic()?width<<1:width;
mMovement.y = mInitialEdgeOffset;
}
break;
case MotionEvent.ACTION_UP:
bUserMoves=false;
bFlipping=true;
FlipAnimationStep();
break;
case MotionEvent.ACTION_MOVE:
bUserMoves=true;
// Get movement
mMovement.x -= mFinger.x - mOldMovement.x;
mMovement.y -= mFinger.y - mOldMovement.y;
mMovement = CapMovement(mMovement, true);
// Make sure the y value get's locked at a nice level
if ( mMovement.y <= 1 )
mMovement.y = 1;
// Get movement direction
if (mFinger.x < mOldMovement.x ) {
bFlipRight = true;
} else {
bFlipRight = false;
}
// Save old movement values
mOldMovement.x = mFinger.x;
mOldMovement.y = mFinger.y;
// Force a new draw call
DoPageCurl();
this.invalidate();
break;
}
}
// TODO: Only consume event if we need to.
return true;
}
/**
* Make sure we never move too much, and make sure that if we
* move too much to add a displacement so that the movement will
* be still in our radius.
* @param radius - radius form the flip origin
* @param bMaintainMoveDir - Cap movement but do not change the
* current movement direction
* @return Corrected point
*/
private Vector2D CapMovement(Vector2D point, boolean bMaintainMoveDir)
{
// Make sure we never ever move too much
if (point.distance(mOrigin) > mFlipRadius)
{
if ( bMaintainMoveDir )
{
// Maintain the direction
point = mOrigin.sum(point.sub(mOrigin).normalize().mult(mFlipRadius));
}
else
{
// Change direction
if ( point.x > (mOrigin.x+mFlipRadius))
point.x = (mOrigin.x+mFlipRadius);
else if ( point.x < (mOrigin.x-mFlipRadius) )
point.x = (mOrigin.x-mFlipRadius);
point.y = (float) (Math.sin(Math.acos(Math.abs(point.x-mOrigin.x)/mFlipRadius))*mFlipRadius);
}
}
return point;
}
/**
* Execute a step of the flip animation
*/
public void FlipAnimationStep() {
if ( !bFlipping )
return;
int width = getWidth();
// No input when flipping
bBlockTouchInput = true;
// Handle speed
float curlSpeed = mCurlSpeed;
if ( !bFlipRight )
curlSpeed *= -1;
// Move us
mMovement.x += curlSpeed;
mMovement = CapMovement(mMovement, false);
// Create values
DoPageCurl();
if (mA.x < 1 || mA.x > width - 1) {
bFlipping = false;
if (bFlipRight) {
//SwapViews();
nextView();
}
ResetClipEdge();
// Create values
DoPageCurl();
// Enable touch input after the next draw event
bEnableInputAfterDraw = true;
}
else
{
mAnimationHandler.sleep(mUpdateRate);
}
// Force a new draw call
this.invalidate();
}
/**
* Do the page curl depending on the methods we are using
*/
private void DoPageCurl()
{
if(bFlipping){
if ( IsCurlModeDynamic() )
doDynamicCurl();
else
doSimpleCurl();
} else {
if ( IsCurlModeDynamic() )
doDynamicCurl();
else
doSimpleCurl();
}
}
/**
* Do a simple page curl effect
*/
private void doSimpleCurl() {
int width = getWidth();
int height = getHeight();
// Calculate point A
mA.x = width - mMovement.x;
mA.y = height;
// Calculate point D
mD.x = 0;
mD.y = 0;
if (mA.x > width / 2) {
mD.x = width;
mD.y = height - (width - mA.x) * height / mA.x;
} else {
mD.x = 2 * mA.x;
mD.y = 0;
}
// Now calculate E and F taking into account that the line
// AD is perpendicular to FB and EC. B and C are fixed points.
double angle = Math.atan((height - mD.y) / (mD.x + mMovement.x - width));
double _cos = Math.cos(2 * angle);
double _sin = Math.sin(2 * angle);
// And get F
mF.x = (float) (width - mMovement.x + _cos * mMovement.x);
mF.y = (float) (height - _sin * mMovement.x);
// If the x position of A is above half of the page we are still not
// folding the upper-right edge and so E and D are equal.
if (mA.x > width / 2) {
mE.x = mD.x;
mE.y = mD.y;
}
else
{
// So get E
mE.x = (float) (mD.x + _cos * (width - mD.x));
mE.y = (float) -(_sin * (width - mD.x));
}
}
/**
* Calculate the dynamic effect, that one that follows the users finger
*/
private void doDynamicCurl() {
int width = getWidth();
int height = getHeight();
// F will follow the finger, we add a small displacement
// So that we can see the edge
mF.x = width - mMovement.x+0.1f;
mF.y = height - mMovement.y+0.1f;
// Set min points
if(mA.x==0) {
mF.x= Math.min(mF.x, mOldF.x);
mF.y= Math.max(mF.y, mOldF.y);
}
// Get diffs
float deltaX = width-mF.x;
float deltaY = height-mF.y;
float BH = (float) (Math.sqrt(deltaX * deltaX + deltaY * deltaY) / 2);
double tangAlpha = deltaY / deltaX;
double alpha = Math.atan(deltaY / deltaX);
double _cos = Math.cos(alpha);
double _sin = Math.sin(alpha);
mA.x = (float) (width - (BH / _cos));
mA.y = height;
mD.y = (float) (height - (BH / _sin));
mD.x = width;
mA.x = Math.max(0,mA.x);
if(mA.x==0) {
mOldF.x = mF.x;
mOldF.y = mF.y;
}
// Get W
mE.x = mD.x;
mE.y = mD.y;
// Correct
if (mD.y < 0) {
mD.x = width + (float) (tangAlpha * mD.y);
mE.y = 0;
mE.x = width + (float) (Math.tan(2 * alpha) * mD.y);
}
}
/**
* Swap between the fore and back-ground.
*/
@Deprecated
private void SwapViews() {
Bitmap temp=null;
try{
temp = mForeground;
mForeground = mBackground;
mBackground = temp;
}
catch (Exception e) {
e.printStackTrace();
}
finally{
if(temp!=null){
if(!temp.isRecycled()){
temp.recycle();
}
}
}
}
/**
* Swap to next view
*/
private void nextView() {
int foreIndex = mIndex + 1;
if(foreIndex >= Constant.ATOZSMALLIMAGES.length) {
System.out.println("nextView===="+Constant.ATOZSMALLIMAGES.length);
foreIndex =0;
}
int backIndex = foreIndex + 1;
if(backIndex >= Constant.ATOZSMALLIMAGES.length) {
backIndex =0;
}
mIndex = foreIndex;
setViews(foreIndex, backIndex);
}
/**
* Swap to previous view
*/
private void previousView() {
int backIndex = mIndex;
int foreIndex = backIndex - 1;
if(foreIndex < 0) {
foreIndex = Constant.ATOZSMALLIMAGES.length -1;
}
mIndex = foreIndex;
setViews(foreIndex, backIndex);
}
/**
* Set current fore and background
* @param foreground - Foreground view index
* @param background - Background view index
*/
private void setViews(int foreground, int background) {
if(mForeground!=null){
if(!mForeground.isRecycled()){
mForeground.recycle();
}
}
if(mBackground!=null){
if(!mBackground.isRecycled()){
mBackground.recycle();
}
}
// if(MainActivity.Check_Resolution()){
// mForeground = BitmapFactory.decodeResource(getResources(), Constant.ATOZ_BIGIMAGES[foreground]);
// mBackground = BitmapFactory.decodeResource(getResources(), Constant.ATOZ_BIGIMAGES[background]);
// }
// else{
mForeground = BitmapFactory.decodeResource(getResources(), Constant.ATOZSMALLIMAGES[foreground]);
mBackground = BitmapFactory.decodeResource(getResources(), Constant.ATOZSMALLIMAGES[background]);
//}
}
//---------------------------------------------------------------
// Drawing methods
//---------------------------------------------------------------
@Override
protected void onDraw(Canvas canvas) {
// Always refresh offsets
mCurrentLeft = getLeft();
mCurrentTop = getTop();
// Translate the whole canvas
//canvas.translate(mCurrentLeft, mCurrentTop);
// We need to initialize all size data when we first draw the view
if ( !bViewDrawn ) {
bViewDrawn = true;
onFirstDrawEvent(canvas);
}
canvas.drawColor(Color.WHITE);
// Curl pages
//DoPageCurl();
// TODO: This just scales the views to the current
// width and height. We should add some logic for:
// 1) Maintain aspect ratio
// 2) Uniform scale
// 3) ...
Rect rect = new Rect();
rect.left = 0;
rect.top = 0;
rect.bottom = getHeight();
rect.right = getWidth();
// First Page render
Paint paint = new Paint();
paint.setDither(true);
// Draw our elements
drawForeground(canvas, rect, paint);
drawBackground(canvas, rect, paint);
drawCurlEdge(canvas);
// Draw any debug info once we are done
if ( bEnableDebugMode )
drawDebug(canvas);
// Check if we can re-enable input
if ( bEnableInputAfterDraw )
{
bBlockTouchInput = false;
bEnableInputAfterDraw = false;
}
}
/**
* Called on the first draw event of the view
* @param canvas
*/
protected void onFirstDrawEvent(Canvas canvas) {
mFlipRadius = getWidth();
ResetClipEdge();
DoPageCurl();
}
/**
* Draw the foreground
* @param canvas
* @param rect
* @param paint
*/
private void drawForeground( Canvas canvas, Rect rect, Paint paint ) {
paint.setDither(true);
canvas.drawBitmap(mForeground, null, rect, paint);
// Draw the page number (first page is 1 in real life :D
// there is no page number 0 hehe)
MainActivity.drawPageNum(canvas, mIndex);
}
/**
* Create a Path used as a mask to draw the background page
* @return
*/
private Path createBackgroundPath() {
Path path = new Path();
path.moveTo(mA.x, mA.y);
path.lineTo(mB.x, mB.y);
path.lineTo(mC.x, mC.y);
path.lineTo(mD.x, mD.y);
path.lineTo(mA.x, mA.y);
return path;
}
/**
* Draw the background image.
* @param canvas
* @param rect
* @param paint
*/
private void drawBackground( Canvas canvas, Rect rect, Paint paint ) {
try{
paint.setDither(true);
Path mask = createBackgroundPath();
// Save current canvas so we do not mess it up
canvas.save();
canvas.clipPath(mask);
canvas.drawBitmap(mBackground, null, rect, paint);
// Draw the page number (first page is 1 in real life :D
// there is no page number 0 hehe)
MainActivity.drawPageNum(canvas, mIndex);
canvas.restore();
}catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
/**
* Creates a path used to draw the curl edge in.
* @return
*/
private Path createCurlEdgePath() {
Path path = new Path();
path.moveTo(mA.x, mA.y);
path.lineTo(mD.x, mD.y);
path.lineTo(mE.x, mE.y);
path.lineTo(mF.x, mF.y);
path.lineTo(mA.x, mA.y);
return path;
}
/**
* Draw the curl page edge
* @param canvas
*/
private void drawCurlEdge( Canvas canvas )
{
Path path = createCurlEdgePath();
canvas.drawPath(path, mCurlEdgePaint);
}
/**
* Draw page num (let this be a bit more custom)
* @param canvas
* @param pageNum
*/
//---------------------------------------------------------------
// Debug draw methods
//---------------------------------------------------------------
/**
* Draw a text with a nice shadow
*/
public static void drawTextShadowed(Canvas canvas, String text, float x, float y, Paint textPain, Paint shadowPaint) {
shadowPaint.setDither(true);
textPain.setDither(true);
canvas.drawText(text, x-1, y, shadowPaint);
canvas.drawText(text, x, y+1, shadowPaint);
canvas.drawText(text, x+1, y, shadowPaint);
canvas.drawText(text, x, y-1, shadowPaint);
canvas.drawText(text, x, y, textPain);
}
/**
* Draw a text with a nice shadow centered in the X axis
* @param canvas
* @param text
* @param y
* @param textPain
* @param shadowPaint
*/
public static void drawCentered(Canvas canvas, String text, float y, Paint textPain, Paint shadowPaint)
{
shadowPaint.setDither(true);
textPain.setDither(true);
float posx = (canvas.getWidth() - textPain.measureText(text))/2;
drawTextShadowed(canvas, text, posx, y, textPain, shadowPaint);
}
/**
* Draw debug info
* @param canvas
*/
private void drawDebug(Canvas canvas)
{
float posX = 10;
float posY = 20;
Paint paint = new Paint();
paint.setDither(true);
paint.setStrokeWidth(5);
paint.setStyle(Style.FILL_AND_STROKE);
paint.setColor(Color.BLACK);
canvas.drawCircle(mOrigin.x, mOrigin.y, getWidth(), paint);
paint.setStrokeWidth(3);
paint.setColor(Color.RED);
canvas.drawCircle(mOrigin.x, mOrigin.y, getWidth(), paint);
paint.setStrokeWidth(5);
paint.setColor(Color.BLACK);
canvas.drawLine(mOrigin.x, mOrigin.y, mMovement.x, mMovement.y, paint);
paint.setStrokeWidth(3);
paint.setColor(Color.RED);
canvas.drawLine(mOrigin.x, mOrigin.y, mMovement.x, mMovement.y, paint);
posY = debugDrawPoint(canvas,"A",mA,Color.RED,posX,posY);
posY = debugDrawPoint(canvas,"B",mB,Color.GREEN,posX,posY);
posY = debugDrawPoint(canvas,"C",mC,Color.BLUE,posX,posY);
posY = debugDrawPoint(canvas,"D",mD,Color.CYAN,posX,posY);
posY = debugDrawPoint(canvas,"E",mE,Color.YELLOW,posX,posY);
posY = debugDrawPoint(canvas,"F",mF,Color.LTGRAY,posX,posY);
posY = debugDrawPoint(canvas,"Mov",mMovement,Color.DKGRAY,posX,posY);
posY = debugDrawPoint(canvas,"Origin",mOrigin,Color.MAGENTA,posX,posY);
posY = debugDrawPoint(canvas,"Finger",mFinger,Color.GREEN,posX,posY);
}
private float debugDrawPoint(Canvas canvas, String name, Vector2D point, int color, float posX, float posY) {
return debugDrawPoint(canvas,name+" "+point.toString(),point.x, point.y, color, posX, posY);
}
private float debugDrawPoint(Canvas canvas, String name, float X, float Y, int color, float posX, float posY) {
mTextPaint.setColor(color);
drawTextShadowed(canvas,name,posX , posY, mTextPaint,mTextPaintShadow);
Paint paint = new Paint();
paint.setDither(true);
paint.setStrokeWidth(5);
paint.setColor(color);
canvas.drawPoint(X, Y, paint);
return posY+15;
}
}
5)SoundEngine.java
=============
package com.mrs.xyz;
import java.io.IOException;
import android.content.Context;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.SoundPool;
import com.drc.abcdfunlite.IntMap.Entry;
// TODO: support volume customizations for both effects and background ...
public class SoundEngine {
// effects are sounds that less than 5 seconds, better in 3 seconds
IntMap<Integer> effectsMap = new IntMap<Integer>();
IntMap<Integer> streamsMap = new IntMap<Integer>();
// sounds are background sounds, usually longer than 5 seconds
IntMap<MediaPlayer> soundsMap = new IntMap<MediaPlayer>();
SoundPool sp = new SoundPool(5, AudioManager.STREAM_MUSIC, 0);
int lastSndId = -1;
Float prevEffectsVolume = null;
Float prevSoundsVolume = null;
Float effectsVolume = null;
Float soundsVolume = null;
boolean mute = false;
static SoundEngine _sharedEngine = null;
public static SoundEngine sharedEngine() {
synchronized(SoundEngine.class) {
if (_sharedEngine == null) {
_sharedEngine = new SoundEngine();
}
}
return _sharedEngine;
}
public static void purgeSharedEngine() {
synchronized(SoundEngine.class) {
_sharedEngine = null;
}
}
public void setEffectsVolume(Float volume) {
if (mute)
return;
effectsVolume = volume;
}
public Float getEffectsVolume() {
return effectsVolume;
}
public void setSoundVolume(Float volume) {
if (mute)
return;
soundsVolume = volume;
for (Entry<MediaPlayer> each : soundsMap)
{
each.getValue().setVolume(soundsVolume, soundsVolume);
}
}
public Float getSoundsVolume() {
return soundsVolume;
}
public void mute() {
if (mute)
return;
prevEffectsVolume = effectsVolume;
prevSoundsVolume = soundsVolume;
effectsVolume = 0f;
setSoundVolume(0f);
mute = true;
}
public void unmute() {
if (!mute)
return;
effectsVolume = prevEffectsVolume;
mute = false;
setSoundVolume(prevSoundsVolume);
}
public boolean isMute() {
return mute;
}
public void preloadEffect(Context app, int resId){
synchronized(effectsMap) {
Integer sndId = effectsMap.get(resId);
if (sndId != null)
return;
sndId = sp.load(app, resId, 0);
effectsMap.put(resId, sndId);
}
}
public void playEffect(Context app, int resId) {
Integer sndId = -1;
synchronized (effectsMap) {
sndId = effectsMap.get(resId);
if (sndId == null) {
sndId = sp.load(app, resId, 0);
effectsMap.put(resId, sndId);
}
}
int streamId = sp.play(sndId, 1.0f, 1.0f, 0, 0, 1.0f);
if (effectsVolume != null) {
sp.setVolume(streamId, effectsVolume, effectsVolume);
}
streamsMap.put(resId, streamId);
}
public void stopEffect(Context app, int resId) {
Integer sid = streamsMap.get(resId);
if (sid != null) {
sp.stop(sid);
}
}
public void preloadSound(Context ctxt, int resId) {
synchronized(soundsMap) {
MediaPlayer mp = soundsMap.get(resId);
if (mp != null)
return;
mp = MediaPlayer.create(ctxt, resId);
// mp.prepareAsync();
soundsMap.put(resId, mp);
}
}
public void playSound(Context ctxt, int resId, boolean loop) {
if (lastSndId != -1) {
pauseSound();
}
MediaPlayer mp = null;
synchronized(soundsMap) {
mp = soundsMap.get(resId);
if (mp == null) {
mp = MediaPlayer.create(ctxt, resId);
// failed to create
if(mp == null)
return;
soundsMap.put(resId, mp);
try {
mp.prepare();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
lastSndId = resId;
mp.start();
if (soundsVolume != null)
mp.setVolume(soundsVolume, soundsVolume);
if (loop)
mp.setLooping(true);
}
public void pauseSound() {
if (lastSndId == -1)
return;
MediaPlayer mp = null;
synchronized(soundsMap) {
mp = soundsMap.get(lastSndId);
if (mp == null)
return;
}
mp.pause();
}
public void resumeSound() {
if (lastSndId == -1)
return;
MediaPlayer mp = null;
synchronized(soundsMap) {
mp = soundsMap.get(lastSndId);
if (mp == null)
return;
}
mp.start();
}
public void realesSound(int resId)
{
MediaPlayer mp = null;
synchronized(soundsMap) {
mp = soundsMap.get(resId);
if (mp != null) {
mp.release();
soundsMap.remove(resId);
}
}
}
public void realesAllSounds() {
for(Entry<MediaPlayer> mp : soundsMap) {
mp.getValue().release();
}
soundsMap.clear();
}
public void realesAllEffects() {
sp.release();
}
}
6)SplashScreen.java
============
package com.mrs.xyz;
import android.app.Activity;
import android.app.Dialog;
import android.content.Intent;
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
public class SplashScreen extends Activity {
private Dialog mDialog = null;
private float X1=0,X2=0,Y1=0,Y2=0;
public ImageView imgArrow;
private ImageView animation;
private LinearLayout lytSplash;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.xsplashscreen);
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
Constant.Index=0;
lytSplash = (LinearLayout)findViewById(R.id.lytSplash);
lytSplash.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
NextActivity();
}
});
animation = (ImageView)findViewById(R.id.imageAnimation);
// if(MainActivity.Check_Resolution()){
// animation.setBackgroundResource(R.drawable.animation_tablet);
// animation.setOnClickListener(new OnClickListener() {
//
// public void onClick(View v) {
// // TODO Auto-generated method stub
// //mDialog = new Dialog(NewSplashScreen.this,android.R.style.Theme_Translucent_NoTitleBar_Fullscreen);
//
// mDialog = new Dialog(SplashScreen.this);
// mDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
// mDialog.setContentView(R.layout.xslashscreenplaydialog);
// mDialog.getWindow().setBackgroundDrawable(new ColorDrawable(0));
//
// Button btnSwip = (Button)mDialog.findViewById(R.id.btnSwip);
// btnSwip.setBackgroundResource(R.drawable.swap_tablet);
// btnSwip.setOnClickListener(new OnClickListener() {
//
// public void onClick(View v) {
// mDialog.dismiss();
// NextActivity();
// }
// });
// mDialog.setCancelable(false);
// mDialog.setCanceledOnTouchOutside(false);
// mDialog.show();
// }
// });
// }
// else{
animation.setBackgroundResource(R.drawable.animation);
animation.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
//mDialog = new Dialog(NewSplashScreen.this,android.R.style.Theme_Translucent_NoTitleBar_Fullscreen);
mDialog = new Dialog(SplashScreen.this);
mDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
mDialog.setContentView(R.layout.xslashscreenplaydialog);
mDialog.getWindow().setBackgroundDrawable(new ColorDrawable(0));
Button btnSwip = (Button)mDialog.findViewById(R.id.btnSwip);
btnSwip.setBackgroundResource(R.drawable.swap);
btnSwip.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
mDialog.dismiss();
NextActivity();
}
});
mDialog.setCancelable(false);
mDialog.setCanceledOnTouchOutside(false);
mDialog.show();
}
});
// }
}
@Override
/**
* This method is called whenever the Activity becomes visible or invisible to the user.
* During this method call its possible to start the animation.
*/
public void onWindowFocusChanged (boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
AnimationDrawable frameAnimation =
(AnimationDrawable) animation.getBackground();
if(hasFocus) {
frameAnimation.start();
} else {
frameAnimation.stop();
}
}
private void NextActivity(){
Intent mIntent=new Intent(this,MainActivity.class);
startActivity(mIntent);
finish();
// overridePendingTransition(R.anim.fade_in,R.anim.fade_out);
}
// This Is run when key down
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
return true;
}
return super.onKeyDown(keyCode, event);
}
}
7)xatoz.xml
===========
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@android:color/white"
android:orientation="vertical" >
<RelativeLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<FrameLayout
android:id="@+id/frmlayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
</FrameLayout>
</RelativeLayout>
<RelativeLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:gravity="top"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:id="@+id/txtspelling"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dip"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
android:textSize="24dip"
android:textStyle="bold"
android:textColor="@android:color/white"
android:layout_weight="1">
</TextView>
<!-- <ImageView -->
<!-- android:id="@+id/imgalphabet" -->
<!-- android:layout_width="100dip" -->
<!-- android:layout_height="100dip"> -->
<!-- </ImageView> -->
</LinearLayout>
</RelativeLayout>
</RelativeLayout>
</LinearLayout>
8)xslashscreenplaydialog.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:id="@+id/lytSplash"
android:background="@android:color/transparent"
android:layout_width="fill_parent"
android:layout_gravity="center"
android:gravity="center"
android:layout_height="fill_parent">
<Button
android:id="@+id/btnSwip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
</Button>
<!-- <TextView -->
<!-- android:layout_width="fill_parent" -->
<!-- android:layout_height="fill_parent" -->
<!-- android:layout_marginLeft= "15dip" -->
<!-- android:layout_marginRight="15dip" -->
<!-- android:textSize="16dip" -->
<!-- android:textStyle="bold" -->
<!-- android:textColor="#FFFFFF" -->
<!-- android:text="@string/splashscreen_text"/> -->
</LinearLayout>
9)xsplashscreen.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/lytSplash"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:background="@drawable/imgsplash_screen">
<ImageView
android:id="@+id/imageAnimation"
android:layout_marginTop="5dip"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_gravity="right"
android:adjustViewBounds="true" />
</LinearLayout>
9)in raw folder add mp3 files for a to z
=========================
10_manifest.xml
============
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.drc.abcdfunlite"
android:installLocation="auto"
android:versionCode="4"
android:versionName="1.3" >
<uses-sdk android:minSdkVersion="7" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" android:vmSafeMode="true">
<activity android:label="@string/app_name"
android:name="SplashScreen"
android:screenOrientation="portrait"
android:configChanges="orientation|keyboardHidden"
android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:label="@string/app_name"
android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"
android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</application>
</manifest>
11) in anim folder add 3 files
1)fadein.xml
===========
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:fromAlpha="0.0"
android:toAlpha="1.0"
android:duration="1200"
android:fillAfter="true"
android:fillEnabled="true"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
/>
2)fadout.xml
========
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:fromAlpha="0.0"
android:toAlpha="1.0"
android:duration="1200"
android:fillAfter="true"
android:fillEnabled="true"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
/>
3)scalingbig.xml
=========
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<scale
android:duration="800"
android:fromXScale="0.0"
android:fromYScale="0.0"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1.0"
android:toYScale="1.0"
android:startOffset="0"
android:fillAfter="true"
android:fillBefore="false"/>
</set>
12)in drawable add file name
1)animation.xml
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">
<item android:drawable="@drawable/img1" android:duration="50" />
<item android:drawable="@drawable/img2" android:duration="50" />
<item android:drawable="@drawable/img3" android:duration="50" />
<item android:drawable="@drawable/img4" android:duration="50" />
<item android:drawable="@drawable/img5" android:duration="50" />
<item android:drawable="@drawable/img6" android:duration="50" />
<item android:drawable="@drawable/img7" android:duration="50" />
<item android:drawable="@drawable/img8" android:duration="50" />
<item android:drawable="@drawable/img9" android:duration="50" />
<item android:drawable="@drawable/img10" android:duration="50" />
<item android:drawable="@drawable/img12" android:duration="50" />
<item android:drawable="@drawable/img13" android:duration="50" />
<item android:drawable="@drawable/img14" android:duration="50" />
<item android:drawable="@drawable/img15" android:duration="50" />
<item android:drawable="@drawable/img16" android:duration="50" />
<item android:drawable="@drawable/img17" android:duration="50" />
<item android:drawable="@drawable/img18" android:duration="50" />
<item android:drawable="@drawable/img19" android:duration="50" />
<item android:drawable="@drawable/img20" android:duration="50" />
<item android:drawable="@drawable/img21" android:duration="50" />
<item android:drawable="@drawable/img20" android:duration="50" />
<item android:drawable="@drawable/img19" android:duration="50" />
<item android:drawable="@drawable/img18" android:duration="50" />
<item android:drawable="@drawable/img17" android:duration="50" />
<item android:drawable="@drawable/img16" android:duration="50" />
<item android:drawable="@drawable/img15" android:duration="50" />
<item android:drawable="@drawable/img14" android:duration="50" />
<item android:drawable="@drawable/img13" android:duration="50" />
<item android:drawable="@drawable/img12" android:duration="50" />
<item android:drawable="@drawable/img11" android:duration="50" />
<item android:drawable="@drawable/img10" android:duration="50" />
<item android:drawable="@drawable/img9" android:duration="50" />
<item android:drawable="@drawable/img8" android:duration="50" />
<item android:drawable="@drawable/img7" android:duration="50" />
<item android:drawable="@drawable/img6" android:duration="50" />
<item android:drawable="@drawable/img5" android:duration="50" />
<item android:drawable="@drawable/img4" android:duration="50" />
<item android:drawable="@drawable/img3" android:duration="50" />
<item android:drawable="@drawable/img2" android:duration="50" />
</animation-list>
No comments:
Post a Comment