Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Implementing a Swipe-Driven Layered Carousel Effect in Android

Tech 1

Creating a stacked or fold-style banner component relies on manipulating view properties in response to horizontal drag gestures. The core architecture layers multiple display elements within a parent container, using a transparent stacking order. As the user drags across the surface, the foreground element's opacity, scale, and rotation are dynamically calculated based on the swipe delta. Once the drag distance crosses a predefined threshold, the component transitions to the next visual state; otherwise, it interpolates back to the initial stacked configuration.

Layout Architecture

The view hierarchy utilizes a FrameLayout to manage z-index ordering natively. The bottom layer acts as the upcoming visual, while the top layer receives touch input and animates independently.

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/banner_container"
    android:layout_width="match_parent"
    android:layout_height="220dp"
    android:clipChildren="false">

    <ImageView
        android:id="@+id/under_layer"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:contentDescription="Background visual"
        android:scaleType="centerCrop"
        android:layout_margin="12dp"
        android:alpha="0.4" />

    <ImageView
        android:id="@+id/top_layer"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:contentDescription="Interactive foreground visual"
        android:scaleType="centerCrop"
        android:elevation="4dp" />
</FrameLayout>

Gesture Processing and Animation Logic

The interaction model intercepts raw touch coordinates and maps them to animation progress values. Instead of relying on basic touch listeners, the implementation tracks movement deltas to drive ViewPropertyAnimator calls. This ensures smooth rendering by leveraging the hardware acceleration pipeline.

public class LayeredCarouselController implements View.OnTouchListener {
    private final ImageView foregroundView;
    private final ImageView backgroundView;
    private final float DRAG_THRESHOLD = 150f;
    private float startX = 0f;
    private boolean isTracking = false;

    public LayeredCarouselController(ImageView top, ImageView bottom) {
        this.foregroundView = top;
        this.backgroundView = bottom;
        foregroundView.setOnTouchListener(this);
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getActionMasked()) {
            case MotionEvent.ACTION_DOWN:
                startX = event.getX();
                isTracking = true;
                return true;

            case MotionEvent.ACTION_MOVE:
                if (!isTracking) break;
                float deltaX = event.getX() - startX;
                updateFoldState(deltaX);
                return true;

            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                isTracking = false;
                resolveTransition(event.getX() - startX);
                return true;

            default:
                return false;
        }
    }

    private void updateFoldState(float delta) {
        float progress = Math.min(Math.abs(delta) / DRAG_THRESHOLD, 1.0f);
        boolean draggingRight = delta > 0;

        foregroundView.setAlpha(1.0f - (progress * 0.7f));
        foregroundView.setTranslationX(delta);
        foregroundView.setRotationY(draggingRight ? -progress * 15f : progress * 15f);

        backgroundView.setAlpha(0.3f + (progress * 0.5f));
    }

    private void resolveTransition(float finalDelta) {
        if (Math.abs(finalDelta) >= DRAG_THRESHOLD) {
            foregroundView.animate()
                    .translationX(finalDelta)
                    .alpha(0f)
                    .setDuration(300)
                    .withEndAction(() -> resetViews())
                    .start();
        } else {
            foregroundView.animate()
                    .translationX(0f)
                    .alpha(1f)
                    .rotationY(0f)
                    .setDuration(250)
                    .setInterpolator(new DecelerateInterpolator())
                    .start();
            backgroundView.animate().alpha(0.4f).setDuration(250).start();
        }
    }

    private void resetViews() {
        foregroundView.setAlpha(1f);
        foregroundView.setTranslationX(0f);
        foregroundView.setRotationY(0f);
    }
}

State Transition Flow

The component lifecycle follows a continuous input-processing-output loop. Touch events are normalized, clamped to avoid over-dragging, and fed into a property calculator. The rendering pipeline updates the matrix transformations for the foreground layer while simultaneously adjusting the alpha channel of the underlying layer. Upon gesture completion, the system evaluates whether the accumulated delta meets the commmit criteria. If the threshold is satisfied, a forward transition is queued; otherwise, a spring-back animation restores the initial stacked alignment.

graph TD
    A[User Touch Event] --> B{Action Type}
    B -->|DOWN| C[Record Initial X Coordinate]
    B -->|MOVE| D[Calculate Delta & Normalize Progress]
    B -->|UP/CANCEL| E[Evaluate Threshold]
    D --> F[Apply Alpha/Translation/Rotation]
    F --> G[Hardware-Accelerated Render]
    E -->|Delta > Limit| H[Trigger Snap & Load Next Frame]
    E -->|Delta <= Limit| I[Spring-Back Animation]
    H --> J[Reset State for Next Cycle]
    I --> J

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.