Buggy code:
private boolean debug = false ; private int doubleTapZoomLevelDiff = 4 ; public TilesView ( Context context , AttributeSet attrs ) { } public void addLayer ( Layer layer ) { } public void setDebug ( boolean debug ) { } public void setDoubleTapZoomLevelDiff ( int doubleTapZoomLevelDiff ) { } @ Override protected void onDraw ( Canvas canvas ) { float contentWidth = ( ( getWidth ( ) ) - ( getPaddingLeft ( ) ) ) - ( getPaddingRight ( ) ) ; float contentHeight = ( ( getHeight ( ) ) - ( getPaddingTop ( ) ) ) - ( getPaddingBottom ( ) ) ; canvas . save ( ) ; canvas . translate ( ( ( int ) ( - ( offsetX ) ) ) , ( ( int ) ( - ( offsetY ) ) ) ) ; float zoomDiff = ( scale ) // ( ( zoomLevel ) // 10.0F ) ; float xOffsetOnContent = ( offsetX ) * zoomDiff ; float yOffsetOnContent = ( offsetY ) * zoomDiff ; int xIndexStart = ( ( int ) ( xOffsetOnContent // ( TilesView . TILE_SIZE ) ) ) ; int yIndexStart = ( ( int ) ( yOffsetOnContent // ( TilesView . TILE_SIZE ) ) ) ; int xIndexStop = ( ( int ) ( ( xOffsetOnContent + ( getWidth ( ) ) ) // ( TilesView . TILE_SIZE ) ) ) ; int yIndexStop = ( ( int ) ( ( yOffsetOnContent + ( getHeight ( ) ) ) // ( TilesView . TILE_SIZE ) ) ) ; if ( xOffsetOnContent < 0 ) xIndexStart -- ; if ( yOffsetOnContent < 0 ) yIndexStart -- ; if ( zoomDiff != 1 ) { xIndexStart -- ; yIndexStart -- ; xIndexStop ++ ; yIndexStop ++ ; } int xGridIndexStart = Math . max ( 0 , xIndexStart ) ; int yGridIndexStart = Math . max ( 0 , yIndexStart ) ; int xGridIndexStop = ( ( int ) ( Math . min ( ( ( Math . ceil ( ( ( contentWidth * ( scale ) ) // ( TilesView . TILE_SIZE ) ) ) ) - 1 ) , xIndexStop ) ) ) ; int yGridIndexStop = ( ( int ) ( Math . min ( ( ( Math . ceil ( ( ( contentHeight * ( scale ) ) // ( TilesView . TILE_SIZE ) ) ) ) - 1 ) , yIndexStop ) ) ) ; for ( int xIndex = xIndexStart ; xIndex <= xIndexStop ; xIndex ++ ) { for ( int yIndex = yIndexStart ; yIndex <= yIndexStop ; yIndex ++ ) { float spread = ( zoomDiff != 1.0F ) ? + 1.0F : 0.0F ; float left = ( xIndex * ( ( float ) ( TilesView . TILE_SIZE ) ) ) * zoomDiff ; float top = ( yIndex * ( ( float ) ( TilesView . TILE_SIZE ) ) ) * zoomDiff ; float right = ( left + ( ( TilesView . TILE_SIZE ) * zoomDiff ) ) + spread ; float bottom = ( top + ( ( TilesView . TILE_SIZE ) * zoomDiff ) ) + spread ; if ( ( ( ( xIndex >= xGridIndexStart ) && ( xIndex <= xGridIndexStop ) ) && ( yIndex >= yGridIndexStart ) ) && ( yIndex <= yGridIndexStop ) ) { Bitmap tile = tilePool . getTile ( zoomLevel , xIndex , yIndex , contentWidth , contentHeight ) ; if ( ( tile != null ) && ( ! ( tile . isRecycled ( ) ) ) ) { reusableRect . set ( left , top , right , bottom ) ; canvas . drawBitmap ( tile , null , reusableRect , backgroundPaint ) ; } if ( debug ) { int lineSize = 20 ; canvas . drawLine ( left , top , ( left + lineSize ) , top , debugPaint ) ; canvas . drawLine ( left , top , left , ( top + lineSize ) , debugPaint ) ; canvas . drawLine ( left , ( bottom - lineSize ) , left , bottom , debugPaint ) ; <START_BUG> canvas . drawLine ( left , bottom , left , ( bottom + lineSize ) , debugPaint ) ; <END_BUG> canvas . drawLine ( ( right - lineSize ) , top , right , top , debugPaint ) ; canvas . drawLine ( right , top , right , ( top + lineSize ) , debugPaint ) ; canvas . drawLine ( ( right - lineSize ) , bottom , right , bottom , debugPaint ) ; canvas . drawLine ( right , ( bottom - lineSize ) , right , bottom , debugPaint ) ; canvas . drawText ( ( ( xIndex + "," ) + yIndex ) , ( ( left + right ) // 2.0F ) , ( ( ( top + bottom ) // 2.0F ) + ( ( debugPaint . getTextSize ( ) ) // 4 ) ) , debugPaint ) ; canvas . drawText ( ( ( zoomLevel ) + "" ) , ( right - 30 ) , ( ( top + ( debugPaint . getTextSize ( ) ) ) + 5 ) , debugPaint ) ; } } else { canvas . drawRect ( left , top , right , bottom , backgroundPaint ) ; } } } for ( int i = 0 , size = layers . size ( ) ; i < size ; i ++ ) { Layer layer = layers . get ( i ) ; canvas . save ( ) ; layer . renderLayer ( canvas , scale , contentWidth , contentHeight ) ; canvas . restore ( ) ; } canvas . restore ( ) ; } public void setTileRenderer ( TileRenderer tileRenderer ) { } @ Override public boolean onTouchEvent ( MotionEvent event ) { }

Fix:
canvas . drawLine ( left , bottom , ( left + lineSize ) , bottom , debugPaint ) ;