# SwipeMenuRecyclerView gives an Android list swipe-to-reveal menus without a framework

> SwipeMenuRecyclerView is a lightweight Kotlin library that adds left and right slide menus to a RecyclerView or to a standalone view, with three built-in menu styles and a Designer interface for writing your own. It suits an Android developer who wants swipe menus with control over the styling, and it depends on JitPack rather than Maven Central.

**aitsuki/SwipeMenuRecyclerView** — Swipe menu for recyclerView. Android 侧滑菜单，可轻松定制各种样式的菜单。

- Repository: https://github.com/aitsuki/SwipeMenuRecyclerView
- Stars: 541 · Forks: 67
- Language: Kotlin
- License: MIT
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/aitsuki-swipemenurecyclerview

## A menu view and a RecyclerView, not a framework

SwipeMenuRecyclerView is a lightweight side-swipe menu library that can be used inside a list or on its own, and the repository description puts it in both languages, as an Android swipe menu and as a way to customise menu styles easily.

The library is small by design and the README states it plainly: you do not need to write any code to get a swipe menu, though you still need to set click listeners on the menu and the content in code. Everything else is declared in the layout file.

The XML is the whole API for the common case. A SwipeLayout wraps a left menu, a right menu and the content, and the menu side is chosen by the layout_gravity attribute on the menu view, with start meaning left and end meaning right. The content view is the one that does not specify a layout_gravity.

```xml
<com.aitsuki.swipe.SwipeLayout
    app:autoClose="true"
    app:designer="@string/classic_designer"
    app:preview="none">

    <!-- This is the left menu, because it specifies `layout_gravity=start` -->
    <TextView
        android:id="@+id/left_menu"
        android:layout_width="100dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:background="@color/red500"
        android:gravity="center"
        android:text="LEFT"
        android:textSize="18sp" />

    <!-- This is the right menu -->
    <TextView
        android:id="@+id/right_menu"
        android:layout_width="100dp"
        android:layout_height="match_parent"
        android:layout_gravity="end"
        android:background="@color/blue500"
        android:gravity="center"
        android:text="RIGHT"
        android:textSize="18sp" />

    <!-- This is the content, because it dows not specify `layout_gravity` -->
    <TextView
        android:id="@+id/content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="Classic"
        android:background="@color/white"
        android:textSize="18sp" />

</com.aitsuki.swipe.SwipeLayout>
```

Three attributes do the configuration work: autoClose for whether the menu closes after a tap, designer for the menu style, and preview for what the layout editor shows. Everything else is standard view layout.

## Inside a list, and the one behaviour it does not intercept

For use in a list, the README says to use `SwipeMenuRecyclerView` in place of `RecyclerView`, and describes how little difference that makes.

The class is almost identical to RecyclerView, with one small intervention in event dispatch: it makes the SwipeLayout automatically close the menu when the RecyclerView scrolls, and it prevents several menus opening at once during multi-touch.

The second point is the interesting one. A swipe menu is a stateful view that lives inside a scrolling container, and without intervention two rows can end up open simultaneously, or a row can stay open while the list moves under it. Handling that centrally, once, in the RecyclerView subclass, is the right place for the logic.

What it deliberately does not do is catch programmatic scrolls. The README is specific that if you call the `scrollxxx()` methods on RecyclerView yourself, `SwipeMenuRecyclerView` will not close menus for you, because it cannot be sure that is the behaviour you want. In that case you close them yourself with the `closeMenus()` method.

So there is a small amount of state to manage if you drive the list programmatically, and it is worth knowing about before you wire a swipe menu into a list with animated scrolling.

## Three built-in styles, and the Designer interface behind them

The three built-in styles are Classic, Overlay and Parallax. Classic has the menu follow the content as it scrolls. Overlay has the menu not scroll and be covered by the content. Parallax has the menu follow the content and adds a parallax effect.

New styles are written by implementing `SwipeLayout.Designer`, and the README explains the mechanism as being similar to how CoordinatorLayout's `Behavior` works. The style is selected in the layout with the designer attribute.

```kotlin
class ClassicDesigner : Designer {

    private var leftMenu: View? = null

    override fun onInit(parent: SwipeLayout, leftMenu: View?, rightMenu: View?) {
        this.leftMenu = leftMenu
        leftMenu?.visibility = View.INVISIBLE
        rightMenu?.visibility = View.INVISIBLE
    }

    override fun onLayout(menuView: View, left: Int, top: Int, right: Int, bottom: Int) {
        menuView.visibility = if (right - left > 0) VISIBLE else INVISIBLE
        if (menuView == leftMenu) {
            menuView.layout(right - menuView.width, menuView.top, right, menuView.bottom)
        } else {
            menuView.layout(left, menuView.top, left + menuView.width, menuView.bottom)
        }
    }
}
```

The two callbacks have a precise lifecycle, and knowing it saves debugging time. `onInit()` runs after the SwipeLayout's `onMeasure` and executes only once, so it is where you hold references to the menu views. `onLayout()` runs after the SwipeLayout's `onLayout` and is also called as the user swipes the menu.

The left, top, right and bottom passed to `onLayout` describe the menu's observable area, which the README says you can read as a VisibleRect. That is the key to writing a custom style: you are not told where to draw, you are told what region of the menu is currently exposed, and you position the menu yourself.

A note on the sample code above, since it is copied from the README and reads oddly: the first line of the class body is a blank line, and the `Designer` type is referenced without a package qualifier.

## Attributes and listeners, and what the state values mean

Three custom attributes control the behaviour, and each has a documented default.

`preview="none|left|right"` defaults to `none`. It exists to help layout, because menus are closed by default and you cannot see the menu styling while you are designing the layout. Setting preview controls that.

`autoClose="true|false"` defaults to `false`. When the menu is open, tapping the menu closes it automatically if this is true. If it is false you have to call the public method on SwipeLayout to close it.

`designer` defaults to `classic` and selects the menu style, in the manner of CoordinateLayout's `Behavior`.

Event handling is through a listener with four callbacks.

```kotlin
swipeLayout.addListener(object : SwipeLayout.Listener {
    override fun onSwipe(menuView: View, swipeOffset: Float) {
    }

    override fun onSwipeStateChanged(menuView: View, newState: Int) {
    }

    override fun onMenuOpened(menuView: View) {
    }

    override fun onMenuClosed(menuView: View) {
    }
})
```

The parameters are documented too. The menuView is the menu currently being operated on, and if you use both a left and a right menu you have to work out which one it is yourself, for example by id or by gravity. The swipeOffset is the percentage of the menu currently shown, from 0.0f to 1.0f. The state is one of STATE_IDLE, STATE_DRAGGING or STATE_SETTLING.

That offset value is the one that makes custom behaviour possible, since it is a continuous value rather than a boolean.

## JitPack, ProGuard and the version you will actually get

Installation takes two steps, and the first one is a repository you may not have configured.

You add the JitPack repository to the project root build.gradle.

```groovy
allprojects {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}
```

The README notes that if your project was created with a newer Android Studio Arctic Fox, the repository configuration may live in settings.gradle instead.

```groovy
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}
```

Then the dependency itself.

```groovy
dependencies {
    implementation 'com.github.aitsuki:SwipeMenuRecyclerView:2.1.5'
}
```

If you enable shrinking, the README says you may need to add a rule.

```groovy
-keep class * implements com.aitsuki.swipe.SwipeLayout$Designer
```

That rule is not optional decoration. The designer is resolved by type at runtime, so obfuscating the class that implements the Designer interface breaks the lookup, and the symptom is a layout that silently falls back to no menu.

Two things to note about the version. The dependency snippet pins 2.1.5, while the newest listed release is 2.1.6 from 2026-05-11, and the release before that is 2.1.5 from 2022-06-07. The last push to the repository was also on 2026-05-11, so 2.1.6 is a recent patch on a codebase that had been quiet for a few years.

The library is MIT licensed with the LICENSE file at the root, credited to Aitsuki, and the README is available in English as README.en.md alongside the Chinese original.

## Where SwipeMenuRecyclerView is the wrong choice

Three cases argue against it.

The first is a project already using a full component or navigation library. If your app has a component library menu treatment or a navigation drawer pattern established, adding a third-party swipe view introduces a different interaction model and a different look. The library deliberately gives you styling control rather than a house style, which is a strength for a library author and a burden for an app that needs consistency across screens.

The second is a list with programmatic scrolling or complex item animations. The README says plainly that SwipeMenuRecyclerView will not close menus when you scroll the list yourself, and the workaround is a manual call to closeMenus(). In a list with diffing, item animations or a pull-to-refresh that also moves the list, that bookkeeping is yours to maintain.

The third is a requirement for a maintained dependency with a broad ecosystem. This library is distributed through JitPack, which builds from GitHub tags on demand rather than serving a release artefact from a repository you control. That means the artefact you depend on is a build of someone else's tag, the availability depends on JitPack's service, and there is no changelog-driven version stream in the way Maven Central provides.

The alternative in the same direction is to implement the swipe yourself with a ViewDragHelper or an ItemTouchHelper, or to use a component library that includes menus as part of a wider set. The difference in approach is that SwipeMenuRecyclerView gives you the interaction, the multi-touch protection and the list integration as working code, and leaves the drawing decisions to a Designer you can write. For a list that needs one specific swipe behaviour, writing it yourself with the platform's own drag helpers is a defensible choice with no third-party dependency at all.

## Conclusion

SwipeMenuRecyclerView fits an Android developer who needs swipe-to-reveal actions in a list and wants to control the animation and the styling rather than accept a fixed menu, since the Designer interface lets you write your own layout behaviour. It does not fit a project that wants menus from a navigation or component library, because this is a single view library with no navigation story. Add `com.github.aitsuki:SwipeMenuRecyclerView` from JitPack, and remember the ProGuard rule for anything implementing `com.aitsuki.swipe.SwipeLayout$Designer`, since obfuscation will otherwise break the designer resolution.

## FAQ

### How do I add SwipeMenuRecyclerView to an Android project?

Add the JitPack repository to your build.gradle, or to settings.gradle if your project uses dependencyResolutionManagement, then declare `implementation 'com.github.aitsuki:SwipeMenuRecyclerView:2.1.5'`. The newest listed release is 2.1.6 from 2026-05-11.

### How do I use SwipeMenuRecyclerView inside a RecyclerView?

Replace the RecyclerView with SwipeMenuRecyclerView and put a SwipeLayout as the item root. The class behaves almost identically to RecyclerView, only intercepting event dispatch slightly so menus close when the list scrolls and several menus cannot open at once during multi-touch.

### What menu styles does SwipeMenuRecyclerView ship with?

Three: Classic, where the menu follows the content, Overlay, where the menu does not scroll and is covered by the content, and Parallax, where the menu follows the content with a parallax effect. New styles are written by implementing the SwipeLayout.Designer interface.

### Why do I need a ProGuard rule for SwipeMenuRecyclerView?

If you enable shrinking you may need to add `-keep class * implements com.aitsuki.swipe.SwipeLayout$Designer`. The designer is resolved by type at runtime, so obfuscating the implementing class breaks the lookup and the menu silently disappears.

## Sources

- [aitsuki/SwipeMenuRecyclerView on GitHub](https://github.com/aitsuki/SwipeMenuRecyclerView)
- [Issues](https://github.com/aitsuki/SwipeMenuRecyclerView/issues)
- [License: MIT](https://github.com/aitsuki/SwipeMenuRecyclerView/blob/master/LICENSE)
- [README](https://github.com/aitsuki/SwipeMenuRecyclerView/blob/master/README.md)
- [Releases](https://github.com/aitsuki/SwipeMenuRecyclerView/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/aitsuki-swipemenurecyclerview
