java - How can I place limits on my canvas's translation matrix? -


so i'm extending custom surfaceview , attempting make have pinch-zoom , scrolling capability.

how scroll:

    @override     public boolean onscroll(motionevent e1, motionevent e2,             float distancex, float distancey) {          // subtract scrolled amount         matrix.posttranslate(-distancex, -distancey);          rebound();          invalidate();          // handled         return true;     } 

how zoom:

    @override     public boolean onscale(scalegesturedetector detector) {         if (detector.isinprogress()) {             // scale              float factor = detector.getscalefactor();              // don't let object small or large.             if (factor * scale > 1f) {                 factor = 1f / scale;             } else if (factor * scale < minscale) {                 factor = minscale / scale;             }              // store local scale             scale *= factor;              // scale             matrix.prescale(factor, factor, detector.getfocusx(), detector.getfocusy());              rebound();              invalidate();         }          return true;     } 

(for reference use code ondraw:)

@override protected void ondraw(canvas canvas) {     super.ondraw(canvas);      canvas.save();     canvas.setmatrix(matrix);     // [...] stuff drawn matrix settings     canvas.restore();     // [...] stuff drawn without matrix settings, overlay } 

currently both of these methods functioning well. zooming stopped @ minimum (between 0f , 1f) , maximum (currently 1f) scale value correctly.

global fields used:

  • draww, drawh = float, size in pixels of canvas data @ scale = 1.
  • parentw, parenth = float, size in pixels of visible view.
  • matrix = android.graphics.matrix.

the problem "rebound()" (maybe needs better name, heh) method i'm attempting implement automatically force contents stay in view.

i've tried various methods try calculate bounds should (within rectangle (0, 0, parentw, parenth)) , translate matrix "back" when goes far.

here's have, doesn't work, instead pushing farther in right lot. feel problem math, not idea. can please come simpler or cleaner code translates matrix edge if far and/or fix problems attempt @ implementation? if checks used make appear in top left

public void rebound() {     // bounds     rectf currentbounds = new rectf(0, 0, draww, drawh);     matrix.maprect(currentbounds);     rectf parentbounds = new rectf(0, 0, parentw, parenth/2);      pointf diff = new pointf(0, 0);      if (currentbounds.left > parentbounds.left) {         diff.x += (parentbounds.left - currentbounds.left);     }     if (currentbounds.top > parentbounds.top) {         diff.y += (parentbounds.top - currentbounds.top);     }     if (currentbounds.width() > parentbounds.width()) {         if (currentbounds.right < parentbounds.right) {             diff.x += (parentbounds.right - currentbounds.right);         }         if (currentbounds.bottom < parentbounds.bottom) {             diff.y += (parentbounds.bottom - currentbounds.bottom);         }     }      matrix.posttranslate(diff.x, diff.y); } 

a previous version wrote before matrix field (i used canvas.scale() canvas.translate() in ondraw) worked:

public void rebound() {     // bounds     int boundtop = 0;     int boundleft = 0;     int boundright = (int)(-scale * draww + parentw);     int boundbottom = (int)(-scale * drawh + parenth);      if (boundleft >= boundright) {         mscrollx = math.min(boundleft, math.max(boundright, mscrollx));     } else {         mscrollx = 0;     }     if (boundtop >= boundbottom) {         mscrolly = math.min(boundtop, math.max(boundbottom, mscrolly));     } else {         mscrolly = 0;     } } 

i'm using new way can correctly scale centered on detector.getfocusx(), detector.getfocusy().

update: changed method now. works somewhat, still bounding y direction way off-center , wrong after changing zoom levels. made "prescale" , "posttranslate" (as understand it) should applying scale translate , not mixing them.

final update: works now. here's working rebound method comments:

public void rebound() {     // make rectangle representing our current canvas looks     rectf currentbounds = new rectf(0, 0, draww, drawh);     matrix.maprect(currentbounds);     // make rectangle representing scroll bounds     rectf areabounds = new rectf((float) getleft(),                                    (float) gettop(),                                    (float) parentw + (float) getleft(),                                    (float) parenth + (float) gettop());      // difference between current rectangle , rectangle want     pointf diff = new pointf(0f, 0f);      // x-direction     if (currentbounds.width() > areabounds.width()) {         // allow scrolling if amount of content wide @ scale         if (currentbounds.left > areabounds.left) {             // stop scrolling far left             diff.x = (areabounds.left - currentbounds.left);         }         if (currentbounds.right < areabounds.right) {             // stop scrolling far right             diff.x = (areabounds.right - currentbounds.right);         }     } else {         // negate scrolling         diff.x = (areabounds.left - currentbounds.left);     }      // y-direction     if (currentbounds.height() > areabounds.height()) {         // allow scrolling if amount of content tall @ scale         if (currentbounds.top > areabounds.top) {             // stop scrolling far above             diff.y = (areabounds.top - currentbounds.top);         }         if (currentbounds.bottom < areabounds.bottom) {             // stop scrolling far below             diff.y = (areabounds.bottom - currentbounds.bottom);         }     } else {         // negate scrolling         diff.y = (areabounds.top - currentbounds.top);     }      // translate     matrix.posttranslate(diff.x, diff.y); } 

it negates scrolling don't want translating bounds. negates scrolling if content small, forcing content in top-left.

i implemented roll own pinch zoom. suspect problem y-axis being off centre may down view not being full screen size, or might not changing co-ordinates match scale.

my implementation calculates scale factor, applies with: canvas.scale( pinchzoomscale, pinchzoomscale ); calculates physical size of screen in pixels, converts metres, , applies scaling factor objects drawn offset correctly.

this implementation relies on knowing should @ centre of screen , locking on it, whatever zoom level.


Comments

Popular posts from this blog

linux - Using a Cron Job to check if my mod_wsgi / apache server is running and restart -

actionscript 3 - TweenLite does not work with object -

jQuery Ajax Render Fragments OR Whole Page -