Knowledge Base and examples

Knowledge Base - Base functionality with Curl

This article illustrate an example of a custom class that is based on PDFViewDual, that supports curl effect (in case zoom factor = 1), and uses the curl effect from the native library.
 
(note: some variables in PDFView need to be protected and to modify these classes you need at least the professional license)
In PDFViewDual you need to do the following:
  • Make m_cells variable protected.
  • Make the variables max_w and max_h declared in vLayout, global and protected
  • Add the variable protected boolean  mCurlAllowed = false;
In PDFReader you need to declare the curl view as follows, both in PDFOpen and PDFSetView:
PDFViewDual viewCurl = new PDFViewCurl(this.getContext());
boolean parasC[] = new boolean[m_doc.GetPageCount()];
int current = 0;
while( current < parasC.length )  {
parasC[current] = false;
current++;
}
viewCurl.vSetLayoutPara(null, parasC, m_rtol, true);
m_view = viewCurl;
 
package com.radaee.view;

import com.radaee.pdf.DIB;
import com.radaee.pdf.Global;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Bitmap.Config;
import android.view.GestureDetector;
import android.view.MotionEvent;

/**
 * @author Nermeen
 */
public class PDFViewCurl extends PDFViewDual {
	
	private int page_w = 0;
	private int page_h = 0;
	private DIB m_dib1 = null;
	private DIB m_dib2 = null;
	private float m_stepy = 0;
	private float m_stepx = 0;
	private int m_hold_dir = 0;
	private Bitmap mCurlBitmap;
	private int m_hold_style = 0;
	private boolean curling = false;
	private boolean mCurlChangePage = false;
	private GestureDetector m_gesture = null;

    public PDFViewCurl(Context context) {
	    super(context);	 
	    m_pageno = 0;
	    m_dib1 = new DIB();
		m_dib2 = new DIB();
	    mCurlAllowed = true;
	    m_gesture = new GestureDetector(context, new PDFGestureListener());
    }
    
    @Override
	public void vClose() {
		super.vClose();
		if(m_dib1 != null) m_dib1.Free();
		if(m_dib2 != null) m_dib2.Free();
		m_dib1 = null;
		m_dib2 = null;
		m_pageno = 0;
	}
    
    @Override
    public void vResize(int w, int h) {
    	if(w != m_w || h != m_h) {
    		m_scale = 0;
    		mCurlBitmap = null;
    	}
        super.vResize(w, h);
    }
    
    @Override
	protected void vLayout() {
    	super.vLayout();
    	
    	vSetLock(3);
    	
		if( m_doc == null || m_w <= m_page_gap || m_h <= m_page_gap ) return;
    	
    	page_w = (int) (max_w * m_scale);
    	page_h = (int) (max_h * m_scale);
    	
    	if(m_status != STA_ZOOM) {
    		m_stepx = page_w / 8;
        	m_stepy = 0;
        	
        	if(m_dib1 == null) m_dib1 = new DIB();
    		if(m_dib2 == null) m_dib2 = new DIB();
    		
        	m_dib1.CreateOrResize(page_w, page_h);
    		m_dib2.CreateOrResize(page_w, page_h);
    		
    		if((mCurlBitmap == null) && mCurlAllowed) 
    			mCurlBitmap = Bitmap.createBitmap(page_w, page_h, Config.ARGB_8888);
    	}
	}   
    
    @Override
    protected boolean vOnFling(float dx, float dy, float velocityX, float velocityY) {
    	return true;
    }
    
    @Override
	protected void vOnTimer(Object obj) {
		if(m_status == STA_CURLING && m_hold_dir != 0 ) {
    		if( m_hold_dir < 0 ) { //next page
    			if( m_holdx <= -m_w/2 ) {
    				m_status = STA_NONE;
    				m_pageno ++;
    				endCurl();
    				if( m_listener != null)
    					m_listener.OnPDFPageChanged(m_pageno);
   				}
    			else {
		    		m_holdx -= m_stepx;
		    		m_holdy += m_stepy * m_stepx;
		    		if( m_holdy < 0.0001 ) m_holdy = 0;
		    		if( m_holdy > m_h - 0.0001 ) m_holdy = m_h;
    			}
    		}
    		else { //previous page
	    		m_holdx += m_stepx;
	    		m_holdy += m_stepy * m_stepx;
    			if( m_holdx >= ((m_w - m_pages[m_pageno].m_w) / 2) + m_pages[m_pageno].m_w) {
    				m_status = STA_NONE;
    				endCurl();
    			}
    		}
        	if( m_listener != null )
        		m_listener.OnPDFInvalidate(false);
		}
		else {
			super.vOnTimer(obj);
		}
    }
    
    private void endCurl() {
    	m_scroller.forceFinished(true);
    	m_scroller.setFinalX(m_cells[m_pageno].left);
		m_scroller.setFinalY(0);
		m_scroller.computeScrollOffset();
		curling = false;
    }
    
    @Override
	protected boolean motionNormal(MotionEvent event) {
    	if(m_gesture.onTouchEvent(event)) return true;
    	
		switch(event.getActionMasked()) {
		case MotionEvent.ACTION_DOWN:
			if( m_status == STA_NONE ) {
				curling = false;
				m_scroller.forceFinished(true);
				m_holdsx = m_scroller.getCurrX();
				m_holdsy = m_scroller.getCurrY();
				
				m_holdx = event.getX();
				m_holdy = event.getY();
				m_hold_style = 1;
    			
    			if( m_holdx > m_w / 2 ) {
    				if(m_pageno == m_pages.length - 1)
    					m_hold_style = 0;
    				else
    					m_status = STA_MOVING;
    			}
    			else {
    				if(m_pageno == 0)
    					m_hold_style = 0;
    				else {
    					mCurlChangePage = true;
    					m_status = STA_MOVING;
    				}
    			}
    	    	if( m_listener != null ) m_listener.OnPDFInvalidate(false);
			}
			return true;
		case MotionEvent.ACTION_MOVE:
			if(mCurlAllowed && m_status == STA_MOVING) {
				if(m_status != STA_ZOOM) {
					if(mCurlChangePage) {
						m_pageno --;
						if( m_listener != null)
							m_listener.OnPDFPageChanged(m_pageno);
						mCurlChangePage = false;
					}
					curling = true;
				}
				
				m_holdx = event.getX();
				m_holdy = event.getY();
				
				if( m_listener != null ) m_listener.OnPDFInvalidate(false);
				
				return true;
			}	
			else 
				return super.motionNormal(event);
		case MotionEvent.ACTION_UP:
		case MotionEvent.ACTION_CANCEL:
			if(m_status == STA_MOVING && mCurlAllowed && curling) {
				m_holdx = event.getX();
				m_holdy = event.getY();
    			if( m_holdx > m_w / 2 ) { //previous page
    				if( m_hold_style == 1 )//right-bottom corner
    					m_stepy = (m_h - m_holdy) / (m_w - m_holdx);
    				else//right-top corner
    					m_stepy = -m_holdy / (m_w - m_holdx);
    				m_hold_dir = 1;
    			}
    			else { //next page
    				if( m_hold_style == 1 ) {
    					m_stepy = (m_h - m_holdy) / (m_stepx * 3);
    					if( m_stepy < 0 ) m_stepy = 0;
    				}
    				else {
    					m_stepy = (0 - m_holdy) / (m_stepx * 3);
    					if( m_stepy > 0 ) m_stepy = 0;
    				}
    				m_hold_dir = -1;
    			}
				m_status = STA_CURLING;
				if( m_listener != null ) m_listener.OnPDFInvalidate(false);
				
				return true;
			}
			else 
				return super.motionNormal(event);
		case MotionEvent.ACTION_POINTER_DOWN:
			if(event.getPointerCount() == 2 && m_status == STA_MOVING && m_lock != 5) {
				curling = false;
				mCurlAllowed = false;
				return super.motionNormal(event);
			}
		}
		return super.motionNormal(event);
	}
    
    @Override
    public void vDraw(Canvas canvas) {
    	if(curling && mCurlAllowed && (m_status == STA_MOVING || m_status == STA_CURLING)) {
    		int cur = 0;
    		int disp_start = -1;
    		int disp_end = -1;
    		int sel_rect1[] = null;
    		int sel_rect2[] = null;
    		
			while( cur < m_pageno ) {
				m_thread.end_render(m_pages[cur]);
				cur++;
			}
			disp_start = cur;
			
			canvas.drawColor(m_back);

			if(m_pages[cur].m_w != mCurlBitmap.getWidth() || m_pages[cur].m_h != mCurlBitmap.getHeight() ) {
				mCurlBitmap = Bitmap.createScaledBitmap(mCurlBitmap, m_pages[cur].m_w, m_pages[cur].m_h, false); 
				m_dib1.CreateOrResize(m_pages[cur].m_w, m_pages[cur].m_h);
				m_dib2.CreateOrResize(m_pages[cur].m_w, m_pages[cur].m_h);
			}
			
			mCurlBitmap.eraseColor(m_back);
			
			m_draw_bmp.Create(mCurlBitmap);
			m_pages[cur].Draw(m_draw_bmp, m_pages[cur].m_x, m_pages[cur].m_y);
			if( Global.dark_mode ) m_draw_bmp.Invert();
			m_draw_bmp.Free(mCurlBitmap);
			
			m_dib1.DrawRect(m_back, 0, 0, m_w, m_h, 1);
			m_dib2.DrawRect(m_back, 0, 0, m_w, m_h, 1);
			
			m_thread.start_render(m_pages[cur]);
			
			m_pages[cur].DrawDIB(m_dib1, m_pages[cur].m_x, m_pages[cur].m_y);
			if( sel_rect1 == null || sel_rect2 == null ) {
				sel_rect1 = m_pages[cur].GetSelRect1(0, 0);
				sel_rect2 = m_pages[cur].GetSelRect2(0, 0);
			}
			if( m_finder.find_get_page() == cur )
				m_finder.find_draw_to_dib(m_dib1, m_pages[cur], 0, 0);
			cur++;

			if( cur < m_pages.length ) {
				m_thread.start_render(m_pages[cur]);
				m_pages[cur].DrawDIB(m_dib2, m_pages[cur].m_x, m_pages[cur].m_y);
				//m_pages[cur].DrawDIB(m_dib2, m_pages[cur].m_x, 0);
				if( sel_rect1 == null || sel_rect2 == null ) {
					sel_rect1 = m_pages[cur].GetSelRect1(0, 0);
					sel_rect2 = m_pages[cur].GetSelRect2(0, 0);
				}
				if( m_finder.find_get_page() == cur )
					m_finder.find_draw_to_dib(m_dib2, m_pages[cur], 0, 0);
				cur++;

				if( Global.dark_mode ) {
					if( m_h > m_w )  //vertical
						Global.DrawScroll(mCurlBitmap, m_dib1, m_dib2, (int) m_holdx, m_h, -m_hold_style);
					else
						Global.DrawScroll(mCurlBitmap, m_dib1, m_dib2, (int) (m_holdx - (page_w / 2)), m_h, -m_hold_style);
				}
				else {
					if( m_h > m_w )  //vertical
						Global.DrawScroll(mCurlBitmap, m_dib1, m_dib2, (int) m_holdx, m_h, m_hold_style);
					else 
						Global.DrawScroll(mCurlBitmap, m_dib1, m_dib2, (int) (m_holdx - (page_w / 2)), m_h, m_hold_style);
				}
			}
			else {
				m_draw_bmp.Create(mCurlBitmap);
				m_dib1.DrawToBmp(m_draw_bmp, 0, 0);
		        if( Global.dark_mode ) m_draw_bmp.Invert();
		        m_draw_bmp.Free(mCurlBitmap);
			}
			
			disp_end = cur;
			int cnt = m_pages.length;
			while( cur < cnt ) {
				m_thread.end_render(m_pages[cur]);
				cur++;
			}
			
			canvas.drawBitmap(mCurlBitmap, (int)((m_w - m_pages[m_pageno].m_w) / 2), m_pages[m_pageno].m_y, null);
			
			if( m_listener != null && disp_start >= 0 ) {
				if( disp_end < 0 ) disp_end = m_pages.length;
				while( disp_start < disp_end ) {
					m_listener.OnPDFPageDisplayed(canvas, m_pages[disp_start]);
					disp_start++;
				}
				if( sel_rect1 != null && sel_rect2 != null )
					m_listener.OnPDFSelecting(canvas, sel_rect1, sel_rect2);
			}
    	}
    	else 
    		super.vDraw(canvas);
    }
    
    protected void vOnZoomEnd() {
    	super.vOnZoomEnd();
    	
    	if(vGetScale() > vGetMinScale()) {
    		vSetLock(0);
    		mCurlAllowed = false;
    	}
    	else {
    		vSetLock(3);
    		mCurlAllowed = true;
    	}
	}
    
    @Override
	public void vCenterPage(int pageno) {
		if( m_pages == null || m_doc == null || m_w <= 0 || m_h <= 0 ) return;
		int ccur = 0;
		while( ccur < m_cells.length ) {
			PDFCell cell = m_cells[ccur];
			if(pageno == cell.page_left || pageno == cell.page_right) {
				int left = m_cells[ccur].left;
				int w = m_cells[ccur].right - left;
				int x = left + (w - m_w)/2;
				int oldx = m_scroller.getCurrX();
				int oldy = m_scroller.getCurrY();
				m_scroller.startScroll(oldx, oldy, x - oldx, 0, 0);
				break;
			}
			ccur++;
		}
	}
    
    class PDFGestureListener extends GestureDetector.SimpleOnGestureListener {    
    	
    	@Override
    	public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
    		if(m_listener != null)
    			m_listener.OnPDFFling(e1, e2, velocityX, velocityY);
			return false;
    	}
    	
    	@Override 
    	public boolean onDoubleTapEvent(MotionEvent e) {
    		if( m_listener != null && e.getActionMasked() == MotionEvent.ACTION_UP) {
    			if( m_listener.OnPDFDoubleTapped(e.getX(), e.getY())) {
    				m_status = STA_NONE;
    				vOnZoomEnd();
    				return true;
    			}
    			else return false;
    		}
    		else
    			return false;
        }
    	
    	@Override
        public void onLongPress(MotionEvent e) {
    		if( m_listener != null )
    			m_listener.OnPDFLongPressed(e.getX(), e.getY());
        }
        
        @Override
        public void onShowPress(MotionEvent e) {
    		if( m_listener != null )
    			m_listener.OnPDFShowPressed(e.getX(), e.getY());
        }
        
        @Override
        public boolean onSingleTapConfirmed(MotionEvent e) {
        	vSingleTap( e.getX(), e.getY() );
    		if( m_listener != null/* && m_status == STA_MOVING*/ ) {
    			if( m_listener.OnPDFSingleTapped(e.getX(), e.getY())) {
    				m_status = STA_NONE;
    				return true;
    			}
    			else
    				return false;
    		}
    		else
    			return false;
        }
        
        @Override
        public boolean onSingleTapUp(MotionEvent e) {
        	return false;
        }
    }
}
Applies To

RadaeePDF SDK for Android

Details

Created : 2015-04-28 10:34:12, Last Modified : 2016-09-19 10:46:06