Tuesday 2 April 2013

PageCurl Example

Create java file PageCurlView.java
======================
package com.drc.abcdfunlite;

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;
        }
}

Create another java file MainActivity.java
===========================
package com.drc.abcdfunlite;

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.mainactivity);
        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);
            }
       }
}

Create xml file named mainactivity.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>

No comments:

Post a Comment