Advertisement
Guest User

Untitled

a guest
Dec 9th, 2012
67
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 32.84 KB | None | 0 0
  1. package com.abs.stickyanimation;
  2.  
  3. import java.lang.ref.WeakReference;
  4. import java.util.ArrayList;
  5.  
  6. import android.content.Context;
  7. import android.content.res.TypedArray;
  8. import android.graphics.Bitmap;
  9. import android.graphics.Canvas;
  10. import android.graphics.Color;
  11. import android.graphics.Paint;
  12. import android.graphics.Paint.Style;
  13. import android.graphics.Path;
  14. import android.graphics.Rect;
  15. import android.os.Handler;
  16. import android.os.Message;
  17. import android.text.TextPaint;
  18. import android.util.AttributeSet;
  19. import android.util.Log;
  20. import android.view.MotionEvent;
  21. import android.view.View;
  22. import android.widget.LinearLayout;
  23.  
  24. import com.huskerit.quicksync.R;
  25.  
  26. /**
  27. *
  28. * @author Moritz 'Moss' Wundke (b.thax.dcg@gmail.com)
  29. *
  30. */
  31. public class PageCurlView extends View
  32. {
  33.  
  34. /** Our Log tag */
  35. private final static String TAG = "PageCurlView";
  36.  
  37. // Debug text paint stuff
  38. private Paint mTextPaint;
  39. private TextPaint mTextPaintShadow;
  40.  
  41. /** Px / Draw call */
  42. private int mCurlSpeed;
  43.  
  44. /** Fixed update time used to create a smooth curl animation */
  45. private int mUpdateRate;
  46.  
  47. /** The initial offset for x and y axis movements */
  48. private int mInitialEdgeOffset;
  49.  
  50. /** The mode we will use */
  51. private int mCurlMode;
  52.  
  53. /** Simple curl mode. Curl target will move only in one axis. */
  54. public static final int CURLMODE_SIMPLE = 0;
  55.  
  56. /** Dynamic curl mode. Curl target will move on both X and Y axis. */
  57. public static final int CURLMODE_DYNAMIC = 1;
  58.  
  59. /** Enable/Disable debug mode */
  60. private boolean bEnableDebugMode = false;
  61.  
  62. /** The context which owns us */
  63. private WeakReference<Context> mContext;
  64.  
  65. /** Handler used to auto flip time based */
  66. private FlipAnimationHandler mAnimationHandler;
  67.  
  68. /** Maximum radius a page can be flipped, by default it's the width of the view */
  69. private float mFlipRadius;
  70.  
  71. /** Point used to move */
  72. private Vector2D mMovement;
  73.  
  74. /** The finger position */
  75. private Vector2D mFinger;
  76.  
  77. /** Movement point form the last frame */
  78. private Vector2D mOldMovement;
  79.  
  80. /** Page curl edge */
  81. private Paint mCurlEdgePaint;
  82.  
  83. /** Our points used to define the current clipping paths in our draw call */
  84. private Vector2D mA, mB, mC, mD, mE, mF, mOldF, mOrigin;
  85.  
  86. /** Left and top offset to be applied when drawing */
  87. private int mCurrentLeft, mCurrentTop;
  88.  
  89. /** If false no draw call has been done */
  90. private boolean bViewDrawn;
  91.  
  92. /** Defines the flip direction that is currently considered */
  93. private boolean bFlipRight;
  94.  
  95. /** If TRUE we are currently auto-flipping */
  96. private boolean bFlipping;
  97.  
  98. /** TRUE if the user moves the pages */
  99. private boolean bUserMoves;
  100.  
  101. /** Used to control touch input blocking */
  102. private boolean bBlockTouchInput = false;
  103.  
  104. /** Enable input after the next draw event */
  105. private boolean bEnableInputAfterDraw = false;
  106.  
  107. /** LAGACY The current foreground */
  108. private Bitmap mForeground;
  109.  
  110. /** LAGACY The current background */
  111. private Bitmap mBackground;
  112.  
  113. /** LAGACY List of pages, this is just temporal */
  114. //public static ArrayList<View> mPages;
  115. public static ArrayList<View> mPages;
  116.  
  117. /** LAGACY Current selected page */
  118. private int mIndex = 0;
  119.  
  120. /**
  121. * Inner class used to represent a 2D point.
  122. */
  123. private class Vector2D
  124. {
  125. public float x,y;
  126. public Vector2D(float x, float y)
  127. {
  128. this.x = x;
  129. this.y = y;
  130. }
  131.  
  132. @Override
  133. public String toString() {
  134. // TODO Auto-generated method stub
  135. return "("+this.x+","+this.y+")";
  136. }
  137.  
  138. public float length() {
  139. return (float) Math.sqrt(x * x + y * y);
  140. }
  141.  
  142. public float lengthSquared() {
  143. return (x * x) + (y * y);
  144. }
  145.  
  146. public boolean equals(Object o) {
  147. if (o instanceof Vector2D) {
  148. Vector2D p = (Vector2D) o;
  149. return p.x == x && p.y == y;
  150. }
  151. return false;
  152. }
  153.  
  154. public Vector2D reverse() {
  155. return new Vector2D(-x,-y);
  156. }
  157.  
  158. public Vector2D sum(Vector2D b) {
  159. return new Vector2D(x+b.x,y+b.y);
  160. }
  161.  
  162. public Vector2D sub(Vector2D b) {
  163. return new Vector2D(x-b.x,y-b.y);
  164. }
  165.  
  166. public float dot(Vector2D vec) {
  167. return (x * vec.x) + (y * vec.y);
  168. }
  169.  
  170. public float cross(Vector2D a, Vector2D b) {
  171. return a.cross(b);
  172. }
  173.  
  174. public float cross(Vector2D vec) {
  175. return x * vec.y - y * vec.x;
  176. }
  177.  
  178. public float distanceSquared(Vector2D other) {
  179. float dx = other.x - x;
  180. float dy = other.y - y;
  181.  
  182. return (dx * dx) + (dy * dy);
  183. }
  184.  
  185. public float distance(Vector2D other) {
  186. return (float) Math.sqrt(distanceSquared(other));
  187. }
  188.  
  189. public float dotProduct(Vector2D other) {
  190. return other.x * x + other.y * y;
  191. }
  192.  
  193. public Vector2D normalize() {
  194. float magnitude = (float) Math.sqrt(dotProduct(this));
  195. return new Vector2D(x / magnitude, y / magnitude);
  196. }
  197.  
  198. public Vector2D mult(float scalar) {
  199. return new Vector2D(x*scalar,y*scalar);
  200. }
  201. }
  202.  
  203. /**
  204. * Inner class used to make a fixed timed animation of the curl effect.
  205. */
  206. class FlipAnimationHandler extends Handler {
  207. @Override
  208. public void handleMessage(Message msg) {
  209. PageCurlView.this.FlipAnimationStep();
  210. }
  211.  
  212. public void sleep(long millis) {
  213. this.removeMessages(0);
  214. sendMessageDelayed(obtainMessage(0), millis);
  215. }
  216. }
  217.  
  218. /**
  219. * Base
  220. * @param context
  221. */
  222. public PageCurlView(Context context,View view/*Bitmap bitmap*/) {
  223. super(context);
  224. init(context,view);
  225. ResetClipEdge();
  226. }
  227.  
  228. /**
  229. * Construct the object from an XML file. Valid Attributes:
  230. *
  231. * @see android.view.View#View(android.content.Context, android.util.AttributeSet)
  232. */
  233. public PageCurlView(Context context, AttributeSet attrs,LinearLayout linearLayout/*Bitmap bitmap*/) {
  234. super(context, attrs);
  235. init(context,linearLayout);
  236.  
  237. // Get the data from the XML AttributeSet
  238. {
  239. TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PageCurlView);
  240.  
  241. // Get data
  242. bEnableDebugMode = a.getBoolean(R.styleable.PageCurlView_enableDebugMode, bEnableDebugMode);
  243. mCurlSpeed = a.getInt(R.styleable.PageCurlView_curlSpeed, mCurlSpeed);
  244. mUpdateRate = a.getInt(R.styleable.PageCurlView_updateRate, mUpdateRate);
  245. mInitialEdgeOffset = a.getInt(R.styleable.PageCurlView_initialEdgeOffset, mInitialEdgeOffset);
  246. mCurlMode = a.getInt(R.styleable.PageCurlView_curlMode, mCurlMode);
  247.  
  248. Log.i(TAG, "mCurlSpeed: " + mCurlSpeed);
  249. Log.i(TAG, "mUpdateRate: " + mUpdateRate);
  250. Log.i(TAG, "mInitialEdgeOffset: " + mInitialEdgeOffset);
  251. Log.i(TAG, "mCurlMode: " + mCurlMode);
  252.  
  253. // recycle object (so it can be used by others)
  254. a.recycle();
  255. }
  256.  
  257. ResetClipEdge();
  258. }
  259.  
  260. /**
  261. * Initialize the view
  262. */
  263. private final void init(Context context,View view/*Bitmap bitmap*/) {
  264. // Foreground text paint
  265. mTextPaint = new Paint();
  266. mTextPaint.setAntiAlias(true);
  267. mTextPaint.setTextSize(16);
  268. mTextPaint.setColor(0xFF000000);
  269.  
  270. // The shadow
  271. mTextPaintShadow = new TextPaint();
  272. mTextPaintShadow.setAntiAlias(true);
  273. mTextPaintShadow.setTextSize(16);
  274. mTextPaintShadow.setColor(0x00000000);
  275.  
  276. // Cache the context
  277. mContext = new WeakReference<Context>(context);
  278.  
  279. // Base padding
  280. setPadding(3, 3, 3, 3);
  281.  
  282. // The focus flags are needed
  283. setFocusable(true);
  284. setFocusableInTouchMode(true);
  285.  
  286. mMovement = new Vector2D(0,0);
  287. mFinger = new Vector2D(0,0);
  288. mOldMovement = new Vector2D(0,0);
  289.  
  290. // Create our curl animation handler
  291. mAnimationHandler = new FlipAnimationHandler();
  292.  
  293. // Create our edge paint
  294. mCurlEdgePaint = new Paint();
  295. mCurlEdgePaint.setColor(Color.WHITE);
  296. mCurlEdgePaint.setAntiAlias(true);
  297. mCurlEdgePaint.setStyle(Paint.Style.FILL);
  298. mCurlEdgePaint.setShadowLayer(10, -5, 5, 0x99000000);
  299.  
  300. // Set the default props, those come from an XML :D
  301. mCurlSpeed = 30;
  302. mUpdateRate = 33;
  303. mInitialEdgeOffset = 20;
  304. mCurlMode = 1;
  305.  
  306. // LEGACY PAGE HANDLING!
  307. addView(context,view);
  308.  
  309. // Create pages
  310. if(mPages.size() != 0)
  311. {
  312. mPages = new ArrayList<View>();
  313. }
  314. //mPages.add(BitmapFactory.decodeResource(getResources(), R.drawable.page2));
  315.  
  316. // Create some sample images
  317. //mForeground = mPages.get(0);
  318. //mBackground = mPages.get(1);
  319. }
  320.  
  321. public static void addView(Context context,View view/*Bitmap bitmap*/)
  322. {
  323. mPages.add(view);
  324. }
  325.  
  326. /**
  327. * Reset points to it's initial clip edge state
  328. */
  329. public void ResetClipEdge()
  330. {
  331. // Set our base movement
  332. mMovement.x = mInitialEdgeOffset;
  333. mMovement.y = mInitialEdgeOffset;
  334. mOldMovement.x = 0;
  335. mOldMovement.y = 0;
  336.  
  337. // Now set the points
  338. // TODO: OK, those points MUST come from our measures and
  339. // the actual bounds of the view!
  340. mA = new Vector2D(mInitialEdgeOffset, 0);
  341. mB = new Vector2D(this.getWidth(), this.getHeight());
  342. mC = new Vector2D(this.getWidth(), 0);
  343. mD = new Vector2D(0, 0);
  344. mE = new Vector2D(0, 0);
  345. mF = new Vector2D(0, 0);
  346. mOldF = new Vector2D(0, 0);
  347.  
  348. // The movement origin point
  349. mOrigin = new Vector2D(this.getWidth(), 0);
  350. }
  351.  
  352. /**
  353. * Return the context which created use. Can return null if the
  354. * context has been erased.
  355. */
  356. private Context GetContext() {
  357. return mContext.get();
  358. }
  359.  
  360. /**
  361. * See if the current curl mode is dynamic
  362. * @return TRUE if the mode is CURLMODE_DYNAMIC, FALSE otherwise
  363. */
  364. public boolean IsCurlModeDynamic()
  365. {
  366. return mCurlMode == CURLMODE_DYNAMIC;
  367. }
  368.  
  369. /**
  370. * Set the curl speed.
  371. * @param curlSpeed - New speed in px/frame
  372. * @throws IllegalArgumentException if curlspeed < 1
  373. */
  374. public void SetCurlSpeed(int curlSpeed)
  375. {
  376. if ( curlSpeed < 1 )
  377. throw new IllegalArgumentException("curlSpeed must be greated than 0");
  378. mCurlSpeed = curlSpeed;
  379. }
  380.  
  381. /**
  382. * Get the current curl speed
  383. * @return int - Curl speed in px/frame
  384. */
  385. public int GetCurlSpeed()
  386. {
  387. return mCurlSpeed;
  388. }
  389.  
  390. /**
  391. * Set the update rate for the curl animation
  392. * @param updateRate - Fixed animation update rate in fps
  393. * @throws IllegalArgumentException if updateRate < 1
  394. */
  395. public void SetUpdateRate(int updateRate)
  396. {
  397. if ( updateRate < 1 )
  398. throw new IllegalArgumentException("updateRate must be greated than 0");
  399. mUpdateRate = updateRate;
  400. }
  401.  
  402. /**
  403. * Get the current animation update rate
  404. * @return int - Fixed animation update rate in fps
  405. */
  406. public int GetUpdateRate()
  407. {
  408. return mUpdateRate;
  409. }
  410.  
  411. /**
  412. * Set the initial pixel offset for the curl edge
  413. * @param initialEdgeOffset - px offset for curl edge
  414. * @throws IllegalArgumentException if initialEdgeOffset < 0
  415. */
  416. public void SetInitialEdgeOffset(int initialEdgeOffset)
  417. {
  418. if ( initialEdgeOffset < 0 )
  419. throw new IllegalArgumentException("initialEdgeOffset can not negative");
  420. mInitialEdgeOffset = initialEdgeOffset;
  421. }
  422.  
  423. /**
  424. * Get the initial pixel offset for the curl edge
  425. * @return int - px
  426. */
  427. public int GetInitialEdgeOffset()
  428. {
  429. return mInitialEdgeOffset;
  430. }
  431.  
  432. /**
  433. * Set the curl mode.
  434. * <p>Can be one of the following values:</p>
  435. * <table>
  436. * <colgroup align="left" />
  437. * <colgroup align="left" />
  438. * <tr><th>Value</th><th>Description</th></tr>
  439. * <tr><td><code>{@link #CURLMODE_SIMPLE com.dcg.pagecurl:CURLMODE_SIMPLE}</code></td><td>Curl target will move only in one axis.</td></tr>
  440. * <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>
  441. * </table>
  442. * @see #CURLMODE_SIMPLE
  443. * @see #CURLMODE_DYNAMIC
  444. * @param curlMode
  445. * @throws IllegalArgumentException if curlMode is invalid
  446. */
  447. public void SetCurlMode(int curlMode)
  448. {
  449. if ( curlMode != CURLMODE_SIMPLE &&
  450. curlMode != CURLMODE_DYNAMIC )
  451. throw new IllegalArgumentException("Invalid curlMode");
  452. mCurlMode = curlMode;
  453. }
  454.  
  455. /**
  456. * Return an integer that represents the current curl mode.
  457. * <p>Can be one of the following values:</p>
  458. * <table>
  459. * <colgroup align="left" />
  460. * <colgroup align="left" />
  461. * <tr><th>Value</th><th>Description</th></tr>
  462. * <tr><td><code>{@link #CURLMODE_SIMPLE com.dcg.pagecurl:CURLMODE_SIMPLE}</code></td><td>Curl target will move only in one axis.</td></tr>
  463. * <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>
  464. * </table>
  465. * @see #CURLMODE_SIMPLE
  466. * @see #CURLMODE_DYNAMIC
  467. * @return int - current curl mode
  468. */
  469. public int GetCurlMode()
  470. {
  471. return mCurlMode;
  472. }
  473.  
  474. /**
  475. * Enable debug mode. This will draw a lot of data in the view so you can track what is happening
  476. * @param bFlag - boolean flag
  477. */
  478. public void SetEnableDebugMode(boolean bFlag)
  479. {
  480. bEnableDebugMode = bFlag;
  481. }
  482.  
  483. /**
  484. * Check if we are currently in debug mode.
  485. * @return boolean - If TRUE debug mode is on, FALSE otherwise.
  486. */
  487. public boolean IsDebugModeEnabled()
  488. {
  489. return bEnableDebugMode;
  490. }
  491.  
  492. /**
  493. * @see android.view.View#measure(int, int)
  494. */
  495. @Override
  496. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  497. int finalWidth, finalHeight;
  498. finalWidth = measureWidth(widthMeasureSpec);
  499. finalHeight = measureHeight(heightMeasureSpec);
  500. setMeasuredDimension(finalWidth, finalHeight);
  501. }
  502.  
  503. /**
  504. * Determines the width of this view
  505. * @param measureSpec A measureSpec packed into an int
  506. * @return The width of the view, honoring constraints from measureSpec
  507. */
  508. private int measureWidth(int measureSpec) {
  509. int result = 0;
  510. int specMode = MeasureSpec.getMode(measureSpec);
  511. int specSize = MeasureSpec.getSize(measureSpec);
  512.  
  513. if (specMode == MeasureSpec.EXACTLY) {
  514. // We were told how big to be
  515. result = specSize;
  516. } else {
  517. // Measure the text
  518. result = specSize;
  519. }
  520.  
  521. return result;
  522. }
  523.  
  524. /**
  525. * Determines the height of this view
  526. * @param measureSpec A measureSpec packed into an int
  527. * @return The height of the view, honoring constraints from measureSpec
  528. */
  529. private int measureHeight(int measureSpec) {
  530. int result = 0;
  531. int specMode = MeasureSpec.getMode(measureSpec);
  532. int specSize = MeasureSpec.getSize(measureSpec);
  533.  
  534. if (specMode == MeasureSpec.EXACTLY) {
  535. // We were told how big to be
  536. result = specSize;
  537. } else {
  538. // Measure the text (beware: ascent is a negative number)
  539. result = specSize;
  540. }
  541. return result;
  542. }
  543.  
  544. /**
  545. * Render the text
  546. *
  547. * @see android.view.View#onDraw(android.graphics.Canvas)
  548. */
  549. //@Override
  550. //protected void onDraw(Canvas canvas) {
  551. // super.onDraw(canvas);
  552. // canvas.drawText(mText, getPaddingLeft(), getPaddingTop() - mAscent, mTextPaint);
  553. //}
  554.  
  555. //---------------------------------------------------------------
  556. // Curling. This handles touch events, the actual curling
  557. // implementations and so on.
  558. //---------------------------------------------------------------
  559.  
  560. @Override
  561. public boolean onTouchEvent(MotionEvent event) {
  562. if (!bBlockTouchInput) {
  563.  
  564. // Get our finger position
  565. mFinger.x = event.getX();
  566. mFinger.y = event.getY();
  567. int width = getWidth();
  568.  
  569. // Depending on the action do what we need to
  570. switch (event.getAction()) {
  571. case MotionEvent.ACTION_DOWN:
  572. mOldMovement.x = mFinger.x;
  573. mOldMovement.y = mFinger.y;
  574.  
  575. // If we moved over the half of the display flip to next
  576. if (mOldMovement.x > (width >> 1)) {
  577. mMovement.x = mInitialEdgeOffset;
  578. mMovement.y = mInitialEdgeOffset;
  579.  
  580. // Set the right movement flag
  581. bFlipRight = true;
  582. } else {
  583. // Set the left movement flag
  584. bFlipRight = false;
  585.  
  586. // go to next previous page
  587. previousView();
  588.  
  589. // Set new movement
  590. mMovement.x = IsCurlModeDynamic()?width<<1:width;
  591. mMovement.y = mInitialEdgeOffset;
  592. }
  593.  
  594. break;
  595. case MotionEvent.ACTION_UP:
  596. bUserMoves=false;
  597. bFlipping=true;
  598. FlipAnimationStep();
  599. break;
  600. case MotionEvent.ACTION_MOVE:
  601. bUserMoves=true;
  602.  
  603. // Get movement
  604. mMovement.x -= mFinger.x - mOldMovement.x;
  605. mMovement.y -= mFinger.y - mOldMovement.y;
  606. mMovement = CapMovement(mMovement, true);
  607.  
  608. // Make sure the y value get's locked at a nice level
  609. if ( mMovement.y <= 1 )
  610. mMovement.y = 1;
  611.  
  612. // Get movement direction
  613. if (mFinger.x < mOldMovement.x ) {
  614. bFlipRight = true;
  615. } else {
  616. bFlipRight = false;
  617. }
  618.  
  619. // Save old movement values
  620. mOldMovement.x = mFinger.x;
  621. mOldMovement.y = mFinger.y;
  622.  
  623. // Force a new draw call
  624. DoPageCurl();
  625. this.invalidate();
  626. break;
  627. }
  628.  
  629. }
  630.  
  631. // TODO: Only consume event if we need to.
  632. return true;
  633. }
  634.  
  635. /**
  636. * Make sure we never move too much, and make sure that if we
  637. * move too much to add a displacement so that the movement will
  638. * be still in our radius.
  639. * @param radius - radius form the flip origin
  640. * @param bMaintainMoveDir - Cap movement but do not change the
  641. * current movement direction
  642. * @return Corrected point
  643. */
  644. private Vector2D CapMovement(Vector2D point, boolean bMaintainMoveDir)
  645. {
  646. // Make sure we never ever move too much
  647. if (point.distance(mOrigin) > mFlipRadius)
  648. {
  649. if ( bMaintainMoveDir )
  650. {
  651. // Maintain the direction
  652. point = mOrigin.sum(point.sub(mOrigin).normalize().mult(mFlipRadius));
  653. }
  654. else
  655. {
  656. // Change direction
  657. if ( point.x > (mOrigin.x+mFlipRadius))
  658. point.x = (mOrigin.x+mFlipRadius);
  659. else if ( point.x < (mOrigin.x-mFlipRadius) )
  660. point.x = (mOrigin.x-mFlipRadius);
  661. point.y = (float) (Math.sin(Math.acos(Math.abs(point.x-mOrigin.x)/mFlipRadius))*mFlipRadius);
  662. }
  663. }
  664. return point;
  665. }
  666.  
  667. /**
  668. * Execute a step of the flip animation
  669. */
  670. public void FlipAnimationStep() {
  671. if ( !bFlipping )
  672. return;
  673.  
  674. int width = getWidth();
  675.  
  676. // No input when flipping
  677. bBlockTouchInput = true;
  678.  
  679. // Handle speed
  680. float curlSpeed = mCurlSpeed;
  681. if ( !bFlipRight )
  682. curlSpeed *= -1;
  683.  
  684. // Move us
  685. mMovement.x += curlSpeed;
  686. mMovement = CapMovement(mMovement, false);
  687.  
  688. // Create values
  689. DoPageCurl();
  690.  
  691. // Check for endings :D
  692. if (mA.x < 1 || mA.x > width - 1) {
  693. bFlipping = false;
  694. if (bFlipRight) {
  695. //SwapViews();
  696. nextView();
  697. }
  698. ResetClipEdge();
  699.  
  700. // Create values
  701. DoPageCurl();
  702.  
  703. // Enable touch input after the next draw event
  704. bEnableInputAfterDraw = true;
  705. }
  706. else
  707. {
  708. mAnimationHandler.sleep(mUpdateRate);
  709. }
  710.  
  711. // Force a new draw call
  712. this.invalidate();
  713. }
  714.  
  715. /**
  716. * Do the page curl depending on the methods we are using
  717. */
  718. private void DoPageCurl()
  719. {
  720. if(bFlipping){
  721. if ( IsCurlModeDynamic() )
  722. doDynamicCurl();
  723. else
  724. doSimpleCurl();
  725.  
  726. } else {
  727. if ( IsCurlModeDynamic() )
  728. doDynamicCurl();
  729. else
  730. doSimpleCurl();
  731. }
  732. }
  733.  
  734. /**
  735. * Do a simple page curl effect
  736. */
  737. private void doSimpleCurl() {
  738. int width = getWidth();
  739. int height = getHeight();
  740.  
  741. // Calculate point A
  742. mA.x = width - mMovement.x;
  743. mA.y = height;
  744.  
  745. // Calculate point D
  746. mD.x = 0;
  747. mD.y = 0;
  748. if (mA.x > width / 2) {
  749. mD.x = width;
  750. mD.y = height - (width - mA.x) * height / mA.x;
  751. } else {
  752. mD.x = 2 * mA.x;
  753. mD.y = 0;
  754. }
  755.  
  756. // Now calculate E and F taking into account that the line
  757. // AD is perpendicular to FB and EC. B and C are fixed points.
  758. double angle = Math.atan((height - mD.y) / (mD.x + mMovement.x - width));
  759. double _cos = Math.cos(2 * angle);
  760. double _sin = Math.sin(2 * angle);
  761.  
  762. // And get F
  763. mF.x = (float) (width - mMovement.x + _cos * mMovement.x);
  764. mF.y = (float) (height - _sin * mMovement.x);
  765.  
  766. // If the x position of A is above half of the page we are still not
  767. // folding the upper-right edge and so E and D are equal.
  768. if (mA.x > width / 2) {
  769. mE.x = mD.x;
  770. mE.y = mD.y;
  771. }
  772. else
  773. {
  774. // So get E
  775. mE.x = (float) (mD.x + _cos * (width - mD.x));
  776. mE.y = (float) -(_sin * (width - mD.x));
  777. }
  778. }
  779.  
  780. /**
  781. * Calculate the dynamic effect, that one that follows the users finger
  782. */
  783. private void doDynamicCurl() {
  784. int width = getWidth();
  785. int height = getHeight();
  786.  
  787. // F will follow the finger, we add a small displacement
  788. // So that we can see the edge
  789. mF.x = width - mMovement.x+0.1f;
  790. mF.y = height - mMovement.y+0.1f;
  791.  
  792. // Set min points
  793. if(mA.x==0) {
  794. mF.x= Math.min(mF.x, mOldF.x);
  795. mF.y= Math.max(mF.y, mOldF.y);
  796. }
  797.  
  798. // Get diffs
  799. float deltaX = width-mF.x;
  800. float deltaY = height-mF.y;
  801.  
  802. float BH = (float) (Math.sqrt(deltaX * deltaX + deltaY * deltaY) / 2);
  803. double tangAlpha = deltaY / deltaX;
  804. double alpha = Math.atan(deltaY / deltaX);
  805. double _cos = Math.cos(alpha);
  806. double _sin = Math.sin(alpha);
  807.  
  808. mA.x = (float) (width - (BH / _cos));
  809. mA.y = height;
  810.  
  811. mD.y = (float) (height - (BH / _sin));
  812. mD.x = width;
  813.  
  814. mA.x = Math.max(0,mA.x);
  815. if(mA.x==0) {
  816. mOldF.x = mF.x;
  817. mOldF.y = mF.y;
  818. }
  819.  
  820. // Get W
  821. mE.x = mD.x;
  822. mE.y = mD.y;
  823.  
  824. // Correct
  825. if (mD.y < 0) {
  826. mD.x = width + (float) (tangAlpha * mD.y);
  827. mE.y = 0;
  828. mE.x = width + (float) (Math.tan(2 * alpha) * mD.y);
  829. }
  830. }
  831.  
  832. /**
  833. * Swap between the fore and back-ground.
  834. */
  835. @Deprecated
  836. private void SwapViews() {
  837. Bitmap temp = mForeground;
  838. mForeground = mBackground;
  839. mBackground = temp;
  840. }
  841.  
  842. /**
  843. * Swap to next view
  844. */
  845. private void nextView() {
  846. int foreIndex = mIndex + 1;
  847. if(foreIndex >= mPages.size()) {
  848. foreIndex = 0;
  849. }
  850. int backIndex = foreIndex + 1;
  851. if(backIndex >= mPages.size()) {
  852. backIndex = 0;
  853. }
  854. mIndex = foreIndex;
  855. setViews(foreIndex, backIndex);
  856. }
  857.  
  858. /**
  859. * Swap to previous view
  860. */
  861. private void previousView() {
  862. int backIndex = mIndex;
  863. int foreIndex = backIndex - 1;
  864. if(foreIndex < 0) {
  865. foreIndex = mPages.size()-1;
  866. }
  867. mIndex = foreIndex;
  868. setViews(foreIndex, backIndex);
  869. }
  870.  
  871. /**
  872. * Set current fore and background
  873. * @param foreground - Foreground view index
  874. * @param background - Background view index
  875. */
  876. private void setViews(int foreground, int background)
  877. {
  878. //mForeground = mPages.get(v);
  879. //mBackground = mPages.get(background);
  880. }
  881.  
  882. //---------------------------------------------------------------
  883. // Drawing methods
  884. //---------------------------------------------------------------
  885.  
  886. @Override
  887. protected void onDraw(Canvas canvas) {
  888. // Always refresh offsets
  889. mCurrentLeft = getLeft();
  890. mCurrentTop = getTop();
  891.  
  892. // Translate the whole canvas
  893. //canvas.translate(mCurrentLeft, mCurrentTop);
  894.  
  895. // We need to initialize all size data when we first draw the view
  896. if ( !bViewDrawn ) {
  897. bViewDrawn = true;
  898. onFirstDrawEvent(canvas);
  899. }
  900.  
  901. canvas.drawColor(Color.WHITE);
  902.  
  903. // Curl pages
  904. //DoPageCurl();
  905.  
  906. // TODO: This just scales the views to the current
  907. // width and height. We should add some logic for:
  908. // 1) Maintain aspect ratio
  909. // 2) Uniform scale
  910. // 3) ...
  911. Rect rect = new Rect();
  912. rect.left = 0;
  913. rect.top = 0;
  914. rect.bottom = getHeight();
  915. rect.right = getWidth();
  916.  
  917. // First Page render
  918. Paint paint = new Paint();
  919.  
  920. // Draw our elements
  921. drawForeground(canvas, rect, paint);
  922. drawBackground(canvas, rect, paint);
  923. drawCurlEdge(canvas);
  924.  
  925. // Draw any debug info once we are done
  926. if ( bEnableDebugMode )
  927. drawDebug(canvas);
  928.  
  929. // Check if we can re-enable input
  930. if ( bEnableInputAfterDraw )
  931. {
  932. bBlockTouchInput = false;
  933. bEnableInputAfterDraw = false;
  934. }
  935.  
  936. // Restore canvas
  937. //canvas.restore();
  938. }
  939.  
  940. /**
  941. * Called on the first draw event of the view
  942. * @param canvas
  943. */
  944. protected void onFirstDrawEvent(Canvas canvas) {
  945.  
  946. mFlipRadius = getWidth();
  947.  
  948. ResetClipEdge();
  949. DoPageCurl();
  950. }
  951.  
  952. /**
  953. * Draw the foreground
  954. * @param canvas
  955. * @param rect
  956. * @param paint
  957. */
  958. private void drawForeground( Canvas canvas, Rect rect, Paint paint ) {
  959. canvas.drawBitmap(mForeground, null, rect, paint);
  960.  
  961. // Draw the page number (first page is 1 in real life :D
  962. // there is no page number 0 hehe)
  963. drawPageNum(canvas, mIndex);
  964. }
  965.  
  966. /**
  967. * Create a Path used as a mask to draw the background page
  968. * @return
  969. */
  970. private Path createBackgroundPath() {
  971. Path path = new Path();
  972. path.moveTo(mA.x, mA.y);
  973. path.lineTo(mB.x, mB.y);
  974. path.lineTo(mC.x, mC.y);
  975. path.lineTo(mD.x, mD.y);
  976. path.lineTo(mA.x, mA.y);
  977. return path;
  978. }
  979.  
  980. /**
  981. * Draw the background image.
  982. * @param canvas
  983. * @param rect
  984. * @param paint
  985. */
  986. private void drawBackground( Canvas canvas, Rect rect, Paint paint ) {
  987. Path mask = createBackgroundPath();
  988.  
  989. // Save current canvas so we do not mess it up
  990. canvas.save();
  991. canvas.clipPath(mask);
  992. canvas.drawBitmap(mBackground, null, rect, paint);
  993.  
  994. // Draw the page number (first page is 1 in real life :D
  995. // there is no page number 0 hehe)
  996. drawPageNum(canvas, mIndex);
  997.  
  998. canvas.restore();
  999. }
  1000.  
  1001. /**
  1002. * Creates a path used to draw the curl edge in.
  1003. * @return
  1004. */
  1005. private Path createCurlEdgePath() {
  1006. Path path = new Path();
  1007. path.moveTo(mA.x, mA.y);
  1008. path.lineTo(mD.x, mD.y);
  1009. path.lineTo(mE.x, mE.y);
  1010. path.lineTo(mF.x, mF.y);
  1011. path.lineTo(mA.x, mA.y);
  1012. return path;
  1013. }
  1014.  
  1015. /**
  1016. * Draw the curl page edge
  1017. * @param canvas
  1018. */
  1019. private void drawCurlEdge( Canvas canvas )
  1020. {
  1021. Path path = createCurlEdgePath();
  1022. canvas.drawPath(path, mCurlEdgePaint);
  1023. }
  1024.  
  1025. /**
  1026. * Draw page num (let this be a bit more custom)
  1027. * @param canvas
  1028. * @param pageNum
  1029. */
  1030. private void drawPageNum(Canvas canvas, int pageNum)
  1031. {
  1032. mTextPaint.setColor(Color.WHITE);
  1033. String pageNumText = "- "+pageNum+" -";
  1034. drawCentered(canvas, pageNumText,canvas.getHeight()-mTextPaint.getTextSize()-5,mTextPaint,mTextPaintShadow);
  1035. }
  1036.  
  1037. //---------------------------------------------------------------
  1038. // Debug draw methods
  1039. //---------------------------------------------------------------
  1040.  
  1041. /**
  1042. * Draw a text with a nice shadow
  1043. */
  1044. public static void drawTextShadowed(Canvas canvas, String text, float x, float y, Paint textPain, Paint shadowPaint) {
  1045. canvas.drawText(text, x-1, y, shadowPaint);
  1046. canvas.drawText(text, x, y+1, shadowPaint);
  1047. canvas.drawText(text, x+1, y, shadowPaint);
  1048. canvas.drawText(text, x, y-1, shadowPaint);
  1049. canvas.drawText(text, x, y, textPain);
  1050. }
  1051.  
  1052. /**
  1053. * Draw a text with a nice shadow centered in the X axis
  1054. * @param canvas
  1055. * @param text
  1056. * @param y
  1057. * @param textPain
  1058. * @param shadowPaint
  1059. */
  1060. public static void drawCentered(Canvas canvas, String text, float y, Paint textPain, Paint shadowPaint)
  1061. {
  1062. float posx = (canvas.getWidth() - textPain.measureText(text))/2;
  1063. drawTextShadowed(canvas, text, posx, y, textPain, shadowPaint);
  1064. }
  1065.  
  1066. /**
  1067. * Draw debug info
  1068. * @param canvas
  1069. */
  1070. private void drawDebug(Canvas canvas)
  1071. {
  1072. float posX = 10;
  1073. float posY = 20;
  1074.  
  1075. Paint paint = new Paint();
  1076. paint.setStrokeWidth(5);
  1077. paint.setStyle(Style.STROKE);
  1078.  
  1079. paint.setColor(Color.BLACK);
  1080. canvas.drawCircle(mOrigin.x, mOrigin.y, getWidth(), paint);
  1081.  
  1082. paint.setStrokeWidth(3);
  1083. paint.setColor(Color.RED);
  1084. canvas.drawCircle(mOrigin.x, mOrigin.y, getWidth(), paint);
  1085.  
  1086. paint.setStrokeWidth(5);
  1087. paint.setColor(Color.BLACK);
  1088. canvas.drawLine(mOrigin.x, mOrigin.y, mMovement.x, mMovement.y, paint);
  1089.  
  1090. paint.setStrokeWidth(3);
  1091. paint.setColor(Color.RED);
  1092. canvas.drawLine(mOrigin.x, mOrigin.y, mMovement.x, mMovement.y, paint);
  1093.  
  1094. posY = debugDrawPoint(canvas,"A",mA,Color.RED,posX,posY);
  1095. posY = debugDrawPoint(canvas,"B",mB,Color.GREEN,posX,posY);
  1096. posY = debugDrawPoint(canvas,"C",mC,Color.BLUE,posX,posY);
  1097. posY = debugDrawPoint(canvas,"D",mD,Color.CYAN,posX,posY);
  1098. posY = debugDrawPoint(canvas,"E",mE,Color.YELLOW,posX,posY);
  1099. posY = debugDrawPoint(canvas,"F",mF,Color.LTGRAY,posX,posY);
  1100. posY = debugDrawPoint(canvas,"Mov",mMovement,Color.DKGRAY,posX,posY);
  1101. posY = debugDrawPoint(canvas,"Origin",mOrigin,Color.MAGENTA,posX,posY);
  1102. posY = debugDrawPoint(canvas,"Finger",mFinger,Color.GREEN,posX,posY);
  1103. }
  1104.  
  1105. private float debugDrawPoint(Canvas canvas, String name, Vector2D point, int color, float posX, float posY) {
  1106. return debugDrawPoint(canvas,name+" "+point.toString(),point.x, point.y, color, posX, posY);
  1107. }
  1108.  
  1109. private float debugDrawPoint(Canvas canvas, String name, float X, float Y, int color, float posX, float posY) {
  1110. mTextPaint.setColor(color);
  1111. drawTextShadowed(canvas,name,posX , posY, mTextPaint,mTextPaintShadow);
  1112. Paint paint = new Paint();
  1113. paint.setStrokeWidth(5);
  1114. paint.setColor(color);
  1115. canvas.drawPoint(X, Y, paint);
  1116. return posY+15;
  1117. }
  1118.  
  1119. }
  1120. // Xml file
  1121. <?xml version="1.0" encoding="utf-8"?>
  1122. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  1123. android:layout_width="match_parent"
  1124. android:layout_height="match_parent" >
  1125.  
  1126. <com.package.name.PageCurlView
  1127. android:id="@+id/dcgpagecurlPageCurlView1"
  1128. android:layout_width="wrap_content"
  1129. android:layout_height="wrap_content"
  1130. android:background="@drawable/note1" >
  1131. </com.package.name.PageCurlView>
  1132.  
  1133. </LinearLayout>
  1134.  
  1135.  
  1136. // Activity where i am using Object of pagecurlview
  1137.  
  1138. import android.app.Activity;
  1139. import android.content.Context;
  1140. import android.graphics.Bitmap;
  1141. import android.graphics.drawable.BitmapDrawable;
  1142. import android.os.Bundle;
  1143. import android.text.Editable;
  1144. import android.text.TextWatcher;
  1145. import android.view.LayoutInflater;
  1146. import android.view.View;
  1147. import android.view.View.OnLongClickListener;
  1148. import android.widget.EditText;
  1149. import android.widget.ImageView;
  1150. import android.widget.Toast;
  1151.  
  1152. public class PagingAnimationActivity extends Activity implements OnLongClickListener
  1153. {
  1154. private ImageView imgMain;
  1155. private EditText note_description;
  1156. private PageCurlView pageCurlView;
  1157. private Database db ;
  1158. public void onCreate(Bundle savedInstanceState)
  1159. {
  1160. super.onCreate(savedInstanceState);
  1161. setContentView(R.layout.activity_paging);
  1162. /*initControls();
  1163. displayAllStickyData();*/
  1164. initControls();
  1165. }
  1166.  
  1167. @Override
  1168. public void onDestroy()
  1169. {
  1170. super.onDestroy();
  1171. System.gc();
  1172. finish();
  1173. }
  1174.  
  1175. private void initControls()
  1176. {
  1177. db = new Database(PagingAnimationActivity.this);
  1178. TabNoteActivity.quickAction.setOnActionItemClickListener(new QuickAction.OnActionItemClickListener()
  1179. {
  1180. public void onItemClick(QuickAction source, int pos, int actionId)
  1181. {
  1182. Toast.makeText(PagingAnimationActivity.this,actionId +"Position",Toast.LENGTH_SHORT).show();
  1183. TabNoteActivity.actionItem = TabNoteActivity.quickAction.getActionItem(pos);
  1184. actionStickyView(actionId);
  1185. }
  1186. });
  1187. }
  1188.  
  1189.  
  1190. public static Bitmap getBitmapFromDrawableId(Context context,int drawableId)
  1191. {
  1192. Bitmap bitmap = null;
  1193. try
  1194. {
  1195. BitmapDrawable drawable = (BitmapDrawable)context.getResources().getDrawable(drawableId);
  1196. bitmap = drawable.getBitmap();
  1197. }
  1198. catch (Exception e)
  1199. {
  1200. e.printStackTrace();
  1201. }
  1202. return bitmap;
  1203. }
  1204. /**
  1205. * Action sticky view.
  1206. * adding sticky to Layer
  1207. *
  1208. * @param imageId the image id
  1209. */
  1210. private void actionStickyView(int imageId)
  1211. {
  1212. try
  1213. {
  1214. LayoutInflater inflate=(LayoutInflater)PagingAnimationActivity.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
  1215. final View v=inflate.inflate(R.layout.note_detail, null);
  1216. imgMain = (ImageView)v.findViewById(R.id.imgMain);
  1217. switch (imageId)
  1218. {
  1219. case 1:
  1220. imgMain.setBackgroundResource(R.drawable.note1);
  1221. break;
  1222.  
  1223. case 2:
  1224. imgMain.setBackgroundResource(R.drawable.note2);
  1225. break;
  1226.  
  1227. case 3:
  1228. imgMain.setBackgroundResource(R.drawable.note3);
  1229. break;
  1230.  
  1231. case 4:
  1232. imgMain.setBackgroundResource(R.drawable.note4);
  1233. break;
  1234.  
  1235. default:
  1236. break;
  1237. }
  1238. note_description=(EditText) v.findViewById(R.id.note_description);
  1239. int w = 190;
  1240. int h = 190;
  1241. v.setId(BaseActivity.createStickyId());
  1242. pageCurlView = new PageCurlView(PagingAnimationActivity.this,v);
  1243.  
  1244. final int getId=v.getId();
  1245. v.setOnLongClickListener(PagingAnimationActivity.this);
  1246. note_description.addTextChangedListener(new TextWatcher()
  1247. {
  1248. public void onTextChanged(CharSequence s, int start, int before, int count)
  1249. {
  1250. String note_text=s.toString();
  1251. db.OpenDatabase();
  1252. if(db.isStickExist(getId))
  1253. {
  1254. db.updateDescription(getId,note_text);
  1255. }
  1256. }
  1257. public void beforeTextChanged(CharSequence s, int start, int count,int after) {}
  1258. public void afterTextChanged(Editable s)
  1259. {
  1260. db.closeDatabase();
  1261. }
  1262. });
  1263. db.closeDatabase();
  1264. }
  1265. catch (Exception e)
  1266. {
  1267. e.printStackTrace();
  1268. }
  1269. }
  1270.  
  1271. public boolean onLongClick(View v)
  1272. {
  1273. return false;
  1274. }
  1275. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement