/* * Copyright (C) 2016 eschao <esc.chao@gmail.com> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.eschao.android.widget.sample.pageflip; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.os.Handler; import android.os.Message; import android.widget.Toast; import com.eschao.android.widget.pageflip.Page; import com.eschao.android.widget.pageflip.PageFlip; import com.eschao.android.widget.pageflip.PageFlipState; /** * Single page render * <p> * Every page need 2 texture in single page mode: * <ul> * <li>First texture: current page content</li> * <li>Back texture: back of front content, it is same with first texture * </li> * <li>Second texture: next page content</li> * </ul> * </p> * * @author eschao */ public class SinglePageRender extends PageRender { /** * Constructor * @see {@link #PageRender(Context, PageFlip, Handler, int)} */ public SinglePageRender(Context context, PageFlip pageFlip, Handler handler, int pageNo) { super(context, pageFlip, handler, pageNo); } /** * Draw frame */ public void onDrawFrame() { // 1. delete unused textures mPageFlip.deleteUnusedTextures(); Page page = mPageFlip.getFirstPage(); // 2. handle drawing command triggered from finger moving and animating if (mDrawCommand == DRAW_MOVING_FRAME || mDrawCommand == DRAW_ANIMATING_FRAME) { // is forward flip if (mPageFlip.getFlipState() == PageFlipState.FORWARD_FLIP) { // check if second texture of first page is valid, if not, // create new one if (!page.isSecondTextureSet()) { drawPage(mPageNo + 1); page.setSecondTexture(mBitmap); } } // in backward flip, check first texture of first page is valid else if (!page.isFirstTextureSet()) { drawPage(--mPageNo); page.setFirstTexture(mBitmap); } // draw frame for page flip mPageFlip.drawFlipFrame(); } // draw stationary page without flipping else if (mDrawCommand == DRAW_FULL_PAGE) { if (!page.isFirstTextureSet()) { drawPage(mPageNo); page.setFirstTexture(mBitmap); } mPageFlip.drawPageFrame(); } // 3. send message to main thread to notify drawing is ended so that // we can continue to calculate next animation frame if need. // Remember: the drawing operation is always in GL thread instead of // main thread Message msg = Message.obtain(); msg.what = MSG_ENDED_DRAWING_FRAME; msg.arg1 = mDrawCommand; mHandler.sendMessage(msg); } /** * Handle GL surface is changed * * @param width surface width * @param height surface height */ public void onSurfaceChanged(int width, int height) { // recycle bitmap resources if need if (mBackgroundBitmap != null) { mBackgroundBitmap.recycle(); } if (mBitmap != null) { mBitmap.recycle(); } // create bitmap and canvas for page //mBackgroundBitmap = background; Page page = mPageFlip.getFirstPage(); mBitmap = Bitmap.createBitmap((int)page.width(), (int)page.height(), Bitmap.Config.ARGB_8888); mCanvas.setBitmap(mBitmap); LoadBitmapTask.get(mContext).set(width, height, 1); } /** * Handle ended drawing event * In here, we only tackle the animation drawing event, If we need to * continue requesting render, please return true. Remember this function * will be called in main thread * * @param what event type * @return ture if need render again */ public boolean onEndedDrawing(int what) { if (what == DRAW_ANIMATING_FRAME) { boolean isAnimating = mPageFlip.animating(); // continue animating if (isAnimating) { mDrawCommand = DRAW_ANIMATING_FRAME; return true; } // animation is finished else { final PageFlipState state = mPageFlip.getFlipState(); // update page number for backward flip if (state == PageFlipState.END_WITH_BACKWARD) { // don't do anything on page number since mPageNo is always // represents the FIRST_TEXTURE no; } // update page number and switch textures for forward flip else if (state == PageFlipState.END_WITH_FORWARD) { mPageFlip.getFirstPage().setFirstTextureWithSecond(); mPageNo++; } mDrawCommand = DRAW_FULL_PAGE; return true; } } return false; } /** * Draw page content * * @param number page number */ private void drawPage(int number) { final int width = mCanvas.getWidth(); final int height = mCanvas.getHeight(); Paint p = new Paint(); p.setFilterBitmap(true); // 1. draw background bitmap Bitmap background = LoadBitmapTask.get(mContext).getBitmap(); Rect rect = new Rect(0, 0, width, height); mCanvas.drawBitmap(background, null, rect, p); background.recycle(); background = null; // 2. draw page number int fontSize = calcFontSize(80); p.setColor(Color.WHITE); p.setStrokeWidth(1); p.setAntiAlias(true); p.setShadowLayer(5.0f, 8.0f, 8.0f, Color.BLACK); p.setTextSize(fontSize); String text = String.valueOf(number); float textWidth = p.measureText(text); float y = height - p.getTextSize() - 20; mCanvas.drawText(text, (width - textWidth) / 2, y, p); if (number <= 1) { String firstPage = "The First Page"; p.setTextSize(calcFontSize(16)); float w = p.measureText(firstPage); float h = p.getTextSize(); mCanvas.drawText(firstPage, (width - w) / 2, y + 5 + h, p); } else if (number >= MAX_PAGES) { String lastPage = "The Last Page"; p.setTextSize(calcFontSize(16)); float w = p.measureText(lastPage); float h = p.getTextSize(); mCanvas.drawText(lastPage, (width - w) / 2, y + 5 + h, p); } } /** * If page can flip forward * * @return true if it can flip forward */ public boolean canFlipForward() { return (mPageNo < MAX_PAGES); } /** * If page can flip backward * * @return true if it can flip backward */ public boolean canFlipBackward() { if (mPageNo > 1) { mPageFlip.getFirstPage().setSecondTextureWithFirst(); return true; } else { return false; } } }