{
    "componentChunkName": "component---src-templates-post-page-index-js",
    "path": "/zoomable-recyclerview-enabling-pinch-to-zoom-and-panning-in-android-recyclerviews/",
    "result": {"data":{"defaultImage":{"childImageSharp":{"fluid":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAME/8QAFwEAAwEAAAAAAAAAAAAAAAAAAAEDBP/aAAwDAQACEAMQAAAByJtdAZ//xAAXEAADAQAAAAAAAAAAAAAAAAABAhIg/9oACAEBAAEFAkWjOf/EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABkQAAEFAAAAAAAAAAAAAAAAAAIAESAhMv/aAAgBAQAGPwKyZaGP/8QAGRABAAIDAAAAAAAAAAAAAAAAAQARICHw/9oACAEBAAE/IQQDW7Z0cf/aAAwDAQACAAMAAAAQDB//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/ED//xAAWEQADAAAAAAAAAAAAAAAAAAABEBH/2gAIAQIBAT8QhX//xAAbEAEAAgIDAAAAAAAAAAAAAAABEVEAICFh0f/aAAgBAQABPxAumKz1gEnii/mv/9k=","aspectRatio":1.9047619047619047,"src":"/static/b9a1fa41d8a11857e973d42dc257e89d/2f1b1/blogs-default-image.jpg","srcSet":"/static/b9a1fa41d8a11857e973d42dc257e89d/fd013/blogs-default-image.jpg 200w,\n/static/b9a1fa41d8a11857e973d42dc257e89d/25252/blogs-default-image.jpg 400w,\n/static/b9a1fa41d8a11857e973d42dc257e89d/2f1b1/blogs-default-image.jpg 800w,\n/static/b9a1fa41d8a11857e973d42dc257e89d/0ff54/blogs-default-image.jpg 1200w,\n/static/b9a1fa41d8a11857e973d42dc257e89d/50fa3/blogs-default-image.jpg 1218w","sizes":"(max-width: 800px) 100vw, 800px"}}},"post":{"id":"cG9zdDoxMTc4Mg==","title":"Zoomable RecyclerView: Enabling Pinch-to-Zoom and Panning in Android RecyclerViews","content":"\n<h2 class=\"wp-block-heading\"><strong>Introduction</strong></h2>\n\n\n\n<p>Android&#8217;s native RecyclerView is exceptionally efficient at handling large datasets through item recycling, but it lacks native support for spatial interactions like pinch-to-zoom and canvas-level panning. For complex layouts—such as interactive retail grids or detailed dashboards—smooth zooming and panning are essential to the user experience.</p>\n\n\n\n<p>To address this limitation, we engineered a custom ZoomableRecyclerView that handles scaling and panning calculations directly at the canvas level, providing a smooth interactive experience without impacting performance. It ships as a small, self-contained open-source library with zero external dependencies and is fully configurable through XML attributes or runtime properties.</p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>What is Zoomable RecyclerView?</strong></h2>\n\n\n\n<p>ZoomableRecyclerView extends the standard Android RecyclerView to add support for multi-touch scaling, double-tap zoom, dynamic translation, and automated kinetic scrolling. Instead of altering the layout hierarchy or structural view properties, it captures user interaction data and applies adjustments directly to the drawing canvas using an affine transformation matrix.</p>\n\n\n\n<p>By shifting the transformation logic into the rendering phase, the underlying item-recycling mechanics and visibility state tracking remain completely unaffected. The layout continues to run efficiently while providing a responsive user experience.</p>\n\n\n\n<figure class=\"wp-block-image size-large\"><span class=\"wp-image-11836 inline-gatsby-image-wrapper gatsby-image-wrapper\" style=\"position:relative;overflow:hidden;max-width:100%;width:1024px\" data-reactroot=\"\"><span aria-hidden=\"true\" style=\"width:100%;padding-bottom:41.40625%\"></span><img aria-hidden=\"true\" src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAIAAAB2/0i6AAAACXBIWXMAAAsTAAALEwEAmpwYAAAB10lEQVR42iXLUVPScAAA8H2JYEiooSlt4SJU5MKNMQbbfwzYBi5A0LCu6zqrj9UH6KGnHniwuzoyKitL1LFAhwhj/NEeW8fd7/WHPH5lTlRfmFtPB6XKIJ83M8IIxMZs+IoOXJPY38j89frsFTUzJt0WiZqUo087LmiHgUzmzkuzumttlts5/nsxfbyT/7OV6VRSRinRLcZ6ZeZSCvQEvMt6+yQ6iDp79vyfq7t2Mx89N7efWaXimRRvxFdrydAeCNf51QYXPOACh6z/N327mcI7iVu9qPMyhhoMehZ3dpDKE9NWrg5L25aaOxfJ+t2bryniTY6tKcxejvmoJj5T2CfiRj2Fa5zXsCfraidcegLVkULBeliwVHW4sQEV4Vx8sB/B3pL4OxKrUdh70veB9u1HFxrU3NeM/1SY77BTbc6l8a5T3nWCSMJoIsONRboLQkdC6IRf1rj7GkfovF8HeEu40xJ9esangdkW59YEd1OcOhLdvxCwDm18BKZpKLMwn4RKHCoMlKmRHLGktaG80peDPZkw8kRbXdKz3uO0+zDr+SF5DhCGGDP3bDC5DPkQFMJQCEGwMgJBCwSGYGkA8IsUZoiL7eyipiw0pZmfkuebMv1FmW78A8pr4aFT2u6FAAAAAElFTkSuQmCC\" alt=\"\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;object-fit:cover;object-position:center;opacity:0;transition-delay:500ms\"/><picture><source srcSet=\"/static/eb02700db95d72cc8eba2090bf1064af/85b06/image_1-scaled.png 256w,\n/static/eb02700db95d72cc8eba2090bf1064af/bc282/image_1-scaled.png 512w,\n/static/eb02700db95d72cc8eba2090bf1064af/f1720/image_1-scaled.png 1024w,\n/static/eb02700db95d72cc8eba2090bf1064af/437a1/image_1-scaled.png 1536w,\n/static/eb02700db95d72cc8eba2090bf1064af/7b24f/image_1-scaled.png 2048w,\n/static/eb02700db95d72cc8eba2090bf1064af/8355f/image_1-scaled.png 2560w\" sizes=\"(max-width: 1024px) 100vw, 1024px\"/><img sizes=\"(max-width: 1024px) 100vw, 1024px\" srcSet=\"/static/eb02700db95d72cc8eba2090bf1064af/85b06/image_1-scaled.png 256w,\n/static/eb02700db95d72cc8eba2090bf1064af/bc282/image_1-scaled.png 512w,\n/static/eb02700db95d72cc8eba2090bf1064af/f1720/image_1-scaled.png 1024w,\n/static/eb02700db95d72cc8eba2090bf1064af/437a1/image_1-scaled.png 1536w,\n/static/eb02700db95d72cc8eba2090bf1064af/7b24f/image_1-scaled.png 2048w,\n/static/eb02700db95d72cc8eba2090bf1064af/8355f/image_1-scaled.png 2560w\" src=\"/static/eb02700db95d72cc8eba2090bf1064af/f1720/image_1-scaled.png\" alt=\"\" loading=\"eager\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;object-fit:cover;object-position:center;opacity:1;transition:opacity 500ms\"/></picture><noscript><picture><source srcset=\"/static/eb02700db95d72cc8eba2090bf1064af/85b06/image_1-scaled.png 256w,\n/static/eb02700db95d72cc8eba2090bf1064af/bc282/image_1-scaled.png 512w,\n/static/eb02700db95d72cc8eba2090bf1064af/f1720/image_1-scaled.png 1024w,\n/static/eb02700db95d72cc8eba2090bf1064af/437a1/image_1-scaled.png 1536w,\n/static/eb02700db95d72cc8eba2090bf1064af/7b24f/image_1-scaled.png 2048w,\n/static/eb02700db95d72cc8eba2090bf1064af/8355f/image_1-scaled.png 2560w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" /><img loading=\"eager\" sizes=\"(max-width: 1024px) 100vw, 1024px\" srcset=\"/static/eb02700db95d72cc8eba2090bf1064af/85b06/image_1-scaled.png 256w,\n/static/eb02700db95d72cc8eba2090bf1064af/bc282/image_1-scaled.png 512w,\n/static/eb02700db95d72cc8eba2090bf1064af/f1720/image_1-scaled.png 1024w,\n/static/eb02700db95d72cc8eba2090bf1064af/437a1/image_1-scaled.png 1536w,\n/static/eb02700db95d72cc8eba2090bf1064af/7b24f/image_1-scaled.png 2048w,\n/static/eb02700db95d72cc8eba2090bf1064af/8355f/image_1-scaled.png 2560w\" src=\"/static/eb02700db95d72cc8eba2090bf1064af/f1720/image_1-scaled.png\" alt=\"\" style=\"position:absolute;top:0;left:0;opacity:1;width:100%;height:100%;object-fit:cover;object-position:center\"/></picture></noscript></span></figure>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Implementation</strong></h2>\n\n\n\n<p>Rather than modifying the structural layout components, the implementation isolates logic across distinct canvas and gesture stages.</p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>1. Canvas Rendering Manipulation</strong></h3>\n\n\n\n<p>To isolate zoom transformations from the layout pass, the matrix transformations are applied during the rendering cycle. Overriding dispatchDraw allows us to intercept the canvas before child views are painted.</p>\n\n\n\n<p>The sequence works as follows: canvas.save() pushes a snapshot of the current canvas state onto a stack. canvas.concat(matrix) then multiplies the canvas&#8217;s existing transformation matrix with our zoom/pan matrix — this is what visually scales and shifts every pixel drawn afterward. Finally, canvas.restore() pops the saved state, ensuring that the parent container&#8217;s coordinate system is completely unaffected by our transformation.</p>\n\n\n\n<figure class=\"wp-block-image size-large\"><span class=\"wp-image-11848 inline-gatsby-image-wrapper gatsby-image-wrapper\" style=\"position:relative;overflow:hidden;max-width:100%;width:1024px\" data-reactroot=\"\"><span aria-hidden=\"true\" style=\"width:100%;padding-bottom:35.15625%\"></span><img aria-hidden=\"true\" src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAIAAACHqfpvAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAuUlEQVR42o2Q6wqCQBCFfZFQ96abmq7bqm2bl4RMgyLs/Z+lif0TgRKcGc6P+Zgz4xDEGAkpCQkO6JcIZrbDwJIcjKjKi2S78za+72IQ8og11q/CHuFxJnUrS9PUndEnJctDeSz2la6MFAr7dBGGwojVTX9/zPPzNQ63runTRGzDmAdRyPjaZjgVuThXujkP4zBdL1Nt2qrUSZRC7BXyA8NXAsojnohUikwCA3euRP2NDTwAVn9iFn4DsWFCVD4KJnUAAAAASUVORK5CYII=\" alt=\"\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;object-fit:cover;object-position:center;opacity:0;transition-delay:500ms\"/><picture><source srcSet=\"/static/e3e0ae036884ed6a3b6d8675f8b7f490/85b06/Code-1-scaled.png 256w,\n/static/e3e0ae036884ed6a3b6d8675f8b7f490/bc282/Code-1-scaled.png 512w,\n/static/e3e0ae036884ed6a3b6d8675f8b7f490/f1720/Code-1-scaled.png 1024w,\n/static/e3e0ae036884ed6a3b6d8675f8b7f490/437a1/Code-1-scaled.png 1536w,\n/static/e3e0ae036884ed6a3b6d8675f8b7f490/7b24f/Code-1-scaled.png 2048w,\n/static/e3e0ae036884ed6a3b6d8675f8b7f490/8355f/Code-1-scaled.png 2560w\" sizes=\"(max-width: 1024px) 100vw, 1024px\"/><img sizes=\"(max-width: 1024px) 100vw, 1024px\" srcSet=\"/static/e3e0ae036884ed6a3b6d8675f8b7f490/85b06/Code-1-scaled.png 256w,\n/static/e3e0ae036884ed6a3b6d8675f8b7f490/bc282/Code-1-scaled.png 512w,\n/static/e3e0ae036884ed6a3b6d8675f8b7f490/f1720/Code-1-scaled.png 1024w,\n/static/e3e0ae036884ed6a3b6d8675f8b7f490/437a1/Code-1-scaled.png 1536w,\n/static/e3e0ae036884ed6a3b6d8675f8b7f490/7b24f/Code-1-scaled.png 2048w,\n/static/e3e0ae036884ed6a3b6d8675f8b7f490/8355f/Code-1-scaled.png 2560w\" src=\"/static/e3e0ae036884ed6a3b6d8675f8b7f490/f1720/Code-1-scaled.png\" alt=\"\" loading=\"eager\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;object-fit:cover;object-position:center;opacity:1;transition:opacity 500ms\"/></picture><noscript><picture><source srcset=\"/static/e3e0ae036884ed6a3b6d8675f8b7f490/85b06/Code-1-scaled.png 256w,\n/static/e3e0ae036884ed6a3b6d8675f8b7f490/bc282/Code-1-scaled.png 512w,\n/static/e3e0ae036884ed6a3b6d8675f8b7f490/f1720/Code-1-scaled.png 1024w,\n/static/e3e0ae036884ed6a3b6d8675f8b7f490/437a1/Code-1-scaled.png 1536w,\n/static/e3e0ae036884ed6a3b6d8675f8b7f490/7b24f/Code-1-scaled.png 2048w,\n/static/e3e0ae036884ed6a3b6d8675f8b7f490/8355f/Code-1-scaled.png 2560w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" /><img loading=\"eager\" sizes=\"(max-width: 1024px) 100vw, 1024px\" srcset=\"/static/e3e0ae036884ed6a3b6d8675f8b7f490/85b06/Code-1-scaled.png 256w,\n/static/e3e0ae036884ed6a3b6d8675f8b7f490/bc282/Code-1-scaled.png 512w,\n/static/e3e0ae036884ed6a3b6d8675f8b7f490/f1720/Code-1-scaled.png 1024w,\n/static/e3e0ae036884ed6a3b6d8675f8b7f490/437a1/Code-1-scaled.png 1536w,\n/static/e3e0ae036884ed6a3b6d8675f8b7f490/7b24f/Code-1-scaled.png 2048w,\n/static/e3e0ae036884ed6a3b6d8675f8b7f490/8355f/Code-1-scaled.png 2560w\" src=\"/static/e3e0ae036884ed6a3b6d8675f8b7f490/f1720/Code-1-scaled.png\" alt=\"\" style=\"position:absolute;top:0;left:0;opacity:1;width:100%;height:100%;object-fit:cover;object-position:center\"/></picture></noscript></span></figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>2. Touch Tracking &amp; Multi-Touch Pointer Stability</strong></h3>\n\n\n\n<p>Touch handling begins with a single guard: when zoom is disabled, the event is handed straight back to the base RecyclerView so it behaves like an ordinary list. Otherwise the event is routed through both the scale and gesture detectors before per-action handling runs.</p>\n\n\n\n<p>Each action type serves a specific role:</p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>ACTION_DOWN</strong> — the first finger touches the screen. We record its coordinates as lastTouchX and lastTouchY. These serve as the baseline for measuring movement in subsequent frames.</li>\n\n\n\n<li><strong>ACTION_MOVE</strong> — the finger moves. We compute the displacement delta since the last recorded position: dx = event.x − lastTouchX and dy = event.y − lastTouchY. This delta is passed to matrix.postTranslate(dx, dy), shifting the canvas by exactly how far the finger moved. We then update lastTouchX/Y so the next frame measures from here. Panning only applies when zoomed in (currentScale &gt; 1f).</li>\n\n\n\n<li><strong>ACTION_POINTER_UP</strong> — a second finger is lifted. Without handling this, event.x/y would suddenly jump to the remaining finger&#8217;s coordinates, causing a visible content snap. We read event.actionIndex to identify which pointer was lifted, then immediately re-anchor lastTouchX/Y to the finger that is still down. This ensures the next ACTION_MOVE frame computes a delta of zero, eliminating the jump.</li>\n\n\n\n<li><strong>ACTION_UP / ACTION_CANCEL</strong> — all fingers lifted. If no drag occurs and scale is at 1x, the event is passed back to the base RecyclerView so normal tap and click handling works as expected.</li>\n</ul>\n\n\n\n<figure class=\"wp-block-image size-large\"><span class=\"wp-image-11920 inline-gatsby-image-wrapper gatsby-image-wrapper\" style=\"position:relative;overflow:hidden;max-width:100%;width:1024px\" data-reactroot=\"\"><span aria-hidden=\"true\" style=\"width:100%;padding-bottom:41.40625%\"></span><img aria-hidden=\"true\" src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAIAAAB2/0i6AAAACXBIWXMAAAsTAAALEwEAmpwYAAAB20lEQVR42hXL61PSAAAA8P0XibzGCQ4odjxSCOSxjb0YbLANxhQf5JndVX9gH83uvE5dZaRRBGTAYMibQR+Tu9/XH4A9UbE1FTWoqElLWIYx8yQKzmP2Ber5lwwsyRd6Gp3nmGlBnMnyeL88Kr8eHb8dH79bAYi1NmFo4sbPkq+6F6wXQ829qLqP9PlQP/V8QMA1Zrsh050TqfXmqPtyt3sotcvlh4PTyeHpGKANf6j1GmVUcPACd3xiNhuU65b0VNiAxgT6SXc9F708YM8F5C+P/cii30q5TkkeyKWpXJoA6fXfjKmaMl6RG2fU0w+0rUZACglfs141HehhUD2PnL+S3nORViZSycSUIqlKmSHPzQVuBmTNd5y5kjJdiLaPR86ztOOWdf1inzV4fzvj6+LOO8pTpX01druZSTZSYr2AqDl0mIrrTGIOCJYb3nKTtSiS7bJoVxhbld5o0o4W7eoSrj662cbcHRzuEd6HZFjDEI0KDumtKe7XHwEFq5K3fhWtFcn1M+9uFL33eW9H9PeErQEfHAmRqbAz48I6G15woeUjOrCIO/U4tALI4FURvC6AXyT7d9FRFaA6B92z7o4U0uTocDex+iQ8JeA5Aeu4R0egRQRchi0r/wHGid+spoXNKwAAAABJRU5ErkJggg==\" alt=\"\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;object-fit:cover;object-position:center;opacity:0;transition-delay:500ms\"/><picture><source srcSet=\"/static/3abfebfeb3b3324d73133aebab68fb04/85b06/image_2-scaled.png 256w,\n/static/3abfebfeb3b3324d73133aebab68fb04/bc282/image_2-scaled.png 512w,\n/static/3abfebfeb3b3324d73133aebab68fb04/f1720/image_2-scaled.png 1024w,\n/static/3abfebfeb3b3324d73133aebab68fb04/437a1/image_2-scaled.png 1536w,\n/static/3abfebfeb3b3324d73133aebab68fb04/7b24f/image_2-scaled.png 2048w,\n/static/3abfebfeb3b3324d73133aebab68fb04/8355f/image_2-scaled.png 2560w\" sizes=\"(max-width: 1024px) 100vw, 1024px\"/><img sizes=\"(max-width: 1024px) 100vw, 1024px\" srcSet=\"/static/3abfebfeb3b3324d73133aebab68fb04/85b06/image_2-scaled.png 256w,\n/static/3abfebfeb3b3324d73133aebab68fb04/bc282/image_2-scaled.png 512w,\n/static/3abfebfeb3b3324d73133aebab68fb04/f1720/image_2-scaled.png 1024w,\n/static/3abfebfeb3b3324d73133aebab68fb04/437a1/image_2-scaled.png 1536w,\n/static/3abfebfeb3b3324d73133aebab68fb04/7b24f/image_2-scaled.png 2048w,\n/static/3abfebfeb3b3324d73133aebab68fb04/8355f/image_2-scaled.png 2560w\" src=\"/static/3abfebfeb3b3324d73133aebab68fb04/f1720/image_2-scaled.png\" alt=\"\" loading=\"eager\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;object-fit:cover;object-position:center;opacity:1;transition:opacity 500ms\"/></picture><noscript><picture><source srcset=\"/static/3abfebfeb3b3324d73133aebab68fb04/85b06/image_2-scaled.png 256w,\n/static/3abfebfeb3b3324d73133aebab68fb04/bc282/image_2-scaled.png 512w,\n/static/3abfebfeb3b3324d73133aebab68fb04/f1720/image_2-scaled.png 1024w,\n/static/3abfebfeb3b3324d73133aebab68fb04/437a1/image_2-scaled.png 1536w,\n/static/3abfebfeb3b3324d73133aebab68fb04/7b24f/image_2-scaled.png 2048w,\n/static/3abfebfeb3b3324d73133aebab68fb04/8355f/image_2-scaled.png 2560w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" /><img loading=\"eager\" sizes=\"(max-width: 1024px) 100vw, 1024px\" srcset=\"/static/3abfebfeb3b3324d73133aebab68fb04/85b06/image_2-scaled.png 256w,\n/static/3abfebfeb3b3324d73133aebab68fb04/bc282/image_2-scaled.png 512w,\n/static/3abfebfeb3b3324d73133aebab68fb04/f1720/image_2-scaled.png 1024w,\n/static/3abfebfeb3b3324d73133aebab68fb04/437a1/image_2-scaled.png 1536w,\n/static/3abfebfeb3b3324d73133aebab68fb04/7b24f/image_2-scaled.png 2048w,\n/static/3abfebfeb3b3324d73133aebab68fb04/8355f/image_2-scaled.png 2560w\" src=\"/static/3abfebfeb3b3324d73133aebab68fb04/f1720/image_2-scaled.png\" alt=\"\" style=\"position:absolute;top:0;left:0;opacity:1;width:100%;height:100%;object-fit:cover;object-position:center\"/></picture></noscript></span></figure>\n\n\n\n<figure class=\"wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-large\"><span class=\"wp-image-11932 inline-gatsby-image-wrapper gatsby-image-wrapper\" style=\"position:relative;overflow:hidden;max-width:100%;width:700px\" data-reactroot=\"\"><span aria-hidden=\"true\" style=\"width:100%;padding-bottom:146.28571428571428%\"></span><img aria-hidden=\"true\" src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAdCAIAAAAl5NuSAAAACXBIWXMAAAsTAAALEwEAmpwYAAADSElEQVR42o1UiXKbMBDNh7Q1BgRCIHEYxH2Zw4AxdtJMO+3/f0gX7Dhuamc689gRx0Pat2/3SRYVTdUVGcNihnSFennyGE9IUrnrqzIWvoniGokr6YJvS1zL0oKH5Lyoi+2uyCsnSXCRGmWu5ynJU1qXlNlYphhRdJcMF3OCoju03TgOh3E6Fd0YN33eDuPhOO6nrj71zckgVBTkO2RpJQc8zJIi9OOARxDDIInDlOmmtEZIVhRZub8zvFaRVubbItsCPwqSNM6zBO7r0I/g7WeCwYVkTDdhmpZlUaVJXm0biIbOFKRJIoLTgmzrOaI7ZICCCOx57KZTd3wZXp6701iPdVxx5vmMQwyt0NKsDwe5kCVBXq+kqmz23ZjF+a7pHNOVBaTK2gKMkaZI+P7OUDDwCYjU1h1oBmnD7d/yIkjhIZkZFsEG0SjRDFhglSgIgz2uOT8kA7gb9NXQFbt+24/1fmoOCU98y+d0Tjs0Aw2R+zkDhJXkRUUSZW21i/ykbweQwNCYKmGgAZCoPtwZOsEPs6Zqu91QJHkRZRuHw+Hh2LDh3YI/XZsJPrKY8+P15/fn13GYjofnKIgNwj7xyfvOM9l0Xr//mA4n7gU6odBnUD8gg2DiEj9o9k6G2jDNtInjGI5NbIaZqVmmZi6w2BJnzW74byaBBpDUpmynbqrTeqiHyIupSs8c+BfFjGHzg+A3JpGwY7lwYEYtzkMYL1+/CMJKXAsSFPmMWbnZLf+QwViBF7q253uh5/AIGpPHrs11lcJ/zyaF1Ob4NqHecwZjpWHRZE0R5PPJt31fdoEdcMZd3XGpuzE23mIYWJx9fqP2GvFk2+32bdPt+0OaFHXdQfF0aFjqKDciX91yWyqUZttfP39DtU7Hl+PhdNwf66qtyrqpO0jk/hi6Ck51FkcpaGZbG1jASABkaVFkJTwRLjU/Q36bYVAnUTGJCbVRRQxm1hVDRzqRiSZpWNLgIUGEwvFnMKbOi8sMwwpRFWLpFre4b/uexV26sXXb0We3QDzDItb8RLdnEBsKBGRZN+xoN7VNHwYx90IYCbM3YeIvnXwD9L5e8p+HPuwMMxBm6Pz1SgZLfz40/57bIjo3HfzojP9hyqLyB0k7LRD+r48sAAAAAElFTkSuQmCC\" alt=\"\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;object-fit:cover;object-position:center;opacity:0;transition-delay:500ms\"/><picture><source srcSet=\"/static/696c4352e59908bea7afc297cf69a3ea/1aaec/Code-2-scaled.png 175w,\n/static/696c4352e59908bea7afc297cf69a3ea/98287/Code-2-scaled.png 350w,\n/static/696c4352e59908bea7afc297cf69a3ea/39600/Code-2-scaled.png 700w,\n/static/696c4352e59908bea7afc297cf69a3ea/57cd1/Code-2-scaled.png 1050w,\n/static/696c4352e59908bea7afc297cf69a3ea/4af54/Code-2-scaled.png 1400w,\n/static/696c4352e59908bea7afc297cf69a3ea/2c607/Code-2-scaled.png 1751w\" sizes=\"(max-width: 700px) 100vw, 700px\"/><img sizes=\"(max-width: 700px) 100vw, 700px\" srcSet=\"/static/696c4352e59908bea7afc297cf69a3ea/1aaec/Code-2-scaled.png 175w,\n/static/696c4352e59908bea7afc297cf69a3ea/98287/Code-2-scaled.png 350w,\n/static/696c4352e59908bea7afc297cf69a3ea/39600/Code-2-scaled.png 700w,\n/static/696c4352e59908bea7afc297cf69a3ea/57cd1/Code-2-scaled.png 1050w,\n/static/696c4352e59908bea7afc297cf69a3ea/4af54/Code-2-scaled.png 1400w,\n/static/696c4352e59908bea7afc297cf69a3ea/2c607/Code-2-scaled.png 1751w\" src=\"/static/696c4352e59908bea7afc297cf69a3ea/39600/Code-2-scaled.png\" alt=\"\" loading=\"eager\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;object-fit:cover;object-position:center;opacity:1;transition:opacity 500ms\"/></picture><noscript><picture><source srcset=\"/static/696c4352e59908bea7afc297cf69a3ea/1aaec/Code-2-scaled.png 175w,\n/static/696c4352e59908bea7afc297cf69a3ea/98287/Code-2-scaled.png 350w,\n/static/696c4352e59908bea7afc297cf69a3ea/39600/Code-2-scaled.png 700w,\n/static/696c4352e59908bea7afc297cf69a3ea/57cd1/Code-2-scaled.png 1050w,\n/static/696c4352e59908bea7afc297cf69a3ea/4af54/Code-2-scaled.png 1400w,\n/static/696c4352e59908bea7afc297cf69a3ea/2c607/Code-2-scaled.png 1751w\" sizes=\"(max-width: 700px) 100vw, 700px\" /><img loading=\"eager\" sizes=\"(max-width: 700px) 100vw, 700px\" srcset=\"/static/696c4352e59908bea7afc297cf69a3ea/1aaec/Code-2-scaled.png 175w,\n/static/696c4352e59908bea7afc297cf69a3ea/98287/Code-2-scaled.png 350w,\n/static/696c4352e59908bea7afc297cf69a3ea/39600/Code-2-scaled.png 700w,\n/static/696c4352e59908bea7afc297cf69a3ea/57cd1/Code-2-scaled.png 1050w,\n/static/696c4352e59908bea7afc297cf69a3ea/4af54/Code-2-scaled.png 1400w,\n/static/696c4352e59908bea7afc297cf69a3ea/2c607/Code-2-scaled.png 1751w\" src=\"/static/696c4352e59908bea7afc297cf69a3ea/39600/Code-2-scaled.png\" alt=\"\" style=\"position:absolute;top:0;left:0;opacity:1;width:100%;height:100%;object-fit:cover;object-position:center\"/></picture></noscript></span></figure>\n</figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>3. Viewport Boundary Clamping</strong></h3>\n\n\n\n<p>When content is scaled up, users can easily pan it entirely out of view. The constrainTranslation method handles viewport containment by first projecting the view&#8217;s physical dimensions through the transformation matrix using matrix.mapRect(drawRect). This gives us the current on-screen bounding box of the transformed canvas. We then compute a correction delta for each axis across three distinct cases:</p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Content smaller than the viewport</strong> (drawRect.width() ≤ viewWidth) — center the content:</li>\n</ul>\n\n\n\n<figure class=\"wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-2 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-large\"><span class=\"wp-image-11944 inline-gatsby-image-wrapper gatsby-image-wrapper\" style=\"position:relative;overflow:hidden;max-width:100%;width:1024px\" data-reactroot=\"\"><span aria-hidden=\"true\" style=\"width:100%;padding-bottom:19.53125%\"></span><img aria-hidden=\"true\" src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAIAAAABPYjBAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAb0lEQVR42mNQUVLT0tBRU9FQUlBRVlRFQUpqcDZQGSZiUFVWt7Kw1tc1VFfV1FDTBJNa6qpaQLaasjqMq4lTs56OgamxuZ2Ng4mRmZmphZWFjaWFjZW5lb6mroWZta21PVAWqAyLZiCGSOByGx4EAJsaJSGc7/fRAAAAAElFTkSuQmCC\" alt=\"\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;object-fit:cover;object-position:center;opacity:0;transition-delay:500ms\"/><picture><source srcSet=\"/static/0b12bc8aa8852968e0b602800320109f/85b06/Code-3-scaled.png 256w,\n/static/0b12bc8aa8852968e0b602800320109f/bc282/Code-3-scaled.png 512w,\n/static/0b12bc8aa8852968e0b602800320109f/f1720/Code-3-scaled.png 1024w,\n/static/0b12bc8aa8852968e0b602800320109f/437a1/Code-3-scaled.png 1536w,\n/static/0b12bc8aa8852968e0b602800320109f/7b24f/Code-3-scaled.png 2048w,\n/static/0b12bc8aa8852968e0b602800320109f/8355f/Code-3-scaled.png 2560w\" sizes=\"(max-width: 1024px) 100vw, 1024px\"/><img sizes=\"(max-width: 1024px) 100vw, 1024px\" srcSet=\"/static/0b12bc8aa8852968e0b602800320109f/85b06/Code-3-scaled.png 256w,\n/static/0b12bc8aa8852968e0b602800320109f/bc282/Code-3-scaled.png 512w,\n/static/0b12bc8aa8852968e0b602800320109f/f1720/Code-3-scaled.png 1024w,\n/static/0b12bc8aa8852968e0b602800320109f/437a1/Code-3-scaled.png 1536w,\n/static/0b12bc8aa8852968e0b602800320109f/7b24f/Code-3-scaled.png 2048w,\n/static/0b12bc8aa8852968e0b602800320109f/8355f/Code-3-scaled.png 2560w\" src=\"/static/0b12bc8aa8852968e0b602800320109f/f1720/Code-3-scaled.png\" alt=\"\" loading=\"eager\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;object-fit:cover;object-position:center;opacity:1;transition:opacity 500ms\"/></picture><noscript><picture><source srcset=\"/static/0b12bc8aa8852968e0b602800320109f/85b06/Code-3-scaled.png 256w,\n/static/0b12bc8aa8852968e0b602800320109f/bc282/Code-3-scaled.png 512w,\n/static/0b12bc8aa8852968e0b602800320109f/f1720/Code-3-scaled.png 1024w,\n/static/0b12bc8aa8852968e0b602800320109f/437a1/Code-3-scaled.png 1536w,\n/static/0b12bc8aa8852968e0b602800320109f/7b24f/Code-3-scaled.png 2048w,\n/static/0b12bc8aa8852968e0b602800320109f/8355f/Code-3-scaled.png 2560w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" /><img loading=\"eager\" sizes=\"(max-width: 1024px) 100vw, 1024px\" srcset=\"/static/0b12bc8aa8852968e0b602800320109f/85b06/Code-3-scaled.png 256w,\n/static/0b12bc8aa8852968e0b602800320109f/bc282/Code-3-scaled.png 512w,\n/static/0b12bc8aa8852968e0b602800320109f/f1720/Code-3-scaled.png 1024w,\n/static/0b12bc8aa8852968e0b602800320109f/437a1/Code-3-scaled.png 1536w,\n/static/0b12bc8aa8852968e0b602800320109f/7b24f/Code-3-scaled.png 2048w,\n/static/0b12bc8aa8852968e0b602800320109f/8355f/Code-3-scaled.png 2560w\" src=\"/static/0b12bc8aa8852968e0b602800320109f/f1720/Code-3-scaled.png\" alt=\"\" style=\"position:absolute;top:0;left:0;opacity:1;width:100%;height:100%;object-fit:cover;object-position:center\"/></picture></noscript></span></figure>\n</figure>\n\n\n\n<p>The first term finds the left offset needed to center the content; subtracting drawRect.left converts it into a relative correction from the canvas&#8217;s current position.</p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Left edge overscrolled right</strong> (drawRect.left &gt; 0) — the content&#8217;s left edge has drifted past the screen&#8217;s left border, leaving empty space on the left. Push it back flush:</li>\n</ul>\n\n\n\n<figure class=\"wp-block-image size-large\"><span class=\"wp-image-11956 inline-gatsby-image-wrapper gatsby-image-wrapper\" style=\"position:relative;overflow:hidden;max-width:100%;width:1024px\" data-reactroot=\"\"><span aria-hidden=\"true\" style=\"width:100%;padding-bottom:18.75%\"></span><img aria-hidden=\"true\" src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAIAAAABPYjBAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAR0lEQVR42mPQ1tTVUNNSVlRVUVIjFTFYmFvp6RgoKagAOaqkagbarK9raG1pY2ttb2luraqsToJmNRUNdVVNoMuBCMgmyWYA7G0jaQP9OMoAAAAASUVORK5CYII=\" alt=\"\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;object-fit:cover;object-position:center;opacity:0;transition-delay:500ms\"/><picture><source srcSet=\"/static/f31727c3d90fbe0dd2cc7cf50c371666/85b06/Code-4-scaled.png 256w,\n/static/f31727c3d90fbe0dd2cc7cf50c371666/bc282/Code-4-scaled.png 512w,\n/static/f31727c3d90fbe0dd2cc7cf50c371666/f1720/Code-4-scaled.png 1024w,\n/static/f31727c3d90fbe0dd2cc7cf50c371666/437a1/Code-4-scaled.png 1536w,\n/static/f31727c3d90fbe0dd2cc7cf50c371666/7b24f/Code-4-scaled.png 2048w,\n/static/f31727c3d90fbe0dd2cc7cf50c371666/8355f/Code-4-scaled.png 2560w\" sizes=\"(max-width: 1024px) 100vw, 1024px\"/><img sizes=\"(max-width: 1024px) 100vw, 1024px\" srcSet=\"/static/f31727c3d90fbe0dd2cc7cf50c371666/85b06/Code-4-scaled.png 256w,\n/static/f31727c3d90fbe0dd2cc7cf50c371666/bc282/Code-4-scaled.png 512w,\n/static/f31727c3d90fbe0dd2cc7cf50c371666/f1720/Code-4-scaled.png 1024w,\n/static/f31727c3d90fbe0dd2cc7cf50c371666/437a1/Code-4-scaled.png 1536w,\n/static/f31727c3d90fbe0dd2cc7cf50c371666/7b24f/Code-4-scaled.png 2048w,\n/static/f31727c3d90fbe0dd2cc7cf50c371666/8355f/Code-4-scaled.png 2560w\" src=\"/static/f31727c3d90fbe0dd2cc7cf50c371666/f1720/Code-4-scaled.png\" alt=\"\" loading=\"eager\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;object-fit:cover;object-position:center;opacity:1;transition:opacity 500ms\"/></picture><noscript><picture><source srcset=\"/static/f31727c3d90fbe0dd2cc7cf50c371666/85b06/Code-4-scaled.png 256w,\n/static/f31727c3d90fbe0dd2cc7cf50c371666/bc282/Code-4-scaled.png 512w,\n/static/f31727c3d90fbe0dd2cc7cf50c371666/f1720/Code-4-scaled.png 1024w,\n/static/f31727c3d90fbe0dd2cc7cf50c371666/437a1/Code-4-scaled.png 1536w,\n/static/f31727c3d90fbe0dd2cc7cf50c371666/7b24f/Code-4-scaled.png 2048w,\n/static/f31727c3d90fbe0dd2cc7cf50c371666/8355f/Code-4-scaled.png 2560w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" /><img loading=\"eager\" sizes=\"(max-width: 1024px) 100vw, 1024px\" srcset=\"/static/f31727c3d90fbe0dd2cc7cf50c371666/85b06/Code-4-scaled.png 256w,\n/static/f31727c3d90fbe0dd2cc7cf50c371666/bc282/Code-4-scaled.png 512w,\n/static/f31727c3d90fbe0dd2cc7cf50c371666/f1720/Code-4-scaled.png 1024w,\n/static/f31727c3d90fbe0dd2cc7cf50c371666/437a1/Code-4-scaled.png 1536w,\n/static/f31727c3d90fbe0dd2cc7cf50c371666/7b24f/Code-4-scaled.png 2048w,\n/static/f31727c3d90fbe0dd2cc7cf50c371666/8355f/Code-4-scaled.png 2560w\" src=\"/static/f31727c3d90fbe0dd2cc7cf50c371666/f1720/Code-4-scaled.png\" alt=\"\" style=\"position:absolute;top:0;left:0;opacity:1;width:100%;height:100%;object-fit:cover;object-position:center\"/></picture></noscript></span></figure>\n\n\n\n<p>Right edge overscrolled left (drawRect.right &lt; viewWidth) — the content&#8217;s right edge has been panned inside the screen, leaving empty space on the right. Push it back flush:</p>\n\n\n\n<figure class=\"wp-block-image size-large\"><span class=\"wp-image-11968 inline-gatsby-image-wrapper gatsby-image-wrapper\" style=\"position:relative;overflow:hidden;max-width:100%;width:1024px\" data-reactroot=\"\"><span aria-hidden=\"true\" style=\"width:100%;padding-bottom:18.75%\"></span><img aria-hidden=\"true\" src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAIAAAABPYjBAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAVklEQVR42mPQ0tDRUNNSVlRVUVIjFTFYmFka6BkBNaupaMBFVZXVidKspaFtqG9sa21vbWlrZGBia21nY2VnYWZFjFsYgBaqq2oCEZABREAvQNjE2AwAPrgkPS+3VBQAAAAASUVORK5CYII=\" alt=\"\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;object-fit:cover;object-position:center;opacity:0;transition-delay:500ms\"/><picture><source srcSet=\"/static/0bc605e88a3f99b488793064c1758320/85b06/Code-5-scaled.png 256w,\n/static/0bc605e88a3f99b488793064c1758320/bc282/Code-5-scaled.png 512w,\n/static/0bc605e88a3f99b488793064c1758320/f1720/Code-5-scaled.png 1024w,\n/static/0bc605e88a3f99b488793064c1758320/437a1/Code-5-scaled.png 1536w,\n/static/0bc605e88a3f99b488793064c1758320/7b24f/Code-5-scaled.png 2048w,\n/static/0bc605e88a3f99b488793064c1758320/8355f/Code-5-scaled.png 2560w\" sizes=\"(max-width: 1024px) 100vw, 1024px\"/><img sizes=\"(max-width: 1024px) 100vw, 1024px\" srcSet=\"/static/0bc605e88a3f99b488793064c1758320/85b06/Code-5-scaled.png 256w,\n/static/0bc605e88a3f99b488793064c1758320/bc282/Code-5-scaled.png 512w,\n/static/0bc605e88a3f99b488793064c1758320/f1720/Code-5-scaled.png 1024w,\n/static/0bc605e88a3f99b488793064c1758320/437a1/Code-5-scaled.png 1536w,\n/static/0bc605e88a3f99b488793064c1758320/7b24f/Code-5-scaled.png 2048w,\n/static/0bc605e88a3f99b488793064c1758320/8355f/Code-5-scaled.png 2560w\" src=\"/static/0bc605e88a3f99b488793064c1758320/f1720/Code-5-scaled.png\" alt=\"\" loading=\"eager\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;object-fit:cover;object-position:center;opacity:1;transition:opacity 500ms\"/></picture><noscript><picture><source srcset=\"/static/0bc605e88a3f99b488793064c1758320/85b06/Code-5-scaled.png 256w,\n/static/0bc605e88a3f99b488793064c1758320/bc282/Code-5-scaled.png 512w,\n/static/0bc605e88a3f99b488793064c1758320/f1720/Code-5-scaled.png 1024w,\n/static/0bc605e88a3f99b488793064c1758320/437a1/Code-5-scaled.png 1536w,\n/static/0bc605e88a3f99b488793064c1758320/7b24f/Code-5-scaled.png 2048w,\n/static/0bc605e88a3f99b488793064c1758320/8355f/Code-5-scaled.png 2560w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" /><img loading=\"eager\" sizes=\"(max-width: 1024px) 100vw, 1024px\" srcset=\"/static/0bc605e88a3f99b488793064c1758320/85b06/Code-5-scaled.png 256w,\n/static/0bc605e88a3f99b488793064c1758320/bc282/Code-5-scaled.png 512w,\n/static/0bc605e88a3f99b488793064c1758320/f1720/Code-5-scaled.png 1024w,\n/static/0bc605e88a3f99b488793064c1758320/437a1/Code-5-scaled.png 1536w,\n/static/0bc605e88a3f99b488793064c1758320/7b24f/Code-5-scaled.png 2048w,\n/static/0bc605e88a3f99b488793064c1758320/8355f/Code-5-scaled.png 2560w\" src=\"/static/0bc605e88a3f99b488793064c1758320/f1720/Code-5-scaled.png\" alt=\"\" style=\"position:absolute;top:0;left:0;opacity:1;width:100%;height:100%;object-fit:cover;object-position:center\"/></picture></noscript></span></figure>\n\n\n\n<p>The same three cases apply identically along the Y axis.</p>\n\n\n\n<figure class=\"wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-3 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-large\"><span class=\"wp-image-12004 inline-gatsby-image-wrapper gatsby-image-wrapper\" style=\"position:relative;overflow:hidden;max-width:100%;width:1024px\" data-reactroot=\"\"><span aria-hidden=\"true\" style=\"width:100%;padding-bottom:50.78125%\"></span><img aria-hidden=\"true\" src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAIAAAA7N+mxAAAACXBIWXMAAAsTAAALEwEAmpwYAAACZklEQVR42g3L608SAQAA8PsLcrMQlDMQxkW8X8edPOJOOvF4HnHAIYKPaG62let/6ot96EPNyWqNajnUMBjOkhJDUMTX8bgD/Va/7z8gs9rOvGQzL64XV67Tz9i5+U4s3gsHeD8xeIwOMOMNprl1QrcOycAB9uyitmPkChNeTgkv8JEW8H+m04cLqeqr1ZOV5eZctDlLsxRxOmPd9yB5D1yySst2edMiLmmHszi0TWp37WNFv6LhFraApeftdKLMhPK0r5gK7KXCJ0z4isJr06aCWfreIskZxXmbrGYUbSrvrJkEG7Dok1WUp5RVQnQKpJ52U3TB71pHNbll1/pisEb72ajrMGjeIqE1M5gzg1t22ZF5dFM19EY/nLUJs0/kGwn1nme0DkTjPSZQDOM5N5xnsO0kWac9V/7JY0L/3TT+1gh+NIHfHLI/8Ohn1dBrw913FkHWOfaFVlV84ipA+XohdyOI1ampZghrUfg5NcV6kTO3rgJPbCGSH+j9Mi7/6wB3Lfc+oIKvNsGmS7gTURyEwApA2jmvk0+G+ESAX4jwsRmOgDmfjU9M83GcZ/BeEmt7lRf+B63U5Nk80lhCahm0yih/UeI9wK3jCAMXsHERnAs/4nwo59ZzhK7nh7txrBNBWa/6wiNrkrLGrKWego8WLb+XLAcxWTkyXgKc8r5D1ndBvFvNE1p+Ws+TJs5r7M7oOqSOJdWXPlUr+LAZhI4pxSENVRjoZ2yiFJMU4tICMDl+g4I3mGJAaPqksR+w8kGkF0K6FNKhYDZkuKTN57ThNKqpxbWHSV1lwbCfhIqMZCch3fkHj1YPiDkr9TEAAAAASUVORK5CYII=\" alt=\"\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;object-fit:cover;object-position:center;opacity:0;transition-delay:500ms\"/><picture><source srcSet=\"/static/aa300622e8b53b03e9d270163c7d8110/85b06/image_3-scaled.png 256w,\n/static/aa300622e8b53b03e9d270163c7d8110/bc282/image_3-scaled.png 512w,\n/static/aa300622e8b53b03e9d270163c7d8110/f1720/image_3-scaled.png 1024w,\n/static/aa300622e8b53b03e9d270163c7d8110/437a1/image_3-scaled.png 1536w,\n/static/aa300622e8b53b03e9d270163c7d8110/7b24f/image_3-scaled.png 2048w,\n/static/aa300622e8b53b03e9d270163c7d8110/8355f/image_3-scaled.png 2560w\" sizes=\"(max-width: 1024px) 100vw, 1024px\"/><img sizes=\"(max-width: 1024px) 100vw, 1024px\" srcSet=\"/static/aa300622e8b53b03e9d270163c7d8110/85b06/image_3-scaled.png 256w,\n/static/aa300622e8b53b03e9d270163c7d8110/bc282/image_3-scaled.png 512w,\n/static/aa300622e8b53b03e9d270163c7d8110/f1720/image_3-scaled.png 1024w,\n/static/aa300622e8b53b03e9d270163c7d8110/437a1/image_3-scaled.png 1536w,\n/static/aa300622e8b53b03e9d270163c7d8110/7b24f/image_3-scaled.png 2048w,\n/static/aa300622e8b53b03e9d270163c7d8110/8355f/image_3-scaled.png 2560w\" src=\"/static/aa300622e8b53b03e9d270163c7d8110/f1720/image_3-scaled.png\" alt=\"\" loading=\"eager\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;object-fit:cover;object-position:center;opacity:1;transition:opacity 500ms\"/></picture><noscript><picture><source srcset=\"/static/aa300622e8b53b03e9d270163c7d8110/85b06/image_3-scaled.png 256w,\n/static/aa300622e8b53b03e9d270163c7d8110/bc282/image_3-scaled.png 512w,\n/static/aa300622e8b53b03e9d270163c7d8110/f1720/image_3-scaled.png 1024w,\n/static/aa300622e8b53b03e9d270163c7d8110/437a1/image_3-scaled.png 1536w,\n/static/aa300622e8b53b03e9d270163c7d8110/7b24f/image_3-scaled.png 2048w,\n/static/aa300622e8b53b03e9d270163c7d8110/8355f/image_3-scaled.png 2560w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" /><img loading=\"eager\" sizes=\"(max-width: 1024px) 100vw, 1024px\" srcset=\"/static/aa300622e8b53b03e9d270163c7d8110/85b06/image_3-scaled.png 256w,\n/static/aa300622e8b53b03e9d270163c7d8110/bc282/image_3-scaled.png 512w,\n/static/aa300622e8b53b03e9d270163c7d8110/f1720/image_3-scaled.png 1024w,\n/static/aa300622e8b53b03e9d270163c7d8110/437a1/image_3-scaled.png 1536w,\n/static/aa300622e8b53b03e9d270163c7d8110/7b24f/image_3-scaled.png 2048w,\n/static/aa300622e8b53b03e9d270163c7d8110/8355f/image_3-scaled.png 2560w\" src=\"/static/aa300622e8b53b03e9d270163c7d8110/f1720/image_3-scaled.png\" alt=\"\" style=\"position:absolute;top:0;left:0;opacity:1;width:100%;height:100%;object-fit:cover;object-position:center\"/></picture></noscript></span></figure>\n</figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><span class=\"wp-image-12016 inline-gatsby-image-wrapper gatsby-image-wrapper\" style=\"position:relative;overflow:hidden;max-width:100%;width:1024px\" data-reactroot=\"\"><span aria-hidden=\"true\" style=\"width:100%;padding-bottom:78.90625%\"></span><img aria-hidden=\"true\" src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAIAAACZeshMAAAACXBIWXMAAAsTAAALEwEAmpwYAAACOklEQVR42o1T7XKbMBDMi7QJCCEJBEhCfMpgA3EanObDTtq+/5t0jd3Ynf7pzHJzgrvbuz1xE/jMKBtz6XsB8Si5W6xHKWHXCPzwX9zgUbrgIvE9yqkQQvIwEixGrbuv/u0XDxbwl4qfuCQnunp8eX9+/XjbfzwP9++vh58fv+6H7aruxn5cu83QjZInnEYijKNQChqdk1EmJKx365Vb9/3YFvWq7Wvb1KpudN0aOBVsIQstlImMjXMd6QszWkpVUZatqVdZahgVkZAqMyHl8BOZcRbFUZKlOkkULCch+UzOTTlND2+vh+3mYR6+qURrZUtbySi1puxXfWnr0ja5LgBrCknFmZn6oZFmcuP702E/v23dGFMBzfANE+WmWHdD53qVGmgeBtxf1vEnmbCUpZhqNzzuxnl0Y5FXfbdBNOJ0lrumgwV559ZtvcIi/lI7DmOdFta6NExSngUeRRpsQJjmkmI3SxdH+Mc0erVnBIWcyyDgJOB3tz4yAe+WHEtAzuV4enPC6f2ZOSC8adfb7dxPM5pEwxDm6GQGfl22OKJz9FzmVV05IxUjDO3cYE+ImDbT/DC3lcuVlVyyUEDqmCcyTjFtVTSpVLFIcIvhIICemQlDG4WtD4cfT7vnabjPFzYwQ/O+7fcv+938HZo3VduUrshL4l3dbZTRpspMhcKgAsNCK2nAVZQmPIaD2xKjG37E5ceAhji7ZZ6mcui8KVsMAmFOl89fFkMW5a7/ijMzVr/IxoKrD/+D31w2qXoQ3ybmAAAAAElFTkSuQmCC\" alt=\"\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;object-fit:cover;object-position:center;opacity:0;transition-delay:500ms\"/><picture><source srcSet=\"/static/ce65ad73904158565842a653f6eb6b19/85b06/Code-6-scaled.png 256w,\n/static/ce65ad73904158565842a653f6eb6b19/bc282/Code-6-scaled.png 512w,\n/static/ce65ad73904158565842a653f6eb6b19/f1720/Code-6-scaled.png 1024w,\n/static/ce65ad73904158565842a653f6eb6b19/437a1/Code-6-scaled.png 1536w,\n/static/ce65ad73904158565842a653f6eb6b19/7b24f/Code-6-scaled.png 2048w,\n/static/ce65ad73904158565842a653f6eb6b19/8355f/Code-6-scaled.png 2560w\" sizes=\"(max-width: 1024px) 100vw, 1024px\"/><img sizes=\"(max-width: 1024px) 100vw, 1024px\" srcSet=\"/static/ce65ad73904158565842a653f6eb6b19/85b06/Code-6-scaled.png 256w,\n/static/ce65ad73904158565842a653f6eb6b19/bc282/Code-6-scaled.png 512w,\n/static/ce65ad73904158565842a653f6eb6b19/f1720/Code-6-scaled.png 1024w,\n/static/ce65ad73904158565842a653f6eb6b19/437a1/Code-6-scaled.png 1536w,\n/static/ce65ad73904158565842a653f6eb6b19/7b24f/Code-6-scaled.png 2048w,\n/static/ce65ad73904158565842a653f6eb6b19/8355f/Code-6-scaled.png 2560w\" src=\"/static/ce65ad73904158565842a653f6eb6b19/f1720/Code-6-scaled.png\" alt=\"\" loading=\"eager\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;object-fit:cover;object-position:center;opacity:1;transition:opacity 500ms\"/></picture><noscript><picture><source srcset=\"/static/ce65ad73904158565842a653f6eb6b19/85b06/Code-6-scaled.png 256w,\n/static/ce65ad73904158565842a653f6eb6b19/bc282/Code-6-scaled.png 512w,\n/static/ce65ad73904158565842a653f6eb6b19/f1720/Code-6-scaled.png 1024w,\n/static/ce65ad73904158565842a653f6eb6b19/437a1/Code-6-scaled.png 1536w,\n/static/ce65ad73904158565842a653f6eb6b19/7b24f/Code-6-scaled.png 2048w,\n/static/ce65ad73904158565842a653f6eb6b19/8355f/Code-6-scaled.png 2560w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" /><img loading=\"eager\" sizes=\"(max-width: 1024px) 100vw, 1024px\" srcset=\"/static/ce65ad73904158565842a653f6eb6b19/85b06/Code-6-scaled.png 256w,\n/static/ce65ad73904158565842a653f6eb6b19/bc282/Code-6-scaled.png 512w,\n/static/ce65ad73904158565842a653f6eb6b19/f1720/Code-6-scaled.png 1024w,\n/static/ce65ad73904158565842a653f6eb6b19/437a1/Code-6-scaled.png 1536w,\n/static/ce65ad73904158565842a653f6eb6b19/7b24f/Code-6-scaled.png 2048w,\n/static/ce65ad73904158565842a653f6eb6b19/8355f/Code-6-scaled.png 2560w\" src=\"/static/ce65ad73904158565842a653f6eb6b19/f1720/Code-6-scaled.png\" alt=\"\" style=\"position:absolute;top:0;left:0;opacity:1;width:100%;height:100%;object-fit:cover;object-position:center\"/></picture></noscript></span></figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>4. Focal-Point Scaling</strong></h3>\n\n\n\n<p>Standard matrix scaling operations default to the top-left origin (0, 0), which makes content appear to zoom toward the corner rather than under the user&#8217;s fingers. By hooking into the native ScaleGestureDetector, we use matrix.postScale(sx, sy, px, py) where px and py are the focal point coordinates from detector.focusX/focusY — the midpoint between the two active fingers.</p>\n\n\n\n<p>Under the hood, postScale(sx, sy, px, py) is equivalent to three sequential operations:</p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>translate(−px, −py) → move the focal point to the origin</li>\n\n\n\n<li>scale(sx, sy) → apply the scale around the origin</li>\n\n\n\n<li>translate(+px, +py) → move the focal point back to its original position</li>\n</ol>\n\n\n\n<figure class=\"wp-block-image size-large\"><span class=\"wp-image-12028 inline-gatsby-image-wrapper gatsby-image-wrapper\" style=\"position:relative;overflow:hidden;max-width:100%;width:1024px\" data-reactroot=\"\"><span aria-hidden=\"true\" style=\"width:100%;padding-bottom:41.40625%\"></span><img aria-hidden=\"true\" src=\"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAIABQDASIAAhEBAxEB/8QAFwABAAMAAAAAAAAAAAAAAAAAAAIDBP/EABYBAQEBAAAAAAAAAAAAAAAAAAACBf/aAAwDAQACEAMQAAABwTNRYE//xAAWEAEBAQAAAAAAAAAAAAAAAAAAEiH/2gAIAQEAAQUCap//xAAVEQEBAAAAAAAAAAAAAAAAAAABEP/aAAgBAwEBPwFn/8QAFhEBAQEAAAAAAAAAAAAAAAAAAAES/9oACAECAQE/AWY//8QAFhAAAwAAAAAAAAAAAAAAAAAAABAh/9oACAEBAAY/AlT/xAAXEAEBAQEAAAAAAAAAAAAAAAABEQAh/9oACAEBAAE/IQcIscSdV3//2gAMAwEAAgADAAAAEHPv/8QAFhEBAQEAAAAAAAAAAAAAAAAAAAER/9oACAEDAQE/EJZH/8QAFhEBAQEAAAAAAAAAAAAAAAAAASEQ/9oACAECAQE/ECly/8QAGhAAAgMBAQAAAAAAAAAAAAAAETEAASFhcf/aAAgBAQABPxADL8sKKiVil4OhP//Z\" alt=\"\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;object-fit:cover;object-position:center;opacity:0;transition-delay:500ms\"/><picture><source srcSet=\"/static/72b3c606a1b6681a40f2881201f57499/b95e4/image_4-2-scaled.jpg 256w,\n/static/72b3c606a1b6681a40f2881201f57499/1779b/image_4-2-scaled.jpg 512w,\n/static/72b3c606a1b6681a40f2881201f57499/87945/image_4-2-scaled.jpg 1024w,\n/static/72b3c606a1b6681a40f2881201f57499/6afe2/image_4-2-scaled.jpg 1536w,\n/static/72b3c606a1b6681a40f2881201f57499/7a411/image_4-2-scaled.jpg 2048w,\n/static/72b3c606a1b6681a40f2881201f57499/bb9a8/image_4-2-scaled.jpg 2560w\" sizes=\"(max-width: 1024px) 100vw, 1024px\"/><img sizes=\"(max-width: 1024px) 100vw, 1024px\" srcSet=\"/static/72b3c606a1b6681a40f2881201f57499/b95e4/image_4-2-scaled.jpg 256w,\n/static/72b3c606a1b6681a40f2881201f57499/1779b/image_4-2-scaled.jpg 512w,\n/static/72b3c606a1b6681a40f2881201f57499/87945/image_4-2-scaled.jpg 1024w,\n/static/72b3c606a1b6681a40f2881201f57499/6afe2/image_4-2-scaled.jpg 1536w,\n/static/72b3c606a1b6681a40f2881201f57499/7a411/image_4-2-scaled.jpg 2048w,\n/static/72b3c606a1b6681a40f2881201f57499/bb9a8/image_4-2-scaled.jpg 2560w\" src=\"/static/72b3c606a1b6681a40f2881201f57499/87945/image_4-2-scaled.jpg\" alt=\"\" loading=\"eager\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;object-fit:cover;object-position:center;opacity:1;transition:opacity 500ms\"/></picture><noscript><picture><source srcset=\"/static/72b3c606a1b6681a40f2881201f57499/b95e4/image_4-2-scaled.jpg 256w,\n/static/72b3c606a1b6681a40f2881201f57499/1779b/image_4-2-scaled.jpg 512w,\n/static/72b3c606a1b6681a40f2881201f57499/87945/image_4-2-scaled.jpg 1024w,\n/static/72b3c606a1b6681a40f2881201f57499/6afe2/image_4-2-scaled.jpg 1536w,\n/static/72b3c606a1b6681a40f2881201f57499/7a411/image_4-2-scaled.jpg 2048w,\n/static/72b3c606a1b6681a40f2881201f57499/bb9a8/image_4-2-scaled.jpg 2560w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" /><img loading=\"eager\" sizes=\"(max-width: 1024px) 100vw, 1024px\" srcset=\"/static/72b3c606a1b6681a40f2881201f57499/b95e4/image_4-2-scaled.jpg 256w,\n/static/72b3c606a1b6681a40f2881201f57499/1779b/image_4-2-scaled.jpg 512w,\n/static/72b3c606a1b6681a40f2881201f57499/87945/image_4-2-scaled.jpg 1024w,\n/static/72b3c606a1b6681a40f2881201f57499/6afe2/image_4-2-scaled.jpg 1536w,\n/static/72b3c606a1b6681a40f2881201f57499/7a411/image_4-2-scaled.jpg 2048w,\n/static/72b3c606a1b6681a40f2881201f57499/bb9a8/image_4-2-scaled.jpg 2560w\" src=\"/static/72b3c606a1b6681a40f2881201f57499/87945/image_4-2-scaled.jpg\" alt=\"\" style=\"position:absolute;top:0;left:0;opacity:1;width:100%;height:100%;object-fit:cover;object-position:center\"/></picture></noscript></span></figure>\n\n\n\n<p>This makes the zoom appear to radiate outward from exactly where the fingers are, rather than from a fixed corner. The new scale is only committed when it stays within the configurable minScale..maxScale range.</p>\n\n\n\n<figure class=\"wp-block-image size-large\"><span class=\"wp-image-12064 inline-gatsby-image-wrapper gatsby-image-wrapper\" style=\"position:relative;overflow:hidden;max-width:100%;width:1024px\" data-reactroot=\"\"><span aria-hidden=\"true\" style=\"width:100%;padding-bottom:68.359375%\"></span><img aria-hidden=\"true\" src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAIAAACgpqunAAAACXBIWXMAAAsTAAALEwEAmpwYAAABrUlEQVR42pWSaXKjMBCFOUnGZhESYpHARkLsi3EIEEgmy/1vMj0hcSX+kclUPalUKn3dXU9Psy2CkWPsLVNHmz6fv5cWeJzzow6AYYOQiUGWYes7EwSFth2eWrp9DRPiqapXeSOzOiu7tu66tldJ5jr+Jt9lxKb7nbHf6Vuhy2gajC1kWt3OzbiO0/qwPD4/vS7zui6PL0+v99M6T8vQD4IXgtUB5dgk2CIfsIkZYYms5uGhb88yVmVe1WVT5nVbn+KDpNiVXCqeJixNuRJ+zB2+NdccRCMaZZGqVHWMhEt9FkSHSIAXzA+FUHDjYz+knFMe0TByI8ei7zCxHN+GaklbdEVaySgr0yoVWZ4UTd4GlGEDw6g27AZBXz3TwFgbOQiRqZ+W8/3cz+uwvp3npZ/hZqhvx3YcmmFs7+QhAecAeYcd7GaqkHFSlY0UigWh77HjQXguMwwEdqI32YhAA2ThL523VOi/jKponn+/jMPUd+dTe3aJb3x8zGddwyD47STJu/oEnWGqLST/ThgsiJTH4yCMqe3ubvQfZvMvDMEG+BLpixk/gv/r9RX8B59ZlBKxV+zlAAAAAElFTkSuQmCC\" alt=\"\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;object-fit:cover;object-position:center;opacity:0;transition-delay:500ms\"/><picture><source srcSet=\"/static/0e0f40fdf85a6cf920bc544f03a40f44/85b06/Code-7-2-scaled.png 256w,\n/static/0e0f40fdf85a6cf920bc544f03a40f44/bc282/Code-7-2-scaled.png 512w,\n/static/0e0f40fdf85a6cf920bc544f03a40f44/f1720/Code-7-2-scaled.png 1024w,\n/static/0e0f40fdf85a6cf920bc544f03a40f44/437a1/Code-7-2-scaled.png 1536w,\n/static/0e0f40fdf85a6cf920bc544f03a40f44/7b24f/Code-7-2-scaled.png 2048w,\n/static/0e0f40fdf85a6cf920bc544f03a40f44/8355f/Code-7-2-scaled.png 2560w\" sizes=\"(max-width: 1024px) 100vw, 1024px\"/><img sizes=\"(max-width: 1024px) 100vw, 1024px\" srcSet=\"/static/0e0f40fdf85a6cf920bc544f03a40f44/85b06/Code-7-2-scaled.png 256w,\n/static/0e0f40fdf85a6cf920bc544f03a40f44/bc282/Code-7-2-scaled.png 512w,\n/static/0e0f40fdf85a6cf920bc544f03a40f44/f1720/Code-7-2-scaled.png 1024w,\n/static/0e0f40fdf85a6cf920bc544f03a40f44/437a1/Code-7-2-scaled.png 1536w,\n/static/0e0f40fdf85a6cf920bc544f03a40f44/7b24f/Code-7-2-scaled.png 2048w,\n/static/0e0f40fdf85a6cf920bc544f03a40f44/8355f/Code-7-2-scaled.png 2560w\" src=\"/static/0e0f40fdf85a6cf920bc544f03a40f44/f1720/Code-7-2-scaled.png\" alt=\"\" loading=\"eager\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;object-fit:cover;object-position:center;opacity:1;transition:opacity 500ms\"/></picture><noscript><picture><source srcset=\"/static/0e0f40fdf85a6cf920bc544f03a40f44/85b06/Code-7-2-scaled.png 256w,\n/static/0e0f40fdf85a6cf920bc544f03a40f44/bc282/Code-7-2-scaled.png 512w,\n/static/0e0f40fdf85a6cf920bc544f03a40f44/f1720/Code-7-2-scaled.png 1024w,\n/static/0e0f40fdf85a6cf920bc544f03a40f44/437a1/Code-7-2-scaled.png 1536w,\n/static/0e0f40fdf85a6cf920bc544f03a40f44/7b24f/Code-7-2-scaled.png 2048w,\n/static/0e0f40fdf85a6cf920bc544f03a40f44/8355f/Code-7-2-scaled.png 2560w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" /><img loading=\"eager\" sizes=\"(max-width: 1024px) 100vw, 1024px\" srcset=\"/static/0e0f40fdf85a6cf920bc544f03a40f44/85b06/Code-7-2-scaled.png 256w,\n/static/0e0f40fdf85a6cf920bc544f03a40f44/bc282/Code-7-2-scaled.png 512w,\n/static/0e0f40fdf85a6cf920bc544f03a40f44/f1720/Code-7-2-scaled.png 1024w,\n/static/0e0f40fdf85a6cf920bc544f03a40f44/437a1/Code-7-2-scaled.png 1536w,\n/static/0e0f40fdf85a6cf920bc544f03a40f44/7b24f/Code-7-2-scaled.png 2048w,\n/static/0e0f40fdf85a6cf920bc544f03a40f44/8355f/Code-7-2-scaled.png 2560w\" src=\"/static/0e0f40fdf85a6cf920bc544f03a40f44/f1720/Code-7-2-scaled.png\" alt=\"\" style=\"position:absolute;top:0;left:0;opacity:1;width:100%;height:100%;object-fit:cover;object-position:center\"/></picture></noscript></span></figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>5. Double-Tap to Zoom</strong></h3>\n\n\n\n<p>A GestureDetector intercepts the double-tap and animates between the resting scale and a configurable doubleTapZoomScale, expanding around the exact point that was tapped. The animation is driven by a ValueAnimator that steps through absolute scale values from currentScale to targetScale.</p>\n\n\n\n<p>The key detail is in the factor calculation inside the update listener:</p>\n\n\n\n<p>factor = newAbsoluteScale / previousAbsoluteScale</p>\n\n\n\n<p>This is necessary because matrix.postScale applies an <em>incremental</em> multiplier on top of whatever transformation the matrix already holds — it does not accept an absolute target scale. Since the ValueAnimator delivers absolute values each frame, we must derive the relative step-size between the previous frame&#8217;s scale and the current one. Applying this relative factor each frame causes the matrix to accumulate correctly into the intended final scale.</p>\n\n\n\n<figure class=\"wp-block-image size-large\"><span class=\"wp-image-12076 inline-gatsby-image-wrapper gatsby-image-wrapper\" style=\"position:relative;overflow:hidden;max-width:100%;width:1024px\" data-reactroot=\"\"><span aria-hidden=\"true\" style=\"width:100%;padding-bottom:89.84375%\"></span><img aria-hidden=\"true\" src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAIAAADUsmlHAAAACXBIWXMAAAsTAAALEwEAmpwYAAACLUlEQVR42oVTi3aiMBD1O3Zb5RFeYkWUN5gECAmg4mO12/7/j+ywdKvbutvDPSGQ3Jk7k5sRUnTLsA3NUmUNyfr7eAvYcxcjWAuDZLHwVFmHEAAdmbpmmb/nAAitqcZ9MlI003ZDUqWkrJhoRFuLVlR1wWpS8IKywIsgnCwhCDHglty/Yj/bV7tN2XLMSYQrzPKU4aTguIrcKFiEoRNMNVueIHmiKhL6i7xcRSWtaJZnhG0Pl1d4Ts/bZnfojrvN/rg/CVan8Tr0Y5yRxXw58HsyKInSvGRNGmdRlKYpjsPEWwXz2QIpBmiGDUPxpj6FEf68Ze4XkKkoBlJNiPf4ffLwbQzj+EGaPMryWJHGijxR+vlElaWr5rfMMzdwE5pktMwZdKgqed8wymIvJ1mZkyL2C4oZaPYcPJs6qnxTs4YMUojny0u3PUCRPy+v59PldDwf9+fT4Qf8hLKzBOuaqSPrU7dlzUAGZONMUFKwkhc5E7whmJqG3ZtENUD8Z7eM3mfQHkp51x6qnG/4pmu6uqwZYesoT5bF3HIVSf1guCsZ1jJv3ZGNSNgWN03Kj8WuXQsRlYVPUyeOnP60g3mg/1E+upUBPROizWnJWd0rFy3F+WrpL11v5frDmd1xGAD0wNbD/tQ22267h+LhbKfmbDadA2zr6a63rx9knUN7obGQ58l24EghIowD/kmGJOA+CD9Y99bA/0HvMDBdf/t0a/Ddh8K+IAPny3t/l/wL+knD9rAANpYAAAAASUVORK5CYII=\" alt=\"\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;object-fit:cover;object-position:center;opacity:0;transition-delay:500ms\"/><picture><source srcSet=\"/static/f7b3a5120a8f47323b4ee565b2a0de7f/85b06/Code-9-scaled.png 256w,\n/static/f7b3a5120a8f47323b4ee565b2a0de7f/bc282/Code-9-scaled.png 512w,\n/static/f7b3a5120a8f47323b4ee565b2a0de7f/f1720/Code-9-scaled.png 1024w,\n/static/f7b3a5120a8f47323b4ee565b2a0de7f/437a1/Code-9-scaled.png 1536w,\n/static/f7b3a5120a8f47323b4ee565b2a0de7f/7b24f/Code-9-scaled.png 2048w,\n/static/f7b3a5120a8f47323b4ee565b2a0de7f/8355f/Code-9-scaled.png 2560w\" sizes=\"(max-width: 1024px) 100vw, 1024px\"/><img sizes=\"(max-width: 1024px) 100vw, 1024px\" srcSet=\"/static/f7b3a5120a8f47323b4ee565b2a0de7f/85b06/Code-9-scaled.png 256w,\n/static/f7b3a5120a8f47323b4ee565b2a0de7f/bc282/Code-9-scaled.png 512w,\n/static/f7b3a5120a8f47323b4ee565b2a0de7f/f1720/Code-9-scaled.png 1024w,\n/static/f7b3a5120a8f47323b4ee565b2a0de7f/437a1/Code-9-scaled.png 1536w,\n/static/f7b3a5120a8f47323b4ee565b2a0de7f/7b24f/Code-9-scaled.png 2048w,\n/static/f7b3a5120a8f47323b4ee565b2a0de7f/8355f/Code-9-scaled.png 2560w\" src=\"/static/f7b3a5120a8f47323b4ee565b2a0de7f/f1720/Code-9-scaled.png\" alt=\"\" loading=\"eager\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;object-fit:cover;object-position:center;opacity:1;transition:opacity 500ms\"/></picture><noscript><picture><source srcset=\"/static/f7b3a5120a8f47323b4ee565b2a0de7f/85b06/Code-9-scaled.png 256w,\n/static/f7b3a5120a8f47323b4ee565b2a0de7f/bc282/Code-9-scaled.png 512w,\n/static/f7b3a5120a8f47323b4ee565b2a0de7f/f1720/Code-9-scaled.png 1024w,\n/static/f7b3a5120a8f47323b4ee565b2a0de7f/437a1/Code-9-scaled.png 1536w,\n/static/f7b3a5120a8f47323b4ee565b2a0de7f/7b24f/Code-9-scaled.png 2048w,\n/static/f7b3a5120a8f47323b4ee565b2a0de7f/8355f/Code-9-scaled.png 2560w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" /><img loading=\"eager\" sizes=\"(max-width: 1024px) 100vw, 1024px\" srcset=\"/static/f7b3a5120a8f47323b4ee565b2a0de7f/85b06/Code-9-scaled.png 256w,\n/static/f7b3a5120a8f47323b4ee565b2a0de7f/bc282/Code-9-scaled.png 512w,\n/static/f7b3a5120a8f47323b4ee565b2a0de7f/f1720/Code-9-scaled.png 1024w,\n/static/f7b3a5120a8f47323b4ee565b2a0de7f/437a1/Code-9-scaled.png 1536w,\n/static/f7b3a5120a8f47323b4ee565b2a0de7f/7b24f/Code-9-scaled.png 2048w,\n/static/f7b3a5120a8f47323b4ee565b2a0de7f/8355f/Code-9-scaled.png 2560w\" src=\"/static/f7b3a5120a8f47323b4ee565b2a0de7f/f1720/Code-9-scaled.png\" alt=\"\" style=\"position:absolute;top:0;left:0;opacity:1;width:100%;height:100%;object-fit:cover;object-position:center\"/></picture></noscript></span></figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>6. Inertial Momentum Fling</strong></h3>\n\n\n\n<p>To simulate realistic physics when a user releases their finger after a rapid swipe, an OverScroller tracks the deceleration velocity path. Flinging only kicks in while zoomed in (and when isFlingEnabled is set), otherwise the gesture falls through to the base list.</p>\n\n\n\n<p>The runFling method is scheduled on every hardware frame via postOnAnimation. Each frame, scroller.computeScrollOffset() advances the scroller&#8217;s internal position along its deceleration curve and returns true while motion is still ongoing. The translation delta applied each frame is:</p>\n\n\n\n<p>dx = scroller.currX − drawRect.left</p>\n\n\n\n<p>dy = scroller.currY − drawRect.top</p>\n\n\n\n<p>Here, scroller.currX is the <em>absolute target position</em> the scroller wants the canvas to reach this frame, while drawRect.left is where the canvas currently sits. Subtracting them yields the precise translation delta to apply — just enough to close the gap between where the canvas is and where it should be. The loop continues until the scroller&#8217;s kinetic energy decays to zero.</p>\n\n\n\n<figure class=\"wp-block-image size-large\"><span class=\"wp-image-12112 inline-gatsby-image-wrapper gatsby-image-wrapper\" style=\"position:relative;overflow:hidden;max-width:100%;width:1024px\" data-reactroot=\"\"><span aria-hidden=\"true\" style=\"width:100%;padding-bottom:98.046875%\"></span><img aria-hidden=\"true\" src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAIAAAAC64paAAAACXBIWXMAAAsTAAALEwEAmpwYAAACf0lEQVR42o1UiW6bQBDtjyTBwC7HLmCuBQyYBWKOgO34SNK4Uf//MzqAFOMqjSo9RmjhMW9m3vBDFjFRqSKr0gL9D+D9T/xAkhKwFSWWJCIFaxipCtI0hahYx7IKEQAn8GiIsn5DhsuL0ohXPuN5WvG0jqMs8EPfZUvTWYVJyCLPYVEQhyx2zFgd+OhKtm2vqtp9f+7bU7c5lmmZpZxnZeyHS8PWVEJ0EyN9IUjiQhZnygeyKCDmhcfnY787HLb756p5fXnrm+2+2nXFU5M3/WNfrHJGfWYM0JA+FT/U7BLHNhzbcm3TQdA5+NyDJNyJiztpcS9KAgJgSQWOKmsAJCrXzPAZohlN3R6eT3lWZGu+TjK+LnJexlEKZePbWdzIhuTCvcjT5uPy+/3npW8PL8fL+9vl9fxm0iUw5x3+u9sTqGJDPwMWOSbz7DDwI2jEpOufZEi7eJDCIMmLDahdRQnEOEpAMEz7G+ZVts2SaF0yL8BoNMMIOP+GOZEReEijtmMzFWtQ/PeEGzII03VL1S2EddNYGtQCJwgP0mSJoWYRgTFGyNPJnCzrpsvrfteDQ46n/TlPiyqvyuzR0CwsKjBYiinBlCoGYF4LyFbAEkSzslW+cqNqvSmTsi1aMBaPeJ3XFa8iJ7Q0y6WuS1xwizT3Nig3ln7x2BS83O8PbdN13bauWuaH1aYB2xDdgIlIo/IvRgVr9Ov943Q4t3W37Xa+G0AX4VwU5In2CXFmsmkxZGfpdU9jNi8cts9fgVt8m3nEg00Awb7hOcSBe4+6RKGT8iEzJNEVOq07mBxgEAukgklgGXQ0xGErxqhjokjqVfaN78cdAi2AL39Dc9l/ACBo1Hisyc9zAAAAAElFTkSuQmCC\" alt=\"\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;object-fit:cover;object-position:center;opacity:0;transition-delay:500ms\"/><picture><source srcSet=\"/static/36a719e484ce5733ce9a6233d0449a45/85b06/Code-11-scaled.png 256w,\n/static/36a719e484ce5733ce9a6233d0449a45/bc282/Code-11-scaled.png 512w,\n/static/36a719e484ce5733ce9a6233d0449a45/f1720/Code-11-scaled.png 1024w,\n/static/36a719e484ce5733ce9a6233d0449a45/437a1/Code-11-scaled.png 1536w,\n/static/36a719e484ce5733ce9a6233d0449a45/7b24f/Code-11-scaled.png 2048w,\n/static/36a719e484ce5733ce9a6233d0449a45/8355f/Code-11-scaled.png 2560w\" sizes=\"(max-width: 1024px) 100vw, 1024px\"/><img sizes=\"(max-width: 1024px) 100vw, 1024px\" srcSet=\"/static/36a719e484ce5733ce9a6233d0449a45/85b06/Code-11-scaled.png 256w,\n/static/36a719e484ce5733ce9a6233d0449a45/bc282/Code-11-scaled.png 512w,\n/static/36a719e484ce5733ce9a6233d0449a45/f1720/Code-11-scaled.png 1024w,\n/static/36a719e484ce5733ce9a6233d0449a45/437a1/Code-11-scaled.png 1536w,\n/static/36a719e484ce5733ce9a6233d0449a45/7b24f/Code-11-scaled.png 2048w,\n/static/36a719e484ce5733ce9a6233d0449a45/8355f/Code-11-scaled.png 2560w\" src=\"/static/36a719e484ce5733ce9a6233d0449a45/f1720/Code-11-scaled.png\" alt=\"\" loading=\"eager\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;object-fit:cover;object-position:center;opacity:1;transition:opacity 500ms\"/></picture><noscript><picture><source srcset=\"/static/36a719e484ce5733ce9a6233d0449a45/85b06/Code-11-scaled.png 256w,\n/static/36a719e484ce5733ce9a6233d0449a45/bc282/Code-11-scaled.png 512w,\n/static/36a719e484ce5733ce9a6233d0449a45/f1720/Code-11-scaled.png 1024w,\n/static/36a719e484ce5733ce9a6233d0449a45/437a1/Code-11-scaled.png 1536w,\n/static/36a719e484ce5733ce9a6233d0449a45/7b24f/Code-11-scaled.png 2048w,\n/static/36a719e484ce5733ce9a6233d0449a45/8355f/Code-11-scaled.png 2560w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" /><img loading=\"eager\" sizes=\"(max-width: 1024px) 100vw, 1024px\" srcset=\"/static/36a719e484ce5733ce9a6233d0449a45/85b06/Code-11-scaled.png 256w,\n/static/36a719e484ce5733ce9a6233d0449a45/bc282/Code-11-scaled.png 512w,\n/static/36a719e484ce5733ce9a6233d0449a45/f1720/Code-11-scaled.png 1024w,\n/static/36a719e484ce5733ce9a6233d0449a45/437a1/Code-11-scaled.png 1536w,\n/static/36a719e484ce5733ce9a6233d0449a45/7b24f/Code-11-scaled.png 2048w,\n/static/36a719e484ce5733ce9a6233d0449a45/8355f/Code-11-scaled.png 2560w\" src=\"/static/36a719e484ce5733ce9a6233d0449a45/f1720/Code-11-scaled.png\" alt=\"\" style=\"position:absolute;top:0;left:0;opacity:1;width:100%;height:100%;object-fit:cover;object-position:center\"/></picture></noscript></span></figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>7. Configurability via XML &amp; Runtime Properties</strong></h3>\n\n\n\n<p>Every behavioral knob is exposed both as a styleable XML attribute and as a public Kotlin property, so teams can tune the experience declaratively in layouts or imperatively at runtime. The constructor reads the attributes once during inflation and falls back to sensible defaults.</p>\n\n\n\n<figure class=\"wp-block-image size-large\"><span class=\"wp-image-12124 inline-gatsby-image-wrapper gatsby-image-wrapper\" style=\"position:relative;overflow:hidden;max-width:100%;width:1024px\" data-reactroot=\"\"><span aria-hidden=\"true\" style=\"width:100%;padding-bottom:50.390625%\"></span><img aria-hidden=\"true\" src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAIAAAA7N+mxAAAACXBIWXMAAAsTAAALEwEAmpwYAAABMklEQVR42n2Si3KCMBBF/ZGqJCEgEhHBByBVHgmBgGCtbf3/H+m2TKetOs5sNskk52bvTgYEUcu0DX2CxgRr+m8g+nerYwNuXsUADpbeejH3KTEN3TJB6juD3E/A2uyl78BzZ5FnQskm2QkplVKt4FLkhcgKyatKtnC6XoWgfg3DAPlgHamyTnPhJHtQsvLESne26zPmzmyHTR3Id2AwMx4igN/Pl9PLuT0c66ZF++1TGo+KRGMMDTFUB2Xf8dzD2zA+didVNpfXj00pse8ZxMR0QjC9Zf7B2giv/E3ByyzhpVRSVpxLnhVGGCCbkZs+Xb2Mw02kqgb6BLlrOmhckKS262lsRjT6GEZREIPbQ92eT2+HpluK/DnNGcBT+1HZ/QQSfUBLv4wgiuBvjMiDmgmin8TiaxCzFZyJAAAAAElFTkSuQmCC\" alt=\"\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;object-fit:cover;object-position:center;opacity:0;transition-delay:500ms\"/><picture><source srcSet=\"/static/fa7189d3b37bba72290655e85e503df5/85b06/Code-10-scaled.png 256w,\n/static/fa7189d3b37bba72290655e85e503df5/bc282/Code-10-scaled.png 512w,\n/static/fa7189d3b37bba72290655e85e503df5/f1720/Code-10-scaled.png 1024w,\n/static/fa7189d3b37bba72290655e85e503df5/437a1/Code-10-scaled.png 1536w,\n/static/fa7189d3b37bba72290655e85e503df5/7b24f/Code-10-scaled.png 2048w,\n/static/fa7189d3b37bba72290655e85e503df5/8355f/Code-10-scaled.png 2560w\" sizes=\"(max-width: 1024px) 100vw, 1024px\"/><img sizes=\"(max-width: 1024px) 100vw, 1024px\" srcSet=\"/static/fa7189d3b37bba72290655e85e503df5/85b06/Code-10-scaled.png 256w,\n/static/fa7189d3b37bba72290655e85e503df5/bc282/Code-10-scaled.png 512w,\n/static/fa7189d3b37bba72290655e85e503df5/f1720/Code-10-scaled.png 1024w,\n/static/fa7189d3b37bba72290655e85e503df5/437a1/Code-10-scaled.png 1536w,\n/static/fa7189d3b37bba72290655e85e503df5/7b24f/Code-10-scaled.png 2048w,\n/static/fa7189d3b37bba72290655e85e503df5/8355f/Code-10-scaled.png 2560w\" src=\"/static/fa7189d3b37bba72290655e85e503df5/f1720/Code-10-scaled.png\" alt=\"\" loading=\"eager\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;object-fit:cover;object-position:center;opacity:1;transition:opacity 500ms\"/></picture><noscript><picture><source srcset=\"/static/fa7189d3b37bba72290655e85e503df5/85b06/Code-10-scaled.png 256w,\n/static/fa7189d3b37bba72290655e85e503df5/bc282/Code-10-scaled.png 512w,\n/static/fa7189d3b37bba72290655e85e503df5/f1720/Code-10-scaled.png 1024w,\n/static/fa7189d3b37bba72290655e85e503df5/437a1/Code-10-scaled.png 1536w,\n/static/fa7189d3b37bba72290655e85e503df5/7b24f/Code-10-scaled.png 2048w,\n/static/fa7189d3b37bba72290655e85e503df5/8355f/Code-10-scaled.png 2560w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" /><img loading=\"eager\" sizes=\"(max-width: 1024px) 100vw, 1024px\" srcset=\"/static/fa7189d3b37bba72290655e85e503df5/85b06/Code-10-scaled.png 256w,\n/static/fa7189d3b37bba72290655e85e503df5/bc282/Code-10-scaled.png 512w,\n/static/fa7189d3b37bba72290655e85e503df5/f1720/Code-10-scaled.png 1024w,\n/static/fa7189d3b37bba72290655e85e503df5/437a1/Code-10-scaled.png 1536w,\n/static/fa7189d3b37bba72290655e85e503df5/7b24f/Code-10-scaled.png 2048w,\n/static/fa7189d3b37bba72290655e85e503df5/8355f/Code-10-scaled.png 2560w\" src=\"/static/fa7189d3b37bba72290655e85e503df5/f1720/Code-10-scaled.png\" alt=\"\" style=\"position:absolute;top:0;left:0;opacity:1;width:100%;height:100%;object-fit:cover;object-position:center\"/></picture></noscript></span></figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><span class=\"wp-image-12160 inline-gatsby-image-wrapper gatsby-image-wrapper\" style=\"position:relative;overflow:hidden;max-width:100%;width:1024px\" data-reactroot=\"\"><span aria-hidden=\"true\" style=\"width:100%;padding-bottom:60.546875%\"></span><img aria-hidden=\"true\" src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAIAAADtbgqsAAAACXBIWXMAAAsTAAALEwEAmpwYAAABYElEQVR42o2S63KCMBCFfRIrYLgIaEhCLgRttahQ8dK+/8P0pDiMf1o7s8lskv02ZzeZzP0wibOIJP5sHnjk0XD0t00QpLjmtIyCOCGLRyNB9Az2CS+0KQxPmciFyESxKFjKsAyDaJDzK4wRkETISknDpM0zmkRpmuSjxWGKGKi4CwnCUZGDaV4cunPb9vvmeLt8nT7O5/566vrL+Xq7fFqhZ1PfewmgYjD4gxwHIz3juq7fXtfbSltrasyVrm21do7CzlqVBsaoEEwabaEOvGuYFFoJ3ez2fX85NEetXAlGWeeUGkxdreFrWZVcAkbeZUbvcCmUkrhl0+2743tb643mhlOBe+iK0SVjlMMpVnyVF8Cwny2WDh6aAeVt0+7stmJoOxcpT+YLlDoWOc5gxif46bZH8EkEl5Wp6Yp7iMOxT9DYJ++MARINQGJv6nITP3r6t+4wNIckdjIeHvCf8DeZxnqvXyAUXgAAAABJRU5ErkJggg==\" alt=\"\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;object-fit:cover;object-position:center;opacity:0;transition-delay:500ms\"/><picture><source srcSet=\"/static/34ec0cf8f17bb4c37230b9f322e64497/85b06/Code-8-3-scaled.png 256w,\n/static/34ec0cf8f17bb4c37230b9f322e64497/bc282/Code-8-3-scaled.png 512w,\n/static/34ec0cf8f17bb4c37230b9f322e64497/f1720/Code-8-3-scaled.png 1024w,\n/static/34ec0cf8f17bb4c37230b9f322e64497/437a1/Code-8-3-scaled.png 1536w,\n/static/34ec0cf8f17bb4c37230b9f322e64497/7b24f/Code-8-3-scaled.png 2048w,\n/static/34ec0cf8f17bb4c37230b9f322e64497/8355f/Code-8-3-scaled.png 2560w\" sizes=\"(max-width: 1024px) 100vw, 1024px\"/><img sizes=\"(max-width: 1024px) 100vw, 1024px\" srcSet=\"/static/34ec0cf8f17bb4c37230b9f322e64497/85b06/Code-8-3-scaled.png 256w,\n/static/34ec0cf8f17bb4c37230b9f322e64497/bc282/Code-8-3-scaled.png 512w,\n/static/34ec0cf8f17bb4c37230b9f322e64497/f1720/Code-8-3-scaled.png 1024w,\n/static/34ec0cf8f17bb4c37230b9f322e64497/437a1/Code-8-3-scaled.png 1536w,\n/static/34ec0cf8f17bb4c37230b9f322e64497/7b24f/Code-8-3-scaled.png 2048w,\n/static/34ec0cf8f17bb4c37230b9f322e64497/8355f/Code-8-3-scaled.png 2560w\" src=\"/static/34ec0cf8f17bb4c37230b9f322e64497/f1720/Code-8-3-scaled.png\" alt=\"\" loading=\"eager\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;object-fit:cover;object-position:center;opacity:1;transition:opacity 500ms\"/></picture><noscript><picture><source srcset=\"/static/34ec0cf8f17bb4c37230b9f322e64497/85b06/Code-8-3-scaled.png 256w,\n/static/34ec0cf8f17bb4c37230b9f322e64497/bc282/Code-8-3-scaled.png 512w,\n/static/34ec0cf8f17bb4c37230b9f322e64497/f1720/Code-8-3-scaled.png 1024w,\n/static/34ec0cf8f17bb4c37230b9f322e64497/437a1/Code-8-3-scaled.png 1536w,\n/static/34ec0cf8f17bb4c37230b9f322e64497/7b24f/Code-8-3-scaled.png 2048w,\n/static/34ec0cf8f17bb4c37230b9f322e64497/8355f/Code-8-3-scaled.png 2560w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" /><img loading=\"eager\" sizes=\"(max-width: 1024px) 100vw, 1024px\" srcset=\"/static/34ec0cf8f17bb4c37230b9f322e64497/85b06/Code-8-3-scaled.png 256w,\n/static/34ec0cf8f17bb4c37230b9f322e64497/bc282/Code-8-3-scaled.png 512w,\n/static/34ec0cf8f17bb4c37230b9f322e64497/f1720/Code-8-3-scaled.png 1024w,\n/static/34ec0cf8f17bb4c37230b9f322e64497/437a1/Code-8-3-scaled.png 1536w,\n/static/34ec0cf8f17bb4c37230b9f322e64497/7b24f/Code-8-3-scaled.png 2048w,\n/static/34ec0cf8f17bb4c37230b9f322e64497/8355f/Code-8-3-scaled.png 2560w\" src=\"/static/34ec0cf8f17bb4c37230b9f322e64497/f1720/Code-8-3-scaled.png\" alt=\"\" style=\"position:absolute;top:0;left:0;opacity:1;width:100%;height:100%;object-fit:cover;object-position:center\"/></picture></noscript></span></figure>\n\n\n\n<p><br>The full set of configuration options:</p>\n\n\n\n<figure class=\"wp-block-image size-large\"><span class=\"wp-image-12172 inline-gatsby-image-wrapper gatsby-image-wrapper\" style=\"position:relative;overflow:hidden;max-width:100%;width:804px\" data-reactroot=\"\"><span aria-hidden=\"true\" style=\"width:100%;padding-bottom:127.363184079602%\"></span><img aria-hidden=\"true\" src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAZCAIAAAC+dZmEAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFgElEQVR42i2T61MbZRjF97tatFYdW0qAAoHckw0JCbkSsuS62exmd5Ns7pCUe5GOrTOO4wf/L3XqaKdSS4solktLS4CEXN93LwS8jGF05nz9zTnPmfMgc2vtwko9v1TNLpxl79ZShXqSa9BUMxpshtwAs/AeveBSCLYhaaK3Y7p5YbzRMXx4YXj/Un/tb6S0Dgjyucv57Yz3B7fj0bT7sdP62Io+MWuemlWbptEXWtmW6ua2tndH8dHLkZ7d4ff2h945UF+vGHr+uYL9gY1Q4Lt7K8+wqUcW0/fTzp8S1Cbhf64f2TAM/4K7f/dbd0Zv/Ir27wRMB6GJQ8PtPfm7x//DOLEZCT/iEj8H/Y9d9h8dE48n0ScT2g2T4tm4/Lmuf0vdu625taO48cfYB7vynr3h9/bUH5ygPX8hs6vt+c9qxZXT4lJldr5amKvlMrVUvE6HGyTWIqbaPjP0aqFXzXtG+alhwXVHdMhEW+85eu0SKSy3Vz4HX3wtfPWNsPZAmC3xC/P8UkngSInCRBo7x20dn+7Cq7ygbRfM5CWuvfQO/2m7eWm8doHkF9sLa6C0AgoL7UIRFEswkwJxErJhnvaJpFsMmcWAXgpoJb/m3CvvuGQdd995V+M950imCObvwZV1uLrOLyzCuQKczcJZjk8SAj0jsF6RmBRDBhHXSyGNGFKJAaXkH5E8Msn0voSkc6A4D1fX+Pv3+aVFmEnCAgfvpvlEWCBcIuMRI1bRpxV8SiFhF4sBKeeRQkrRdUuwXOeRFAdnZ2EmDbgkSMVBIQWTURjzQxqDjIenXDxu5nEjT6AwoOBnhiB2h/fd4bFBaL0OEYbmZ/P85+v8lw+F1XmeI2GRg8s5vshAbgbEPSBmBWFtO6wBzATIumHGDkkNwPrbtg9bCBXhcxxcXxbuLwv5OIyHYZ6BBaprC2JOQNnaESMIaVq4uhkzttL2VsraDMsbvv6G86MaQvqv3OgQiPkBE4ApAjIYIJ2AtIOYo03bWtHxJoE2KLQRUdfDo7XQUA0fqYVHau6Pqwg+LaRI4V6RX58XlvNCKgxzEbjAwrkoYN3NhLOZsDdw9RmhPkvbaovBet5RYw1VfPh0+pMTJOi4KnYpKy5nhXSomxZmQqBLMs4mZWnQljqJnkW1FVJdydqqBVclgZ4kDcdReRn7tIwErHwME2hMZLx8YqZbEmRcgHa24s4mO1mPW89i41VKf8qiJ4y2TKuPumJVR7HRo8CtQ8SLCt0Z5QhxjhLnGT6FgfhUO+9vFXzN+GStC7OmCqEsU6qjOdfxWuR0NXicMb2lRl4Hbx4gXp0QtorB7gZNgt8ACAuImFq4oYFra6ShGkMrUdUx1XXTHTHqN3H1YVz1mh49YBX7eO9LZEol4hMiaRMpu5iYgrQNUtY2bW0mbDV2opown7KGMqM9SqJHSd0hp32V0e/njPucajfSu4O4RkXCIq5lpAdFqUQIpBmkPe3Pku2iv84YK0nTScJYJhVvaeVhyfb6YfRwefqgZN3lFDtk36+IfUgKGMTIuIgbxRlVd4YgijZJQyOiqlK6E0ZfvsqsfZPSv0pp9lKal12MG9vOqLbpvheIbfDcr5NYh8RNSVlMjI5D2txMuxppR41BTzhzOWk8opWvOc1+3ri36NhdmNxZtPyWVW4xsk3E2t/BlOfEuERNSJRJwHWA0DVZU51BzyjVSVxfZtVvmbFXSdXeXevefd9eyfRb0bCVU27G+58ilr6OR97xdF90RJweEUJKEBxrBuS1sLwSVRzT6jKlOGQVB5z66k5udDs99iKn2Mwq/oNvd6x9nUmZZJcJDhl09bWnZI3pgTOs/9TXVw72vw0PvooMvCQHdmID28zgFju4mRh8mhzYSA5s/AtNmtsv8hUugQAAAABJRU5ErkJggg==\" alt=\"\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;object-fit:cover;object-position:center;opacity:0;transition-delay:500ms\"/><picture><source srcSet=\"/static/07f7f2acd2a4e5919b5d5fc322734248/bb31a/image_5-scaled.png 201w,\n/static/07f7f2acd2a4e5919b5d5fc322734248/115f4/image_5-scaled.png 402w,\n/static/07f7f2acd2a4e5919b5d5fc322734248/84c27/image_5-scaled.png 804w,\n/static/07f7f2acd2a4e5919b5d5fc322734248/786d3/image_5-scaled.png 1206w,\n/static/07f7f2acd2a4e5919b5d5fc322734248/a0792/image_5-scaled.png 1608w,\n/static/07f7f2acd2a4e5919b5d5fc322734248/d55e8/image_5-scaled.png 2011w\" sizes=\"(max-width: 804px) 100vw, 804px\"/><img sizes=\"(max-width: 804px) 100vw, 804px\" srcSet=\"/static/07f7f2acd2a4e5919b5d5fc322734248/bb31a/image_5-scaled.png 201w,\n/static/07f7f2acd2a4e5919b5d5fc322734248/115f4/image_5-scaled.png 402w,\n/static/07f7f2acd2a4e5919b5d5fc322734248/84c27/image_5-scaled.png 804w,\n/static/07f7f2acd2a4e5919b5d5fc322734248/786d3/image_5-scaled.png 1206w,\n/static/07f7f2acd2a4e5919b5d5fc322734248/a0792/image_5-scaled.png 1608w,\n/static/07f7f2acd2a4e5919b5d5fc322734248/d55e8/image_5-scaled.png 2011w\" src=\"/static/07f7f2acd2a4e5919b5d5fc322734248/84c27/image_5-scaled.png\" alt=\"\" loading=\"eager\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;object-fit:cover;object-position:center;opacity:1;transition:opacity 500ms\"/></picture><noscript><picture><source srcset=\"/static/07f7f2acd2a4e5919b5d5fc322734248/bb31a/image_5-scaled.png 201w,\n/static/07f7f2acd2a4e5919b5d5fc322734248/115f4/image_5-scaled.png 402w,\n/static/07f7f2acd2a4e5919b5d5fc322734248/84c27/image_5-scaled.png 804w,\n/static/07f7f2acd2a4e5919b5d5fc322734248/786d3/image_5-scaled.png 1206w,\n/static/07f7f2acd2a4e5919b5d5fc322734248/a0792/image_5-scaled.png 1608w,\n/static/07f7f2acd2a4e5919b5d5fc322734248/d55e8/image_5-scaled.png 2011w\" sizes=\"(max-width: 804px) 100vw, 804px\" /><img loading=\"eager\" sizes=\"(max-width: 804px) 100vw, 804px\" srcset=\"/static/07f7f2acd2a4e5919b5d5fc322734248/bb31a/image_5-scaled.png 201w,\n/static/07f7f2acd2a4e5919b5d5fc322734248/115f4/image_5-scaled.png 402w,\n/static/07f7f2acd2a4e5919b5d5fc322734248/84c27/image_5-scaled.png 804w,\n/static/07f7f2acd2a4e5919b5d5fc322734248/786d3/image_5-scaled.png 1206w,\n/static/07f7f2acd2a4e5919b5d5fc322734248/a0792/image_5-scaled.png 1608w,\n/static/07f7f2acd2a4e5919b5d5fc322734248/d55e8/image_5-scaled.png 2011w\" src=\"/static/07f7f2acd2a4e5919b5d5fc322734248/84c27/image_5-scaled.png\" alt=\"\" style=\"position:absolute;top:0;left:0;opacity:1;width:100%;height:100%;object-fit:cover;object-position:center\"/></picture></noscript></span></figure>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Key Features of ZoomableRecyclerView</strong></h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Canvas Manipulation:</strong> Intercepts the dispatchDraw method to apply transformations directly using canvas.concat(matrix). This keeps operations isolated from structural view measurement cycles.</li>\n\n\n\n<li><strong>Touch Event Routing:</strong> Passes interaction data through dedicated gesture engines while gracefully handing control back to standard RecyclerView scrolling behavior when zoom is disabled or the scale is at its baseline (1x).</li>\n\n\n\n<li><strong>Double-Tap Zoom:</strong> Animates between the resting scale and a configurable doubleTapZoomScale around the tapped point using a ValueAnimator that derives incremental scale factors to compose cleanly with the matrix pipeline.</li>\n\n\n\n<li><strong>Boundary Clamping:</strong> Uses a constrainTranslation() method that reads current canvas bounds via matrix.mapRect() and applies per-case correction deltas to center small content or lock overscrolled edges back to the viewport.</li>\n\n\n\n<li><strong>Multi-Touch Stability:</strong> Re-anchors the touch baseline to the remaining active pointer inside ACTION_POINTER_UP, ensuring the next motion frame measures a zero delta — eliminating the coordinate jump that occurs when a finger is lifted mid-gesture.</li>\n\n\n\n<li><strong>Momentum Flinging:</strong> Integrates an OverScroller engine linked to a recursive postOnAnimation loop that applies frame-by-frame translation deltas until kinetic energy decays to zero.</li>\n\n\n\n<li><strong>Fully Configurable:</strong> Exposes seven knobs—min/max scale, double-tap scale, animation duration, and individual toggles for zoom, double-tap, and fling—through both XML attributes and runtime Kotlin properties.</li>\n</ul>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Benefits of ZoomableRecyclerView</strong></h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Maintained View Recycling:</strong> The parent container measures coordinates exactly as it normally would. Visible child ViewHolders continue to recycle properly within standard view boundaries.</li>\n\n\n\n<li><strong>Optimized Performance:</strong> Eliminates structural layout passes entirely during user interactions, allowing the interface to maintain stable frame rates on production hardware.</li>\n\n\n\n<li><strong>Drop-In Integration:</strong> Behaves like a standard RecyclerView—any LayoutManager, Adapter, or item decoration works unchanged, with no special adapter requirements.</li>\n\n\n\n<li><strong>Zero External Dependencies:</strong> Written purely using native Android graphics frameworks, keeping app bundle sizes small and reducing maintenance overhead.</li>\n</ul>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Conclusion</strong></h2>\n\n\n\n<p>ZoomableRecyclerView offers an efficient way to introduce pinch-to-zoom, double-tap zoom, translation panning, and deceleration physics into standard layout hierarchies. By handling transformation math at the canvas layer rather than forcing continuous structural layout updates—and by exposing every behavior through simple XML attributes and runtime properties—it enhances visual presentation and user interactivity while preserving high performance.</p>\n\n\n\n<p><strong>Ready to integrate it into your project?</strong> Check out the complete source code, installation instructions, and sample application on our official GitHub repository:</p>\n\n\n\n<p><a href=\"http://github.com/PhonePe/zoomable-recyclerview\"><strong>github.com/PhonePe/zoomable-recyclerview</strong></a></p>\n\n\n\n<p></p>\n","date":"08 September, 2026","uri":"/zoomable-recyclerview-enabling-pinch-to-zoom-and-panning-in-android-recyclerviews/","categories":{"nodes":[{"name":"Engineering","slug":"engineering"}]},"author":{"node":{"name":"akankshamishra","slug":"akankshamishra","description":null}},"featuredImage":{"node":{"altText":"","localFile":{"childImageSharp":{"fluid":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAAAsTAAALEwEAmpwYAAAC70lEQVR42iXR109TcRTA8f4vjuCAe87vDtuKaEHAhYOYmOiDvvpmJI5Eg4AIMcYVY5DRSsXBUCLEKIgxEYpIw6zILeW2peOWhq5b2mJbSn8WTL7JefrknOSoAH5sNUzQLLBzBCUAmeAKy4Z4Lszzm3FsiGAAQUZwIM4jTgKM5JTqP0YcJzhXxNvVnA9JWBAiWo2i1cZy7dfGNJo4z8cQVwECAC5CRI6dQBj+j00EZwCkAmaZsGG1OnKgUNHpwkfK7RXHbOXlC8UlYnmZreywVa32AhPgOefRI1aWjKm21poRRQY8LAlp1ZFDB8OHS6JnTjo6XkQGe1MGffhZk394KCHOpBvqnLt3L3Osf5+wSMhkDo8QnEaQEP0cpwjqeNGheKEuffqM83tf6te3zIyZWmc3pPlsLEBfGTx79ng4NgzgIGjJ4dHcQHQWMOEibeDSKevl89LjqxN1V0yfOpNjn//O/sqKkxm7NRuVqbHNW1Ag87yC4CE4r0IYY8kcgpuBSH9NV6qnNt7zMPupMfHxycTXkN9HFT/1OOKiJRkJUH2LC8AjCNGtj4gqAmMEfm/PW7l5wZT6cCf07kGiq+7FDVN/fSf9+SaTptl1Gg0qLuvfwBJ9qbczjEsQVrewVZW/d1Snm2X3OT/X6KNdNcG3jY6mhotnfRWVS8sDA6lAyN9nWbfZvHYqL9CXbW6G8fB8brN382yGGdFwlnNlZntbvc9Yr7yrHX3UVnEi+rhqODHUmYkqq+JKJrbmk+iKRI0GOT9f5tgIogtxTkXIj215ltYqY/D1LZfh7vKrXI1iy/NkT3Vk6EMyQdfT2XSS+t0bioe2t3rzdnkJGwS0A8yodu01VZYOLDZXO/XVS/pa2Vgb777tM97vuNX7pTs+MUoXpjakPxt/pjNBH21t8u7Y6VZzsoabBxjfxO3XnroNNxaaq5cMdxZb7rVff3+8xFtc6h7sXjP1rU39zFrNGUnM+Kdi+mb39h02DS8V8lMApn/5ZcMwVRrcXAAAAABJRU5ErkJggg==","aspectRatio":1.5873015873015872,"src":"/static/b19c886c47692230b76a1bd769d3e1dd/bc8e0/Tech-Blog_Opt1-2-scaled.png","srcSet":"/static/b19c886c47692230b76a1bd769d3e1dd/8ac63/Tech-Blog_Opt1-2-scaled.png 200w,\n/static/b19c886c47692230b76a1bd769d3e1dd/3891b/Tech-Blog_Opt1-2-scaled.png 400w,\n/static/b19c886c47692230b76a1bd769d3e1dd/bc8e0/Tech-Blog_Opt1-2-scaled.png 800w,\n/static/b19c886c47692230b76a1bd769d3e1dd/6050d/Tech-Blog_Opt1-2-scaled.png 1200w,\n/static/b19c886c47692230b76a1bd769d3e1dd/00405/Tech-Blog_Opt1-2-scaled.png 1600w,\n/static/b19c886c47692230b76a1bd769d3e1dd/a76e0/Tech-Blog_Opt1-2-scaled.png 2560w","sizes":"(max-width: 800px) 100vw, 800px"}}}}},"subtitleAcf":{"text":"Akhil Elango"}},"moreCategoryBlogs":{"nodes":[{"id":"cG9zdDoxMTc4Mg==","excerpt":"<p>Introduction Android&#8217;s native RecyclerView is exceptionally efficient at handling large datasets through item recycling, but it lacks native support for spatial interactions like pinch-to-zoom and canvas-level panning. For complex layouts—such as interactive retail grids or detailed dashboards—smooth zooming and panning are essential to the user experience. To address this limitation, we engineered a custom ZoomableRecyclerView&hellip; <a class=\"more-link\" href=\"/zoomable-recyclerview-enabling-pinch-to-zoom-and-panning-in-android-recyclerviews/\">Continue reading <span class=\"screen-reader-text\">Zoomable RecyclerView: Enabling Pinch-to-Zoom and Panning in Android RecyclerViews</span></a></p>\n","uri":"/zoomable-recyclerview-enabling-pinch-to-zoom-and-panning-in-android-recyclerviews/","date":"September 08, 2026","title":"Zoomable RecyclerView: Enabling Pinch-to-Zoom and Panning in Android RecyclerViews","categories":{"nodes":[{"slug":"engineering","id":"dGVybTo3","name":"Engineering"}]},"author":{"node":{"id":"dXNlcjoxMzc4","name":"akankshamishra"}},"featuredImage":{"node":{"altText":"","localFile":{"childImageSharp":{"fluid":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAAAsTAAALEwEAmpwYAAAC70lEQVR42iXR109TcRTA8f4vjuCAe87vDtuKaEHAhYOYmOiDvvpmJI5Eg4AIMcYVY5DRSsXBUCLEKIgxEYpIw6zILeW2peOWhq5b2mJbSn8WTL7JefrknOSoAH5sNUzQLLBzBCUAmeAKy4Z4Lszzm3FsiGAAQUZwIM4jTgKM5JTqP0YcJzhXxNvVnA9JWBAiWo2i1cZy7dfGNJo4z8cQVwECAC5CRI6dQBj+j00EZwCkAmaZsGG1OnKgUNHpwkfK7RXHbOXlC8UlYnmZreywVa32AhPgOefRI1aWjKm21poRRQY8LAlp1ZFDB8OHS6JnTjo6XkQGe1MGffhZk394KCHOpBvqnLt3L3Osf5+wSMhkDo8QnEaQEP0cpwjqeNGheKEuffqM83tf6te3zIyZWmc3pPlsLEBfGTx79ng4NgzgIGjJ4dHcQHQWMOEibeDSKevl89LjqxN1V0yfOpNjn//O/sqKkxm7NRuVqbHNW1Ag87yC4CE4r0IYY8kcgpuBSH9NV6qnNt7zMPupMfHxycTXkN9HFT/1OOKiJRkJUH2LC8AjCNGtj4gqAmMEfm/PW7l5wZT6cCf07kGiq+7FDVN/fSf9+SaTptl1Gg0qLuvfwBJ9qbczjEsQVrewVZW/d1Snm2X3OT/X6KNdNcG3jY6mhotnfRWVS8sDA6lAyN9nWbfZvHYqL9CXbW6G8fB8brN382yGGdFwlnNlZntbvc9Yr7yrHX3UVnEi+rhqODHUmYkqq+JKJrbmk+iKRI0GOT9f5tgIogtxTkXIj215ltYqY/D1LZfh7vKrXI1iy/NkT3Vk6EMyQdfT2XSS+t0bioe2t3rzdnkJGwS0A8yodu01VZYOLDZXO/XVS/pa2Vgb777tM97vuNX7pTs+MUoXpjakPxt/pjNBH21t8u7Y6VZzsoabBxjfxO3XnroNNxaaq5cMdxZb7rVff3+8xFtc6h7sXjP1rU39zFrNGUnM+Kdi+mb39h02DS8V8lMApn/5ZcMwVRrcXAAAAABJRU5ErkJggg==","aspectRatio":1.5873015873015872,"src":"/static/b19c886c47692230b76a1bd769d3e1dd/bc8e0/Tech-Blog_Opt1-2-scaled.png","srcSet":"/static/b19c886c47692230b76a1bd769d3e1dd/8ac63/Tech-Blog_Opt1-2-scaled.png 200w,\n/static/b19c886c47692230b76a1bd769d3e1dd/3891b/Tech-Blog_Opt1-2-scaled.png 400w,\n/static/b19c886c47692230b76a1bd769d3e1dd/bc8e0/Tech-Blog_Opt1-2-scaled.png 800w,\n/static/b19c886c47692230b76a1bd769d3e1dd/6050d/Tech-Blog_Opt1-2-scaled.png 1200w,\n/static/b19c886c47692230b76a1bd769d3e1dd/00405/Tech-Blog_Opt1-2-scaled.png 1600w,\n/static/b19c886c47692230b76a1bd769d3e1dd/a76e0/Tech-Blog_Opt1-2-scaled.png 2560w","sizes":"(max-width: 800px) 100vw, 800px"}}}}},"subtitleAcf":{"text":"Akhil Elango"}},{"id":"cG9zdDoxMDg4Mg==","excerpt":"<p>When processing billions of transactions in a system as large as PhonePe, underlying databases go through constant querying, repairs and management. While a set of these tasks are automated, some are managed by human users. This leaves a potential risk of unauthorised/untracked human activities being executed in the databases. PhonePe addresses this risk with a&hellip; <a class=\"more-link\" href=\"/hosho-a-database-activity-monitoring-tool/\">Continue reading <span class=\"screen-reader-text\">Hoshō: A Database Activity Monitoring Tool</span></a></p>\n","uri":"/hosho-a-database-activity-monitoring-tool/","date":"May 15, 2026","title":"Hoshō: A Database Activity Monitoring Tool","categories":{"nodes":[{"slug":"engineering","id":"dGVybTo3","name":"Engineering"}]},"author":{"node":{"id":"dXNlcjoyMg==","name":"Muktha Tavane"}},"featuredImage":{"node":{"altText":"","localFile":{"childImageSharp":{"fluid":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAAC4jAAAuIwF4pT92AAADqElEQVR42kWRW1AUdBSH18xERTCYoFLQhExwHMLAQQhwhhHFhWV3WeSuMpSRhBdwYAFX1EEgFIhrJZgND/jQQ4MOAioNZWg0TQnLLiwXWS6i3JeLrEb29c9ppoffnPP0zfc7R1JR/YzLlYt8W7pIaf5TLqlNXIifQLN/FLXXEKku/Rx/p5+PbQ0cWqUjenknquVawkRUFp3IV4us6iR2nRaZhRZJRdX/wJILCxSkzpATN44m8BEZuwb5UuxNZycp3tPPoTX6l0ClRMtBWz2l8cPkRY6QtXeQNE8DIZY6JJXVZiqumCkpW6Tw3Dz5SdOcV41xevcwp9yM1CaPYbzWwzdhBmJXdhH1qhalsAtfoSXGTk+kfRfhIrJ1eqRrBLAib4LycjNF2fNcTJ+l8OgUZ0TddA9R972HqF37KPNr57O3uohbqSPiv7pykaBXOgh6TUwL3UvYfis9ki8KFig5a6IwY47PhV1OxLiwG+GE0wCJNj0k2fZyxKaPw6v1RCzrQCkg/xoqLfWEWuuR23Qjt+0mxEbstsKwSDNH4aePyU02kXd4SjxjjMxdI5wWht9lzdKQb6Yp9xl1ajNX4+aIF8+RLdNywL4b5Rsib/ci39BHsL2egxs7kOSlirsdm6cwYZpsxQRnAp+Q6jrEpeAn/HLtBY15f1GXtsT3yUvcVsPJrUakK8Sn7XpQvGlA7tiLYr0OhYO45TYjkoJPZsmKNHFeMUl6wDiZH46S5GhE88Ejvt43R4XvFLXRM9SlzFOfZubo5gHCREWVQw9Su26kG3sJ2dRNqHMPgc79SEqPL3BZ85SixFmKoyfJ8RniyPpBipXjtBQt8INmgs5aE5OGRVj6m9zwUYIsuwgToFCnfiJdB4hxHyLQxYhi5zCS/MQZrmSbKEuaoiBqjCz/Ea5HT/Nr1iJtVX/SVv6c3756zoOaJdqqX1B0zsypxGlUWwxInQ2Ebu9D5v4QlZeRxIAhJHHe94nyEHFrJdyphfjtd6k5+ZiaExNUpUxSqZ6hPN1ESaqJiynTlGbOcDVjEtnWZnw23MTPuQlvl1v4uN5i9/t3BNDrHjGerUS73SViSwsqx2YSdt7nI9kD5Kp2dhz4HY+oPwiP6+RYjA61vJ0Ej5/xFzDfTQ34vduI0v1HIqT38PK6jSTWo5WYHa1EbfuJCOcWwhyakb3eRKhVA7K1DQRb3WSfdT17rerZs/YG/tbX8ba5ga9DA76bG/EVdgHuzQR6t+DjeYd/AMRumnO2r9qKAAAAAElFTkSuQmCC","aspectRatio":1.5873015873015872,"src":"/static/fd5350b7061977085d7c523b6f5a309f/bc8e0/Hosho-Final-Header-Icon-scaled.png","srcSet":"/static/fd5350b7061977085d7c523b6f5a309f/8ac63/Hosho-Final-Header-Icon-scaled.png 200w,\n/static/fd5350b7061977085d7c523b6f5a309f/3891b/Hosho-Final-Header-Icon-scaled.png 400w,\n/static/fd5350b7061977085d7c523b6f5a309f/bc8e0/Hosho-Final-Header-Icon-scaled.png 800w,\n/static/fd5350b7061977085d7c523b6f5a309f/6050d/Hosho-Final-Header-Icon-scaled.png 1200w,\n/static/fd5350b7061977085d7c523b6f5a309f/00405/Hosho-Final-Header-Icon-scaled.png 1600w,\n/static/fd5350b7061977085d7c523b6f5a309f/a76e0/Hosho-Final-Header-Icon-scaled.png 2560w","sizes":"(max-width: 800px) 100vw, 800px"}}}}},"subtitleAcf":{"text":"Pratik Anurag, Manisha C, Shubham Sharma, and Krishna Prasanth"}},{"id":"cG9zdDoxMDczOA==","excerpt":"<p>Infrastructure as Code (IaC) is often treated as the holy grail of Site Reliability Engineering (SRE). We use tools like SaltStack and Ansible, alongside golden images and post-install scripts, to define our ideal state. But here is the hidden secret of infrastructure engineering: IaC dictates how things should be, but it doesn&#8217;t guarantee what actually&hellip; <a class=\"more-link\" href=\"/beyond-iac-engineering-a-solution-to-guarantee-what-actually-is-in-production/\">Continue reading <span class=\"screen-reader-text\">Beyond IaC: Engineering a solution to Guarantee What Actually Is in Production</span></a></p>\n","uri":"/beyond-iac-engineering-a-solution-to-guarantee-what-actually-is-in-production/","date":"April 17, 2026","title":"Beyond IaC: Engineering a solution to Guarantee What Actually Is in Production","categories":{"nodes":[{"slug":"engineering","id":"dGVybTo3","name":"Engineering"}]},"author":{"node":{"id":"dXNlcjoyMg==","name":"Muktha Tavane"}},"featuredImage":{"node":{"altText":"","localFile":{"childImageSharp":{"fluid":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAAC4jAAAuIwF4pT92AAAC80lEQVR42i2S60sUYRTG5/+ob30w3Z2Z97zzrjvu7Ozqru5a3i9kQWRYGkG3T0ZgBEGQkRFUaER2J8mCogsUed20csswddXSLE1T192Zd8fVXffWaMFzDocDD4fz8GMQ6tUF4BEEL8AIz08BmsPYL+AAIcF/EoQggB9z82aYxjAKMMDzvYB6Gb04rgfjD6LZx/M/LOYlEwmaiCJZVKv1v/SZmJRMpMiCH8O0gEeIMLBh5vkes+m9U/YBmmS5BbuoyhZVsqoWSXU6ab6LOhxUklWbTTWLCiZBjvvjcEwX7PQBvGMMxu7qyvGztUHgZ3k+cPZM2OuJebsSzRej5eWay01379KuX4i+fRB/3ho/ejBs5AJZ4pzNNgHwkUHII+AvRJhMS1u4cnk1QlP3W6PXLkVGe5Kv7sUP1YZ7niT6niTON0SuN0aHXqaO14W3py8IMIVhUP+5D8Mwy07LcmBxNnn50hoxqc5cergu3N2eGO5IdjxK7N+3kuemoqQ2nYm8vhsnZBmhnxiGdHO/iYwYDTMlxYp/LnnwgOZ00D1VWmGxdqtlfXEo1XQuUlyi6ZscBz1cE+5rT8hSENCMmDnKYPiA+GFDxi895Mmx+Mtn63pOhUWhpvORqc+pzqfxr13J0yfXiopC+fm07WrscXOMQ8sEz5hNowxrfGe3D7sLvm/bNn/sSJj6k99G4p/6YktTqfs31vfuW3l4I+brSr24He94kNDPVpWFjGyACDOAvjJG1pMjDrpt40Z2AZBSU63duRlpuxc9VR+uqNB2V61UVmr1J1ZbGqONDZGSwhBCCsfOGgw+jvvEAPSy3ADLTQCeF0hANCuEKFaJ5ubS0pJQWWlI7/pstVFzlpKZqQBeLnMMiumdW7a+YTbZ7NcDJ8JPCQIEFJu8gYfLRfPdoR3ukNtFC3ZQdx61SqpOHoLFbMu4TAYz0rs3zciDkJfgcQn/RpxfIEqWqMhW1W5Xs+2qzb6BlyVLFbBO+BLGv3h+jENeDJ6/+9mUb2IXpW0AAAAASUVORK5CYII=","aspectRatio":1.5873015873015872,"src":"/static/63436876543243cc7eb59bd61c85f7c1/bc8e0/Beyond-IaC-HEADER-scaled.png","srcSet":"/static/63436876543243cc7eb59bd61c85f7c1/8ac63/Beyond-IaC-HEADER-scaled.png 200w,\n/static/63436876543243cc7eb59bd61c85f7c1/3891b/Beyond-IaC-HEADER-scaled.png 400w,\n/static/63436876543243cc7eb59bd61c85f7c1/bc8e0/Beyond-IaC-HEADER-scaled.png 800w,\n/static/63436876543243cc7eb59bd61c85f7c1/6050d/Beyond-IaC-HEADER-scaled.png 1200w,\n/static/63436876543243cc7eb59bd61c85f7c1/00405/Beyond-IaC-HEADER-scaled.png 1600w,\n/static/63436876543243cc7eb59bd61c85f7c1/a76e0/Beyond-IaC-HEADER-scaled.png 2560w","sizes":"(max-width: 800px) 100vw, 800px"}}}}},"subtitleAcf":{"text":"Aniruddha Thombre, Udeshya Giri, Shivam Pansy Satyendra Tyagi, and Ghanshyam Gupta"}},{"id":"cG9zdDoxMDY5MA==","excerpt":"<p>At PhonePe Limited (“PhonePe”), the top banner on our platform’s homepage (the &#8220;masthead&#8221;) isn&#8217;t just an ad slot—it&#8217;s the important real estate we have. However, delivering real-time, personalized recommendations at a scale of hundreds of millions of users presents a complex problem to solve for two reasons: Whether a user is brand new or a&hellip; <a class=\"more-link\" href=\"/optimizing-merchandising-machine-learning-for-real-time-app-experience-and-ltv-maximization/\">Continue reading <span class=\"screen-reader-text\">Optimizing Merchandising: Machine Learning for Real-Time App Experience and LTV Maximization</span></a></p>\n","uri":"/optimizing-merchandising-machine-learning-for-real-time-app-experience-and-ltv-maximization/","date":"February 16, 2026","title":"Optimizing Merchandising: Machine Learning for Real-Time App Experience and LTV Maximization","categories":{"nodes":[{"slug":"engineering","id":"dGVybTo3","name":"Engineering"}]},"author":{"node":{"id":"dXNlcjoyMg==","name":"Muktha Tavane"}},"featuredImage":{"node":{"altText":"","localFile":{"childImageSharp":{"fluid":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAAC4jAAAuIwF4pT92AAADBklEQVR42mPQEK3VkGxUVqxXEa5UFa0CIjXhElWhYjWhEh2JEj2pQg3hHDWhDCXBZCBSEIxXEos3kyuSFYqSEY5g0BCrU5ds0FBp0pKoUROtVBet1hSu0BWtkOfJyfHetKP2V5bLWnneZBWhVKBmRaEkeeEYWeFoIAJp1hSu0hCsNJRoMJJq0Bau0hGp0RepNZFsUOHLy/PceGb2r+rE9bKcyapC6WDLgZrjZIWiQUg4kkFfsEFXsMFEvAWIdARqdASrtQWrtQQrtIVL9CXLDaTKtEXyNISzVATTIC5XFE6QF4kBalYWT2QwEWg24muyluiwEGo14G0w5q834q/R563W4i5V4ypQ5spT4s6U50lX4odoTgHaLMUfAURywjEM1jwdljxtvvwzynQOugn2mvE2GbBVx1hN3zjz6uL289Mrz/Xln+nOv2Sn3SHHE68onKTLn1uhuz9QpV+cP5TBmavbnqszhn/eBOfDfiKT3ES6HAV7a+PX/v///8Otf2fX/Duy5teT4/9DnWfJc6aYqpZbiVY1GG3z12gX5wtj8GSf4MHe78k9wZWt25m9y5Wny5qtOcpwxryWoxOKD7ak7q2K2V0ef8BatUmJN1VNJF1ZOFmGN1qSPxwY4AyBLFMCmCcHcU3z45rsxdrnztblzNFhzdakw1ChwVCkxpCrypChwJCiwZOhJpgJ9LOCQJKWRJqSaLyMYDRDONOsUIbp8QILogXm+TJN9Gbt8wDpb/PR7Aky7vXS7nLT6LBTbtTiz1EXyFQWTFUUSFIVSlEQjpMRimaIZZyXyLg4lnVOFNvsYOap/myTvdn6nDhal04+d+vo71ObP+6f+7Wv6pwqT7qWYLaKYLqqcKquTK60YBQwkTEkMSxIZlwYyzAnmml2OMuMYLapvqwT3Hnb5zeeu7jw/8293/4+/394yx0l9nRtoVwVoXSgtw1kC+QFExTFM0CagSiRYX4M4+wIxhkgy1kmubC3R0dMzctblpG+KDtrZVjATE3ebE1+aFKR549XEIqXF00GAK/U7tOfAxm6AAAAAElFTkSuQmCC","aspectRatio":1.5873015873015872,"src":"/static/53b94435b8d140eec0522e246b3cec75/bc8e0/Machine-Learning-System-FINAL-1-scaled.png","srcSet":"/static/53b94435b8d140eec0522e246b3cec75/8ac63/Machine-Learning-System-FINAL-1-scaled.png 200w,\n/static/53b94435b8d140eec0522e246b3cec75/3891b/Machine-Learning-System-FINAL-1-scaled.png 400w,\n/static/53b94435b8d140eec0522e246b3cec75/bc8e0/Machine-Learning-System-FINAL-1-scaled.png 800w,\n/static/53b94435b8d140eec0522e246b3cec75/6050d/Machine-Learning-System-FINAL-1-scaled.png 1200w,\n/static/53b94435b8d140eec0522e246b3cec75/00405/Machine-Learning-System-FINAL-1-scaled.png 1600w,\n/static/53b94435b8d140eec0522e246b3cec75/a76e0/Machine-Learning-System-FINAL-1-scaled.png 2560w","sizes":"(max-width: 800px) 100vw, 800px"}}}}},"subtitleAcf":{"text":"Rohit Walimbe, Pramod Patil, Kunal Bhadra, Nrutya Doshi, Kedar Swadi"}},{"id":"cG9zdDo5NzM2","excerpt":"<p>At PhonePe’s scale, handling millions of transactions and user interactions every hour requires an analytics platform that’s not just fast, but instant. When every millisecond counts — both for user experience and incident detection — batch processing simply doesn’t cut it. Enter Garfield, PhonePe’s custom-built, high-throughput event analytics platform, engineered around the power of Apache Druid. Garfield is the&hellip; <a class=\"more-link\" href=\"/powering-real-time-decisions-with-phonepes-garfield-platform-and-apache-druid/\">Continue reading <span class=\"screen-reader-text\">Powering Real-Time Decisions with PhonePe’s Garfield Platform and Apache Druid</span></a></p>\n","uri":"/powering-real-time-decisions-with-phonepes-garfield-platform-and-apache-druid/","date":"November 04, 2025","title":"Powering Real-Time Decisions with PhonePe’s Garfield Platform and Apache Druid","categories":{"nodes":[{"slug":"engineering","id":"dGVybTo3","name":"Engineering"}]},"author":{"node":{"id":"dXNlcjoyMg==","name":"Muktha Tavane"}},"featuredImage":{"node":{"altText":"","localFile":{"childImageSharp":{"fluid":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAAC4jAAAuIwF4pT92AAADt0lEQVR42g3PfUzUBRzH8d/ClkinAXc8nSgMEY/ogZghCFNAUQHl4XgIOOAQ7nh2Mh4EuRAiIJjC8WiCgIDiLHqwGscapMXWdG25WY02hyVhCgrI4xEPvvv98frj+89734/gLivnfdFReRMBcj17bIpwsCzAWVaMQqrDTVrKe9KP2GtegdfWSgLM6knY3ku0TRshJo1EvtpK9ObLxJt0Eie5guArq+KI9QVCrfUoZfWEWdZywr0FN8cKFJYl7JYUojAr4l3TEvaZnePA5o859lotxzZVEyLUoBQuECWGY19pJcr0UwSlXQuJdu1k7uimwOUGGbaX0HlexWdnJXZmuYQevEZS5ADqCAOJJwaJOWog3M9AyH4DQR6DBO8ZJMx2QPzuW1I23UTQWHeTZd1L8a7PaQv5Gb3HAHlWraQ5NJJ64isuXlmjs2uD9opJ6jrWKWl/yakLa2h1K4QVGglOniPMbwq1zV/kmf6B0Js5xvXccVoCxdg7Brq8b/OZ6lduN80zVL/GxfYVmluWaaibo7Jhifw6I2kVi8QVzBGcNkO46hlJRx6j2jJKjnAP4acOGOmCH5pW6Qn8heuH7nC3c4nr+nUas+dpqjfS3Gyk9ryRc9VGPsx9SlruNAn5C8SnzxIcMkn03n9IsX1Alsl9hCExNNS4yvDlDfq1D/ky7D4j3UZqzi6jz5inRrdEbdkSZWeWKM43UqCZRKudJjZ1DlXsNFH+T0jwGCdb8ZB8+SjCj5c2GLn0EkOHkY6cMQyxY9zrW6FPv0ZD+gvKNAvoUhfRaRfI086TId6apHk0cdMkhk4R4/svCW6PSLV/QPrrvyPcqDDyReUyXRnPaIsa57fiKUYrJ7hVN81wAxRFzFEYPsuZiBlOx82S/cEM6vDn5CmnyAl5SoLvBJnej1DJ/kRjJk4uylqgVDOLPuU5d0pfsNS7Qe++axTurCb56FUKDy9TELjB6aB1yqNWKVetcjL0P5KCjKj8FlB7zqJ2eozW4m9KZBPiZN1z7lYt8qRlhcnzk3wTM0S53Sd4mJ/E3FSJj2MTgbv7CNjdg7+ilwOuPfgoutnv0oWXUyfe8jZ83foJeLMff0kzwnfHv+eWcpivD9+kwamJAokOH6sM5LJ4dlmpkb8RhXxbJNsl0aIY7EU7RI5b43G2TMR+SwQHPfV4Hb+CrUSJkGV2llOuNWjfriJ0Ww6utinYSuNxskrCxToZB2kSjpZqUTJOFhpRKk6WWtyl+QS4lONsreUtSToKi0zspQn8DzeSbq8tXUexAAAAAElFTkSuQmCC","aspectRatio":1.5873015873015872,"src":"/static/0a2eb436f64553e845347bea12e6331a/bc8e0/Garfield-Tech-Blog-Icon-02-scaled.png","srcSet":"/static/0a2eb436f64553e845347bea12e6331a/8ac63/Garfield-Tech-Blog-Icon-02-scaled.png 200w,\n/static/0a2eb436f64553e845347bea12e6331a/3891b/Garfield-Tech-Blog-Icon-02-scaled.png 400w,\n/static/0a2eb436f64553e845347bea12e6331a/bc8e0/Garfield-Tech-Blog-Icon-02-scaled.png 800w,\n/static/0a2eb436f64553e845347bea12e6331a/6050d/Garfield-Tech-Blog-Icon-02-scaled.png 1200w,\n/static/0a2eb436f64553e845347bea12e6331a/00405/Garfield-Tech-Blog-Icon-02-scaled.png 1600w,\n/static/0a2eb436f64553e845347bea12e6331a/a76e0/Garfield-Tech-Blog-Icon-02-scaled.png 2560w","sizes":"(max-width: 800px) 100vw, 800px"}}}}},"subtitleAcf":{"text":"Nitish Goyal"}}]},"moreBlogs":{"nodes":[{"id":"cG9zdDoxMTc4Mg==","excerpt":"<p>Introduction Android&#8217;s native RecyclerView is exceptionally efficient at handling large datasets through item recycling, but it lacks native support for spatial interactions like pinch-to-zoom and canvas-level panning. For complex layouts—such as interactive retail grids or detailed dashboards—smooth zooming and panning are essential to the user experience. To address this limitation, we engineered a custom ZoomableRecyclerView&hellip; <a class=\"more-link\" href=\"/zoomable-recyclerview-enabling-pinch-to-zoom-and-panning-in-android-recyclerviews/\">Continue reading <span class=\"screen-reader-text\">Zoomable RecyclerView: Enabling Pinch-to-Zoom and Panning in Android RecyclerViews</span></a></p>\n","uri":"/zoomable-recyclerview-enabling-pinch-to-zoom-and-panning-in-android-recyclerviews/","date":"September 08, 2026","title":"Zoomable RecyclerView: Enabling Pinch-to-Zoom and Panning in Android RecyclerViews","categories":{"nodes":[{"slug":"engineering","id":"dGVybTo3","name":"Engineering"}]},"author":{"node":{"id":"dXNlcjoxMzc4","name":"akankshamishra"}},"featuredImage":{"node":{"altText":"","localFile":{"childImageSharp":{"fluid":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAAAsTAAALEwEAmpwYAAAC70lEQVR42iXR109TcRTA8f4vjuCAe87vDtuKaEHAhYOYmOiDvvpmJI5Eg4AIMcYVY5DRSsXBUCLEKIgxEYpIw6zILeW2peOWhq5b2mJbSn8WTL7JefrknOSoAH5sNUzQLLBzBCUAmeAKy4Z4Lszzm3FsiGAAQUZwIM4jTgKM5JTqP0YcJzhXxNvVnA9JWBAiWo2i1cZy7dfGNJo4z8cQVwECAC5CRI6dQBj+j00EZwCkAmaZsGG1OnKgUNHpwkfK7RXHbOXlC8UlYnmZreywVa32AhPgOefRI1aWjKm21poRRQY8LAlp1ZFDB8OHS6JnTjo6XkQGe1MGffhZk394KCHOpBvqnLt3L3Osf5+wSMhkDo8QnEaQEP0cpwjqeNGheKEuffqM83tf6te3zIyZWmc3pPlsLEBfGTx79ng4NgzgIGjJ4dHcQHQWMOEibeDSKevl89LjqxN1V0yfOpNjn//O/sqKkxm7NRuVqbHNW1Ag87yC4CE4r0IYY8kcgpuBSH9NV6qnNt7zMPupMfHxycTXkN9HFT/1OOKiJRkJUH2LC8AjCNGtj4gqAmMEfm/PW7l5wZT6cCf07kGiq+7FDVN/fSf9+SaTptl1Gg0qLuvfwBJ9qbczjEsQVrewVZW/d1Snm2X3OT/X6KNdNcG3jY6mhotnfRWVS8sDA6lAyN9nWbfZvHYqL9CXbW6G8fB8brN382yGGdFwlnNlZntbvc9Yr7yrHX3UVnEi+rhqODHUmYkqq+JKJrbmk+iKRI0GOT9f5tgIogtxTkXIj215ltYqY/D1LZfh7vKrXI1iy/NkT3Vk6EMyQdfT2XSS+t0bioe2t3rzdnkJGwS0A8yodu01VZYOLDZXO/XVS/pa2Vgb777tM97vuNX7pTs+MUoXpjakPxt/pjNBH21t8u7Y6VZzsoabBxjfxO3XnroNNxaaq5cMdxZb7rVff3+8xFtc6h7sXjP1rU39zFrNGUnM+Kdi+mb39h02DS8V8lMApn/5ZcMwVRrcXAAAAABJRU5ErkJggg==","aspectRatio":1.5873015873015872,"src":"/static/b19c886c47692230b76a1bd769d3e1dd/bc8e0/Tech-Blog_Opt1-2-scaled.png","srcSet":"/static/b19c886c47692230b76a1bd769d3e1dd/8ac63/Tech-Blog_Opt1-2-scaled.png 200w,\n/static/b19c886c47692230b76a1bd769d3e1dd/3891b/Tech-Blog_Opt1-2-scaled.png 400w,\n/static/b19c886c47692230b76a1bd769d3e1dd/bc8e0/Tech-Blog_Opt1-2-scaled.png 800w,\n/static/b19c886c47692230b76a1bd769d3e1dd/6050d/Tech-Blog_Opt1-2-scaled.png 1200w,\n/static/b19c886c47692230b76a1bd769d3e1dd/00405/Tech-Blog_Opt1-2-scaled.png 1600w,\n/static/b19c886c47692230b76a1bd769d3e1dd/a76e0/Tech-Blog_Opt1-2-scaled.png 2560w","sizes":"(max-width: 800px) 100vw, 800px"}}}}},"subtitleAcf":{"text":"Akhil Elango"}},{"id":"cG9zdDoxMTU2MA==","excerpt":"<p>Lens lets your team see what is happening inside a running mobile app—from a normal web browser. You Know This Bug, Right? It is Friday afternoon. QA tells you that the profile screen is blank after login. You open the same app, follow the same steps, and everything works. The app does not crash. System&hellip; <a class=\"more-link\" href=\"/lens-give-your-entire-team-x-ray-vision-into-your-android-app/\">Continue reading <span class=\"screen-reader-text\">Lens: Give Your Entire Team X-Ray Vision Into Your Android App</span></a></p>\n","uri":"/lens-give-your-entire-team-x-ray-vision-into-your-android-app/","date":"August 10, 2026","title":"Lens: Give Your Entire Team X-Ray Vision Into Your Android App","categories":{"nodes":[{"slug":"ai","id":"dGVybTo0MjE2","name":"AI"}]},"author":{"node":{"id":"dXNlcjo1OA==","name":"Sampurna Mitra"}},"featuredImage":{"node":{"altText":"","localFile":{"childImageSharp":{"fluid":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAAAsTAAALEwEAmpwYAAADJElEQVR42gEZA+b8ACYQaCUQZyIQYyAQXxwQWRgQUhMQSw8QRQwQPggQOAUQMwYOMQcOMgkONg4NOBIOPBQeSxkJQBwKRB4KRQAmEGgmEGcjEWUoD2QvGnEiF2IUEEwPD0ULED4LEj0JEDcHDjQJCzENBzEOCTcUDz4UIU0aCEEfDEchCkgAJhBoJBBnGAldIRBgHxJdGhFXExBLFBFLFhJJAAcvBgs1CAgxKj9uS4KhGxhDFAo+GRFFHQpEGAQ+HQVDACQOZy0SamA8kiUQYhwPWR0QVg8PR2QXl2YYl1hIhkk3eAMELxcdTixbfR8cSxcDPB0ORx0HRFk3g0gkcQAiB2M5SIejve48MoMcCVYbDlQbEVE6B2+gZ8Pn2/9ucqsWEEMbEkcUADocIVEhE0shAEIaAz+eaMmTUMIAJQ1kJx1sLjp/JRZlHQpXKRFdIRFVAwA6lo64ven0pMDXPEN4MCBiJgtTIZWaJr21M1B9KQ9SUCF2YjCNACQPYyMMYSkPYScSYBgRV5aZ0mhcowcAPZaGvLjl8qi91z09eDEdZCcHVCOLmSPey0HU106hxUJMjzcTZAAgDlshD10XCVQdDVYhHl87b5Y4T4EIAz6ikr7h4f9uZqwtH1wuH2MqA1gpkaAjzcJMzNZgzOVnsetpeNEAHA9TFAdMY0iPSjJ7EgRHGARILAhdWASNtXXau2zkewWxUQmEORFqKwRXMGCKMMfHTtfgaMjka6fjbX/cABYLRhEWS3KpyGl2sxAHQx0UT3MOpaME15QEy4IAuXwEtHwGtmgHnDEKXCQCSDIdZENim1mdzm6q7XJ+4QANDjwPDj0PHUkVGksXD0YYEUgVD0Q1CmNqCJyEB7pyB6ZGCXUrEFUoDlFZDotPBHwwAFI9DmlRQ5xqYscABg4xByFBCg02DAo3EA4+EQxAFA1DEA0+FAxBMQtfJglRGglFJgpSLQ1WZhehVguIMghbOgRiOwBdQQZoAAMOLAQfOgYRMwoONQ0NOhANPhQMQRgMRhoMSRcMRB4KSiUJUScJUisIVCsHVDEHWTgGYTsGZD8HaEEFadEH0IHxhAm0AAAAAElFTkSuQmCC","aspectRatio":1.5873015873015872,"src":"/static/d85997c8e2f35163369a838af5c893fe/bc8e0/LENS-blog-icon-scaled.png","srcSet":"/static/d85997c8e2f35163369a838af5c893fe/8ac63/LENS-blog-icon-scaled.png 200w,\n/static/d85997c8e2f35163369a838af5c893fe/3891b/LENS-blog-icon-scaled.png 400w,\n/static/d85997c8e2f35163369a838af5c893fe/bc8e0/LENS-blog-icon-scaled.png 800w,\n/static/d85997c8e2f35163369a838af5c893fe/6050d/LENS-blog-icon-scaled.png 1200w,\n/static/d85997c8e2f35163369a838af5c893fe/00405/LENS-blog-icon-scaled.png 1600w,\n/static/d85997c8e2f35163369a838af5c893fe/a76e0/LENS-blog-icon-scaled.png 2560w","sizes":"(max-width: 800px) 100vw, 800px"}}}}},"subtitleAcf":{"text":"Mohan Sandeep Kella and Ashish Kumar Khatri"}},{"id":"cG9zdDoxMTQxMA==","excerpt":"<p>The Debugging Dilemma: Why TraceMind? In a complex mobile ecosystem, debugging a single production crash is rarely a straightforward task. Historically, developers at PhonePe faced a fragmented landscape of data points. When a crash alert hit, an engineer would often spend hours—or even days of bandwidth—jumping between disparate tools to piece together the narrative of&hellip; <a class=\"more-link\" href=\"/tracemind-automating-the-chaos-of-crash-debugging/\">Continue reading <span class=\"screen-reader-text\">TraceMind: Automating the Chaos of Crash Debugging</span></a></p>\n","uri":"/tracemind-automating-the-chaos-of-crash-debugging/","date":"July 29, 2026","title":"TraceMind: Automating the Chaos of Crash Debugging","categories":{"nodes":[{"slug":"ai","id":"dGVybTo0MjE2","name":"AI"}]},"author":{"node":{"id":"dXNlcjo1OA==","name":"Sampurna Mitra"}},"featuredImage":{"node":{"altText":"","localFile":{"childImageSharp":{"fluid":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAAAsTAAALEwEAmpwYAAADJElEQVR42gEZA+b8AFIZhlAZhE4ZgkoYfEUYd0AXcTsWazYWZTAVXyoUWiYUVSETUB0SSxsTSBgQQhEOPA8ROgoQMwgQLwQPKQBSFoRJKYhKIIJJFnpDGHU+F3A5Fmk0FWMuFV4pFFklFVUhFVAZDEQ5R35ViKcbG0YPDzsNETcGDi0HEC4AUBaBRyiDRyB+SBd4Qxp1PRdtPB1rNxxlLxlfKBZZIhJRJhRWIBJOGxhPLURtIylVEhJBFhFEMiFoDhI8AEoXfEccfEMYdj0TbjYTZTgXZzYXZS8UXSsPVyUKUSAZT2sdnVsdjBMQQhQFPhcLQxcVSBUSRx4WUhMSQwBFGHZCF3RGHnZbNIyBTrtkOZgtEFg6Km1BTYE+gJZEmKh1Pr9QG4YXC0cjOmMmSm4WDkoVDkkWEksXEkwAPBRtTSh9rIHjvIH2xXf/j3HVT3uwUqDESrjESsTAVtPFZcTEKiZnGAlHO2qDe/LhYZS6KSpqGhBTHBNWADkYaFIygat84IhZuoFvz2ie1my00oHB15jP25PW2W7f01rKxTVojh4eVh8mWlKJo4rB40ZOjhkJUx8eYgA0FmE2GWM3HGQoD1NscrqlxeuYwNqBv9JRxMcswbshxbklv7QoeY0eJVgVCUgVC00oKGogHWMVCFIeKWgAMBVcLxVbLRRZKRFUZ2m4XqHJSpq9SqzEIsC7KcbBONDIPL/CLnuZHiBSGA9EIBxQGBBMYEmXVDuRHRpiACYUUSATSRgTQhAON2Flumuc5G6a0myiyiu9vy6xuCyUpiZ3lS5khiQiVBcPQRgUQxEUOplvyKZo5R4YWQAHDy0FDysGDywIDi87O3pERYoxKm4vM3galaEahJUlbognWHkzR28hGk4YEUMXEkINDjZvVJ+baNQSFjkABA8qCxAxERU8DBE1Cw0xDAoyEwpCJyhpK26JIkltIixbIhxRHhFKGxFHGRNEFhFBEQ87FRg8KylWDhI3AAQPKgwQMhMWQQsQNQ8ROBMTPhUSPxgSQR0QRx4OSB8PSh4RSx0TSxwTSBkSRBURQBMSPBMUOwcNLwgPMPek40up98KQAAAAAElFTkSuQmCC","aspectRatio":1.5873015873015872,"src":"/static/ce3dbe909b007cd9c8350b8b2f15046a/bc8e0/Tracemind_Icon-scaled.png","srcSet":"/static/ce3dbe909b007cd9c8350b8b2f15046a/8ac63/Tracemind_Icon-scaled.png 200w,\n/static/ce3dbe909b007cd9c8350b8b2f15046a/3891b/Tracemind_Icon-scaled.png 400w,\n/static/ce3dbe909b007cd9c8350b8b2f15046a/bc8e0/Tracemind_Icon-scaled.png 800w,\n/static/ce3dbe909b007cd9c8350b8b2f15046a/6050d/Tracemind_Icon-scaled.png 1200w,\n/static/ce3dbe909b007cd9c8350b8b2f15046a/00405/Tracemind_Icon-scaled.png 1600w,\n/static/ce3dbe909b007cd9c8350b8b2f15046a/a76e0/Tracemind_Icon-scaled.png 2560w","sizes":"(max-width: 800px) 100vw, 800px"}}}}},"subtitleAcf":{"text":"PhonePe Team"}},{"id":"cG9zdDoxMTM4MA==","excerpt":"<p>India is undergoing a massive digital transformation, and at the heart of this revolution is PhonePe, enabling seamless payments and financial services for over 700 million registered users across Bharat. When you build at this kind of population scale, handling millions of transactions every single day, one thing matters above everything else: Trust. In the&hellip; <a class=\"more-link\" href=\"/from-gatekeeper-to-strategic-catalyst-how-genai-is-transforming-compliance-at-phonepe/\">Continue reading <span class=\"screen-reader-text\">From Gatekeeper to Strategic Catalyst: How GenAI is Transforming Compliance at PhonePe</span></a></p>\n","uri":"/from-gatekeeper-to-strategic-catalyst-how-genai-is-transforming-compliance-at-phonepe/","date":"July 16, 2026","title":"From Gatekeeper to Strategic Catalyst: How GenAI is Transforming Compliance at PhonePe","categories":{"nodes":[{"slug":"ai","id":"dGVybTo0MjE2","name":"AI"}]},"author":{"node":{"id":"dXNlcjoyMg==","name":"Muktha Tavane"}},"featuredImage":{"node":{"altText":"","localFile":{"childImageSharp":{"fluid":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAAAsTAAALEwEAmpwYAAADJElEQVR42gEZA+b8AB0UWR0UWR0UWRwSViQcXCAZVhgSUBgSTRcQShYQSRYPRhQOQhQOQhcSRw0QOgkOMgoSNQkQMgYOLQQPKgAdFFkeE1kZEFIhBlZ/Lbl0I7AYB0sXEEsYEEsWEEkWDkYUDkMWD0QQDz8nC1VhDJo9VIMLGDYJDTAJEDAAHRNWHBBUIB9aQk2IhhLChQ7ELUNsGRFMGBFLFg9IFQ1FFhFHEwpAERk+UDOPkADTVyKUEiZADAUyDBE0ABgOTywnZVuYv1y51HY/wG9LvznyuTGWiRcCQxcOSBgTSA4AOTAwaFenw2aV0n8Du1hgrzPuryVgaQ4FNAAXEU0iHVZFUX9PiqVMx8E/zrE+kow6UG4pQ2k8ippJk64uSHYtMGFQao9SobJKzcQ/zbE6no8rQV8RBjoAFxNLGRNLIxpQLSVYOVFyPFN0PVx8SKKmUcrFVLjJYaHRZJ7TcorJTk6MPDdqP2F9OUZtLhVSHwxJFwhCABQQRBUXSRgZSx8aUigKUC1Haj/Es1PVzmu+1men1m6V2YyW46SP+pd1/2hzzjA3ZiMKTB4OTh4MTBsQTgAQGkcPHEgLBThEJm5WWpE7T3Q8QGg+bYdQnrZqntyJkPCRgPd6deRYbLBHUYE8J200GGR8VqstClodD1MACxI8ERM/NU98Xou5YprBTbK5PLugQGl8MDdgN2KBVH23UW6pOUpzQTtqWk6PgQu3iwG9gGTCMjFsJgBUAAgPNhkfSFeCqle4zEzHx0+wvjfotDqnki8iWSoXUisoWTAjWzcTXFhuo2C11WBwwFtgtD3AszfcqDUqbQAJETUKEjYfIEQ4RmpFkptAoZo8U280JVoiF1AlFlMoElUsFFktE1tEL3FVYZNPr7VE3LtEp55JT4I5DmkABhAxCxI2FxtEFxc/IyFJKiJPIxhMHhlNGhBKHg5MIg1QJA1TKAtXMhJfPBFlRyR0Sj5/RRRwPwdrNwRpAAUQMAkRNBAVPw4UOxQYPxYXQxUTRBUPRBgLRhsLSR8ITSMHUSUGVSoIWzEMYjcMaDsIajoJazgHazcCag776tIRnKh8AAAAAElFTkSuQmCC","aspectRatio":1.5873015873015872,"src":"/static/a6977280a111e503accacad5691b9521/bc8e0/AI-in-compliance-blog-scaled.png","srcSet":"/static/a6977280a111e503accacad5691b9521/8ac63/AI-in-compliance-blog-scaled.png 200w,\n/static/a6977280a111e503accacad5691b9521/3891b/AI-in-compliance-blog-scaled.png 400w,\n/static/a6977280a111e503accacad5691b9521/bc8e0/AI-in-compliance-blog-scaled.png 800w,\n/static/a6977280a111e503accacad5691b9521/6050d/AI-in-compliance-blog-scaled.png 1200w,\n/static/a6977280a111e503accacad5691b9521/00405/AI-in-compliance-blog-scaled.png 1600w,\n/static/a6977280a111e503accacad5691b9521/a76e0/AI-in-compliance-blog-scaled.png 2560w","sizes":"(max-width: 800px) 100vw, 800px"}}}}},"subtitleAcf":{"text":"PhonePe Team"}},{"id":"cG9zdDoxMTM1MA==","excerpt":"<p>At PhonePe, we process a staggering 400 million transactions a day—amounting to over 10 billion monthly, operating at a scale that places it among the largest payment platforms globally. Managing such scale would typically require a massive customer support infrastructure for any company; however, PhonePe has consistently prioritized an automation-first approach. Today, we have achieved&hellip; <a class=\"more-link\" href=\"/how-ai-driven-automation-is-scaling-phonepes-customer-support-framework/\">Continue reading <span class=\"screen-reader-text\">How AI-Driven Automation is Scaling PhonePe’s Customer Support Framework</span></a></p>\n","uri":"/how-ai-driven-automation-is-scaling-phonepes-customer-support-framework/","date":"July 13, 2026","title":"How AI-Driven Automation is Scaling PhonePe’s Customer Support Framework","categories":{"nodes":[{"slug":"ai","id":"dGVybTo0MjE2","name":"AI"}]},"author":{"node":{"id":"dXNlcjoyMg==","name":"Muktha Tavane"}},"featuredImage":{"node":{"altText":"","localFile":{"childImageSharp":{"fluid":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAAAsTAAALEwEAmpwYAAADHElEQVR42hWT3U9TZwDGzwWKQGnfr3POe07PaTlYhUp1LcpXO+BgP0576mkLlAq0lFEyO0gGUzIh0KCRwYgLk2g0kcTvmBiNiXqhXmh002Xe+BE3nFmy7cILY6IX3i272c7+gN/zPPklD1Nm27YR7KgAjRbYAmCAhaqAIg4U30y6t4qDHppvZAstXLGdTuwWvo7wM3vofLf9mx5xKS0uMxvgjnLgNWFIAvX2NA+DFIZlIVnjGqyTsh4252NHmvliQJjoYL/SlFm99pBO5nvsSybPbOJ2bQK+KtAMUICyIQ4FBaRJQpICzVEVb2CzXnZkFxlttYyG6qa+2H1t/6c3+1uXNXjQoIeZSlsTxF0IqeZmBDp4FDJhhaSG1NV8ZNUt9NfjvS3Kvt7C2vj3z2f8Txa3Pzs5/f7L0A1DmWdsriRHdAg7IFBZGOKxRqG2Rcxcmvzr6qHfA9JYwDIRcU+PHL8zefFNaert0ezHE2P/Lo2+Mtwlxqytgm1ua2655v5edsWE7TguV8Z89Z+lJteWWh9fbnhRlE55nQOpyOLUxE+H9/2a7zrRoYw1c0WGoDDCwVpbX7JywVMxbLG0O0mis/Rd8uEPuVu/zRVerQTWv429Du2cc1mTO+V8k2NoG840kJzpkuGRjm3RWkdmILv6eeZsPnR6iz2jji+kr98pXF+fOv1uYfbDwaHH7d5JJ04oKKVIg7W0z4W7XaSHsdNeXBWL+2fWbvzx6Pg/P07/3eYdl6zR7Zuz0fTi8NjVYGCmRogLKCrhPQrJSDVZgddFoIlQY5y4r3loVn92+8Cjl6Vrr0vn/yyeeRFPr1AQE4EuE50HEQqjPNI4FOZQiNg6MehEWEVimHGgfr8xHbxyQV2/G/nl5757T0eOPdD0I3ZiUGxQGOOg9r8X2IWBiqFaDf3VsNXC+i24jVGkvBMNNNB8lzGXOHIumjvqlvtlISXgBIVxjsSw00AkXI3ahoWLcetiGfBUgKZy0FgOfIzC5x1cTuayZkSdkJVhr8j2UtJNocFxBpETkGoQqlbo93AFJ0htAJ9sBD7zDmU2z38o/8/Aez8H9wAAAABJRU5ErkJggg==","aspectRatio":1.5873015873015872,"src":"/static/0f2c7a1ce1a142ba3f82cd2c29c25431/bc8e0/AI-automation-in-CX-blog-icon-scaled.png","srcSet":"/static/0f2c7a1ce1a142ba3f82cd2c29c25431/8ac63/AI-automation-in-CX-blog-icon-scaled.png 200w,\n/static/0f2c7a1ce1a142ba3f82cd2c29c25431/3891b/AI-automation-in-CX-blog-icon-scaled.png 400w,\n/static/0f2c7a1ce1a142ba3f82cd2c29c25431/bc8e0/AI-automation-in-CX-blog-icon-scaled.png 800w,\n/static/0f2c7a1ce1a142ba3f82cd2c29c25431/6050d/AI-automation-in-CX-blog-icon-scaled.png 1200w,\n/static/0f2c7a1ce1a142ba3f82cd2c29c25431/00405/AI-automation-in-CX-blog-icon-scaled.png 1600w,\n/static/0f2c7a1ce1a142ba3f82cd2c29c25431/a76e0/AI-automation-in-CX-blog-icon-scaled.png 2560w","sizes":"(max-width: 800px) 100vw, 800px"}}}}},"subtitleAcf":{"text":"PhonePe Team"}}]},"previous":null,"next":{"uri":"/lens-give-your-entire-team-x-ray-vision-into-your-android-app/","title":"Lens: Give Your Entire Team X-Ray Vision Into Your Android App"},"categoriesData":{"nodes":[{"id":"dGVybTo0MjE2","name":"AI","count":5,"uri":"/category/ai/"},{"id":"dGVybToxOQ==","name":"Architecture","count":15,"uri":"/category/architecture/"},{"id":"dGVybTo0NDI=","name":"Cricket","count":null,"uri":"/category/sports/cricket/"},{"id":"dGVybTo3","name":"Engineering","count":16,"uri":"/category/engineering/"},{"id":"dGVybToyNQ==","name":"Mobile","count":10,"uri":"/category/mobile/"},{"id":"dGVybToyMg==","name":"Open Source","count":null,"uri":"/category/open-source/"},{"id":"dGVybToxNg==","name":"People Stories","count":3,"uri":"/category/people-stories/"},{"id":"dGVybToyOA==","name":"Product","count":3,"uri":"/category/product/"},{"id":"dGVybTo0MzM=","name":"Sports","count":null,"uri":"/category/sports/"},{"id":"dGVybTozMQ==","name":"Tech Stories","count":null,"uri":"/category/tech-stories/"},{"id":"dGVybTox","name":"Uncategorized","count":null,"uri":"/category/uncategorized/"}]},"recentPosts":{"nodes":[{"id":"cG9zdDoxMTc4Mg==","title":"Zoomable RecyclerView: Enabling Pinch-to-Zoom and Panning in Android RecyclerViews","uri":"/zoomable-recyclerview-enabling-pinch-to-zoom-and-panning-in-android-recyclerviews/"},{"id":"cG9zdDoxMTU2MA==","title":"Lens: Give Your Entire Team X-Ray Vision Into Your Android App","uri":"/lens-give-your-entire-team-x-ray-vision-into-your-android-app/"},{"id":"cG9zdDoxMTQxMA==","title":"TraceMind: Automating the Chaos of Crash Debugging","uri":"/tracemind-automating-the-chaos-of-crash-debugging/"},{"id":"cG9zdDoxMTM4MA==","title":"From Gatekeeper to Strategic Catalyst: How GenAI is Transforming Compliance at PhonePe","uri":"/from-gatekeeper-to-strategic-catalyst-how-genai-is-transforming-compliance-at-phonepe/"},{"id":"cG9zdDoxMTM1MA==","title":"How AI-Driven Automation is Scaling PhonePe’s Customer Support Framework","uri":"/how-ai-driven-automation-is-scaling-phonepes-customer-support-framework/"}]}},"pageContext":{"id":"cG9zdDoxMTc4Mg==","categories":[{"id":"dGVybTo0MjE2","name":"AI","slug":"ai","uri":"/category/ai/","count":5},{"id":"dGVybToxOQ==","name":"Architecture","slug":"architecture","uri":"/category/architecture/","count":15},{"id":"dGVybTo3","name":"Engineering","slug":"engineering","uri":"/category/engineering/","count":16},{"id":"dGVybToyNQ==","name":"Mobile","slug":"mobile","uri":"/category/mobile/","count":10},{"id":"dGVybToxNg==","name":"People Stories","slug":"people-stories","uri":"/category/people-stories/","count":3},{"id":"dGVybToyOA==","name":"Product","slug":"product","uri":"/category/product/","count":3}],"categoryId":"dGVybTo3","previousPostId":null,"nextPostId":"cG9zdDoxMTU2MA=="}},
    "staticQueryHashes": ["4132566406"]}