Library / SDK
akshay2211/PixImagePicker avatar
akshay2211/PixImagePicker

PixImagePicker puts a WhatsApp style media picker inside your Android app

Pix is a Whatsapp image picker replica. with this, you can integrate an image picker just like WhatsApp.

871 stars219 forksKotlinApache-2.0

At a glance

What is it?
Pix is a Kotlin Android library that reproduces the WhatsApp image and video picker as an embeddable fragment, configured through a single Options object. It fits apps whose design already looks like WhatsApp, and it leaves camera permissions, dark theme and result persistence for the integrator to solve.
Who is it for?
Adopt PixImagePicker when your design brief is literally the WhatsApp picker and you want that grid, badge count and camera tab inside your own Android app without writing a media browser. Skip it when you need per-platform camera permission flows, a documented dark theme, or a large selection pipeline, because the README covers none of those and the video options type has no documented properties.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Activity is slowing. The repository last received commits 6 months ago.
What is it written in?
Mainly Kotlin, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Why copy the WhatsApp picker instead of using the system one

The Android system photo picker is generic: a grid, a camera button, a back arrow. WhatsApp does something more opinionated, a tabbed gallery with a media preview, a running selection badge, and a camera view that also records video. Pix exists to put that opinionated experience into an app that is not WhatsApp. The repository describes the project as a WhatsApp image picker replica, and it is written in Kotlin as an embeddable fragment rather than a standalone application.

That framing matters for the reader deciding whether to use it. Pix is not a general purpose media browser with a WhatsApp skin. The gallery layout, the multi-select count, the ratio of captured media and the flash behaviour are all fixed knobs on a single Options object, and the visual language comes from a handful of color resources. If your product spec already borrows from WhatsApp, this saves weeks of custom gallery work. If your spec is a document scanner, a single avatar field or a backup uploader, the surface area here is far larger than the problem.

One Options object carries every setting

Configuration is a single mutable object created in your own code and passed to the picker. The README gives this as the starting point.

kotlin
val options = Options().apply{
    ratio = Ratio.RATIO_AUTO
    count = 1
    spanCount = 4
    path = "Pix/Camera"
    isFrontFacing = false
    videoDurationLimitInSeconds = 10
    mode = Mode.All
    flash = Flash.Auto
    preSelectedUrls = ArrayList<Uri>()
    videoOptions : VideoOptions
}

The capture ratio accepts three constants, RATIO_4_3, RATIO_16_9 and RATIO_AUTO, and the media mode accepts All, Picture or Video. Count caps how many items the user may select, spanCount sets the number of grid columns, and path names the subfolder where captured media is stored, here "Pix/Camera". Flash selects the capture flash mode and isFrontFacing decides which camera opens first.

Two fields deserve scepticism. preSelectedUrls is typed as a list of Uri, but no documentation explains where those Uris come from, whether they survive a process restart, or how the picker reconciles them with the count limit. videoOptions is declared as a type of its own, yet its properties are never described. Both are hooks for features that the library clearly anticipated and did not finish documenting.

Results arrive by fragment callback or by the PixBus flow

The picker hands back a callback object whose status field distinguishes a successful selection from a back press. You can attach the picker to a container view in an Activity:

kotlin
addPixToActivity(R.id.container, options) {
    when (it.status) {
        PixEventCallback.Status.SUCCESS -> //use results as it.data
        PixEventCallback.Status.BACK_PRESSED -> // back pressed called
    }
}

Or you can obtain the fragment yourself and read the result through the constructor callback, which is the path to pick when you already manage fragments:

kotlin
pixFragment(options){
    when (it.status) {
        PixEventCallback.Status.SUCCESS -> //use results as it.data
        PixEventCallback.Status.BACK_PRESSED -> // back pressed called
    }
}

A third option lets any part of the application listen. PixBus is described as a state flow event bus, and the README shows it as a global results channel.

kotlin
PixBus.results {
    when (it.status) {
        PixEventCallback.Status.SUCCESS ->  //use results as it.data
        PixEventCallback.Status.BACK_PRESSED ->  // back pressed called
    }
}

The sample app shows the three supported host patterns side by side in FragmentSample.kt, NavControllerSample.kt and ViewPager2Sample.kt, all under app/src/main/java/io/ak1/pixsample/samples. That is the fastest way to judge whether the picker fits the navigation stack you already run.

Adding the dependency and opening the picker for the first time

The library is published to Maven Central under the group id io.ak1.pix and the artifact id piximagepicker, so the install step is a one line Gradle declaration. The README asks you to add mavenCentral() to the repositories block of your app level build.gradle.

groovy
repositories {
    mavenCentral()
}

Then declare the implementation dependency, using the current version 1.6.8:

groovy
implementation  'io.ak1.pix:piximagepicker:1.6.8'

A Maven consumer uses the same coordinates with a pom type:

xml
<dependency>
  <groupId>io.ak1.pix</groupId>
  <artifactId>piximagepicker</artifactId>
  <version>1.6.8</version>
  <type>pom</type>
</dependency>

Ivy repositories get an equivalent declaration with rev set to 1.6.8 and the artifact named pix. Older documentation is not thrown away: the project keeps a wiki with the guides for versions 1.5.6 and 1.2.5, and the source for 1.5.6 is kept on a branch called activity_branch. That branch naming is a useful hint when you read older snippets, since the Options shape and the callback wiring changed between those releases.

Theming runs through five named color resources

Customisation is deliberately narrow. The README asks you to define five colors in your own colors.xml, each with a name that ends in _pix so it cannot collide with your application resources.

xml
<resources>
    <color name="video_counter_color_pix">#E53935</color>
    <color name="primary_color_pix">#075e54</color>
    <color name="primary_light_color_pix">#80075e54</color>
    <color name="surface_color_pix">#ffffff</color>
    <color name="text_color_pix">#807f7f</color>
</resources>

primary_color_pix sets the accent, primary_light_color_pix is a translucent variant of it, surface_color_pix is the picker background, text_color_pix the secondary text, and video_counter_color_pix the red badge that marks the recording timer.

The limits of this approach are worth stating plainly. There is no documented theme attribute for switching to a dark surface, no documented typography override and no documented way to change the corner shape of the selected item badge. If your app ships a dark mode, you are limited to the five colors above and whatever your own resource qualifiers can do with them, such as placing the same names under a night resource folder.

Where the picker stops short of a production media flow

Several gaps are visible in the documented API. The README contains no section on runtime permissions. Since the picker opens a camera inside your app, an integrator has to work out separately which camera and media permissions the host Activity needs and how the capture path "Pix/Camera" is exposed to the system gallery. No FileProvider setup is described, and the documentation does not state whether the library registers one for you.

Selection results are returned as a list of Uri, and the documentation says nothing about the lifetime of those Uri objects, about permission flags that survive a reboot, or about handing large selections to an upload pipeline. The count field caps the number of items, but no guidance is given on memory behaviour when the span count and the count are both large.

Video capture is configured by duration limit, flash and ratio, and VideoOptions is offered as a type without documented members, so anything beyond those three knobs, such as output format or resolution, is left to inspection of the source. Teams that need any of these behaviours will end up reading the pix module directly.

The library sits on CameraX, Coroutines and FastScroll

The project credits five upstream libraries rather than reimplementing them: Glide for image loading, FastScroll for the fast scrolling gallery, Header-decor for the collapsing header, CameraX for capture, and Coroutines for asynchronous work. That choice is the clearest signal of the library's scope. The camera path is CameraX rather than a raw camera API, which is why the README frames the camera inside the same grid rather than as a separate activity. Coroutines sit under the state flow that PixBus exposes.

It also explains where the library can be flexible. Because the underlying pieces are standard Android libraries, a host app can usually theme or replace behaviour around the edges rather than inside the picker. It also marks the limit: anything that needs different capture semantics means working against CameraX configuration that the picker does not surface.

The project also states its own quality tooling. Spotless with ktlint handles formatting, Detekt runs static analysis on the Kotlin code, and Dokka generates API documentation. A mkdocs site is part of the repository build, with requirements.txt pinning mkdocs, mkdocs-material and pymdown-extensions.

Version history, licence and the cost of an upgrade

The release list is short. Version 1.6.8 was published on 2026-02-06, while the previous tag, 1.2.4, dates from 2018-08-07. The last push to the default branch was on 2026-04-15, and the repository is not archived. That last push date matters when you plan an upgrade: the library is a single consumer of a handful of upstream libraries, and a fresh release tends to mean a fresh set of CameraX and Glide constraints in your build.

The licence is Apache-2.0, which permits use in closed and commercial applications and asks you to carry the licence and notice files. That is a licensing fact rather than advice, and you should still have your own counsel read the text if your organisation treats licence review as a gate.

Because the documentation for 1.5.6 and 1.2.5 lives in the wiki rather than in the README, an upgrade means comparing your current Options usage against the 1.6.8 README and the sample app, since the callback wiring has changed between those guides.

Editorial conclusion

Adopt PixImagePicker when your design brief is literally the WhatsApp picker and you want that grid, badge count and camera tab inside your own Android app without writing a media browser. Skip it when you need per-platform camera permission flows, a documented dark theme, or a large selection pipeline, because the README covers none of those and the video options type has no documented properties. Before you commit, check the 1.6.8 artifact in Maven Central, read the Fragments samples under app/src/main/java/io/ak1/pixsample/samples, and confirm that your own Activity can host the container view that addPixToActivity(R.id.container, options) expects.

Frequently asked questions

How do I add PixImagePicker to an Android project?

Add mavenCentral() to the repositories block in your app level build.gradle and declare implementation 'io.ak1.pix:piximagepicker:1.6.8'. The artifact is also published to Maven Central with the group id io.ak1.pix and the artifact id piximagepicker, and Maven and Ivy declarations are given in the README.

How can I limit how many images a user selects in PixImagePicker?

Set the count field on the Options object, which the README describes as the number of images to restrict selection count. The spanCount field sets how many columns the selection grid shows, and both are configured on the same object you pass to the picker.

Does PixImagePicker support video capture as well as photos?

Yes. The mode field accepts All, Picture or Video, videoDurationLimitInSeconds caps the recording length, and the ratio and flash settings apply to capture as well. A separate VideoOptions type is offered for video configuration, although the README does not list its properties.

How do I change the colors of the PixImagePicker interface?

Define five color resources with the names video_counter_color_pix, primary_color_pix, primary_light_color_pix, surface_color_pix and text_color_pix in your own colors.xml. The README documents no other theme attributes, so those five names are the documented surface for theming.

Official sources

  1. akshay2211/PixImagePicker on GitHub
  2. License: Apache-2.0
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/akshay2211-piximagepicker.svg)](https://hysenlabs.com/projects/akshay2211-piximagepicker)

Was this useful?