rubensousa/ViewPagerCards
ViewPager cards inspired by Duolingo
Solo project — review before adopting
weakest axissingle-maintainer (no co-maintainers visible); no CI workflows detected
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓Last commit 8w ago
- ✓Apache-2.0 licensed
- ✓Tests present
Show all 5 evidence items →Show less
- ⚠Solo or near-solo (1 contributor active in recent commits)
- ⚠No CI workflows detected
What would change the summary?
- →Use as dependency Mixed → Healthy if: onboard a second core maintainer
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Forkable" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/rubensousa/viewpagercards)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/rubensousa/viewpagercards on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: rubensousa/ViewPagerCards
Generated by RepoPilot · 2026-05-09 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/rubensousa/ViewPagerCards shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
WAIT — Solo project — review before adopting
- Last commit 8w ago
- Apache-2.0 licensed
- Tests present
- ⚠ Solo or near-solo (1 contributor active in recent commits)
- ⚠ No CI workflows detected
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live rubensousa/ViewPagerCards
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/rubensousa/ViewPagerCards.
What it runs against: a local clone of rubensousa/ViewPagerCards — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in rubensousa/ViewPagerCards | Confirms the artifact applies here, not a fork |
| 2 | License is still Apache-2.0 | Catches relicense before you depend on it |
| 3 | Default branch master exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 89 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of rubensousa/ViewPagerCards. If you don't
# have one yet, run these first:
#
# git clone https://github.com/rubensousa/ViewPagerCards.git
# cd ViewPagerCards
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of rubensousa/ViewPagerCards and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "rubensousa/ViewPagerCards(\\.git)?\\b" \\
&& ok "origin remote is rubensousa/ViewPagerCards" \\
|| miss "origin remote is not rubensousa/ViewPagerCards (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(Apache-2\\.0)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"Apache-2\\.0\"" package.json 2>/dev/null) \\
&& ok "license is Apache-2.0" \\
|| miss "license drift — was Apache-2.0 at generation time"
# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 4. Critical files exist
test -f "app/src/main/java/com/github/rubensousa/viewpagercards/MainActivity.java" \\
&& ok "app/src/main/java/com/github/rubensousa/viewpagercards/MainActivity.java" \\
|| miss "missing critical file: app/src/main/java/com/github/rubensousa/viewpagercards/MainActivity.java"
test -f "app/src/main/java/com/github/rubensousa/viewpagercards/ShadowTransformer.java" \\
&& ok "app/src/main/java/com/github/rubensousa/viewpagercards/ShadowTransformer.java" \\
|| miss "missing critical file: app/src/main/java/com/github/rubensousa/viewpagercards/ShadowTransformer.java"
test -f "app/src/main/java/com/github/rubensousa/viewpagercards/CardPagerAdapter.java" \\
&& ok "app/src/main/java/com/github/rubensousa/viewpagercards/CardPagerAdapter.java" \\
|| miss "missing critical file: app/src/main/java/com/github/rubensousa/viewpagercards/CardPagerAdapter.java"
test -f "app/src/main/java/com/github/rubensousa/viewpagercards/CardFragmentPagerAdapter.java" \\
&& ok "app/src/main/java/com/github/rubensousa/viewpagercards/CardFragmentPagerAdapter.java" \\
|| miss "missing critical file: app/src/main/java/com/github/rubensousa/viewpagercards/CardFragmentPagerAdapter.java"
test -f "app/src/main/res/layout/activity_main.xml" \\
&& ok "app/src/main/res/layout/activity_main.xml" \\
|| miss "missing critical file: app/src/main/res/layout/activity_main.xml"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 89 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~59d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/rubensousa/ViewPagerCards"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
ViewPagerCards is an Android library that implements a card-based ViewPager UI pattern inspired by Duolingo's lesson cards. It provides smooth scrolling animations with shadow effects and scaling transformations as users swipe through cards, supporting both Fragment-based (CardFragmentPagerAdapter) and View-based (CardPagerAdapter) implementations. Single-module Android app structure with core logic in app/src/main/java/com/github/rubensousa/viewpagercards/: adapters (CardPagerAdapter, CardFragmentPagerAdapter, CardAdapter), a ShadowTransformer for view animations, CardItem data model, and demo implementations (CardFragment, MainActivity). Layout XMLs in app/src/main/res/layout/ define the card views.
👥Who it's for
Android app developers building premium feature showcases, app intros, or image galleries who want Duolingo-style card animations without building the transformation logic from scratch.
🌱Maturity & risk
This project is abandoned and no longer maintained, as stated in the README. It targets API 14+ with compileSdkVersion 25 (Android 7.1), lacks any visible test automation (only one empty ApplicationTest.java), and has no CI/CD setup. It should be treated as a reference implementation or starting point, not production code.
High risk: single maintainer with no recent commits (project explicitly unmaintained), outdated Support Library dependencies (v25.1.0 from 2016), no test coverage, and zero dependency pinning in build.gradle. The Android support libraries have since been replaced with AndroidX. Not suitable for new projects without significant refactoring.
Active areas of work
Nothing—project is dormant. The README explicitly states 'this project is no longer being maintained'. No active development, pull requests, or issue resolution is occurring.
🚀Get running
Clone the repo: git clone https://github.com/rubensousa/ViewPagerCards.git && cd ViewPagerCards. Open in Android Studio. Sync gradle dependencies by running ./gradlew build. Run on an emulator/device via ./gradlew installDebug or press Run in Android Studio.
Daily commands:
Open the project in Android Studio (API 25+ emulator or Android 7.1+ device recommended). Click 'Run' or execute ./gradlew installDebug from terminal, then launch the app. MainActivity displays two demo scenarios: View-based paging (CardPagerAdapter) and Fragment-based paging (CardFragmentPagerAdapter) at app/src/main/java/com/github/rubensousa/viewpagercards/MainActivity.java.
🗺️Map of the codebase
app/src/main/java/com/github/rubensousa/viewpagercards/MainActivity.java— Entry point that initializes the ViewPager with card adapters and demonstrates the core UI patternapp/src/main/java/com/github/rubensousa/viewpagercards/ShadowTransformer.java— Core PageTransformer that applies the stacked card effect and shadow animations—the defining visual featureapp/src/main/java/com/github/rubensousa/viewpagercards/CardPagerAdapter.java— Adapter for regular Views; developers must extend this to populate card contentapp/src/main/java/com/github/rubensousa/viewpagercards/CardFragmentPagerAdapter.java— Adapter for Fragments; alternative adapter pattern for dynamic card-based UIsapp/src/main/res/layout/activity_main.xml— Layout template showing proper ViewPager setup for the card effect patternapp/build.gradle— Defines SDK target (25), support library versions, and CardView dependency required for cards
🧩Components & responsibilities
- MainActivity (Activity, ViewPager, PagerAdapter) — Orchestrates lifecycle, creates adapters, attaches ViewPager and transformer, handles user interactions
- Failure mode: App crashes if adapter is null or ViewPager not found in layout
- CardPagerAdapter / CardFragmentPagerAdapter (PagerAdapter, FragmentPagerAdapter, CardItem data model) — Populates ViewPager with View or Fragment instances; manages card data and recycling
- Failure mode: Blank or corrupted card display if instantiateItem/getItem returns null or malformed Views
- ShadowTransformer (PageTransformer, View.setScale) — Animates card scale, translation, and shadow elevation as user swipes between pages
🛠️How to make changes
Add a new card (View-based)
- Create a new CardItem data class in CardItem.java with your card content properties (
app/src/main/java/com/github/rubensousa/viewpagercards/CardItem.java) - Extend CardPagerAdapter and override instantiateItem() to inflate and populate your card layout (
app/src/main/java/com/github/rubensousa/viewpagercards/CardPagerAdapter.java) - Create a new layout resource file (e.g., adapter.xml) with your card UI structure (
app/src/main/res/layout/adapter.xml) - In MainActivity, instantiate your adapter and set it on the ViewPager; attach ShadowTransformer (
app/src/main/java/com/github/rubensousa/viewpagercards/MainActivity.java)
Add a new card (Fragment-based)
- Create a new Fragment class extending CardFragment with your card content (
app/src/main/java/com/github/rubensousa/viewpagercards/CardFragment.java) - Design the Fragment layout in fragment_adapter.xml (
app/src/main/res/layout/fragment_adapter.xml) - Extend CardFragmentPagerAdapter and override getItem() to return your Fragment instances (
app/src/main/java/com/github/rubensousa/viewpagercards/CardFragmentPagerAdapter.java) - Set the adapter on the ViewPager in MainActivity and apply ShadowTransformer (
app/src/main/java/com/github/rubensousa/viewpagercards/MainActivity.java)
Customize the card stack animation
- Open ShadowTransformer and modify the scale factors, translation values, and shadow elevations (
app/src/main/java/com/github/rubensousa/viewpagercards/ShadowTransformer.java) - Adjust card dimensions and margins in dimens.xml to control spacing (
app/src/main/res/values/dimens.xml) - Update colors.xml if you want different shadow or card background colors (
app/src/main/res/values/colors.xml)
🔧Why these technologies
- ViewPager (Android Support Library v25) — Enables smooth horizontal card swiping and page-by-page navigation with built-in lifecycle management
- PageTransformer (ShadowTransformer) — Applies per-page transformations during scroll to create the stacked card illusion without custom ViewGroup logic
- CardView — Provides elevation and shadow rendering for the card appearance
- PagerAdapter / FragmentPagerAdapter — Abstracts card instantiation and lifecycle; supports both View and Fragment-based cards
⚖️Trade-offs already made
-
Single Activity with ViewPager instead of Fragment-based nav
- Why: Simpler demo; ViewPager handles horizontal pagination naturally
- Consequence: Limited back-stack management; all card state lives in adapters
-
PageTransformer-based animation over custom LayoutManager
- Why: Reuses framework APIs; less code; intuitive offset-based math
- Consequence: Less control over recycling; harder to do complex per-card animation sequences
-
Support API 14+ (minSdkVersion 14)
- Why: Broad device coverage for a 2016 sample project
- Consequence: Cannot use modern Jetpack Compose or newer animation APIs
🚫Non-goals (don't propose these)
- Not a library—this is a sample/demo project (as stated in README)
- Does not persist card state across app restarts
- Does not handle real-time data streaming or live updates
- No built-in accessibility features or screen-reader support
- Not designed for infinite scroll or lazy loading (fixed card list only)
🪤Traps & gotchas
- Android Support Library deprecation: This uses support-v7, design, and cardview v25.1.0 (from 2016). Modern Android requires AndroidX migration. 2. API level mismatch: minSdkVersion 14 (Android 4.0) is far below modern Play Store requirements (API 24+). 3. ProGuard/R8 not tested: minifyEnabled=false in release build; actual obfuscation untested. 4. Fragment transaction issues: CardFragmentPagerAdapter uses old FragmentPagerAdapter (can leak Fragments); no explicit transaction handling visible. 5. No lifecycle awareness: ShadowTransformer and adapters don't integrate with Android lifecycle—potential memory leaks if ViewPager persists after Fragment destruction.
🏗️Architecture
💡Concepts to learn
- PageTransformer — Core mechanism in ViewPagerCards—allows custom per-page animations (scale, alpha, translation) as user swipes between cards. ShadowTransformer implements this to achieve Duolingo-like effects.
- CardView and Elevation — ViewPagerCards uses CardView for Material shadow rendering and Z-depth effects that enhance the card flip/scale animation visually.
- FragmentPagerAdapter lifecycle — CardFragmentPagerAdapter relies on FragmentPagerAdapter to manage Fragment creation, destruction, and state—critical to understand for avoiding memory leaks and transaction issues.
- View interpolation and transformation matrices — ShadowTransformer applies scale factors and alpha values calculated from ViewPager scroll position using linear interpolation—fundamental to smooth card animations.
- RecyclerView-style Adapter pattern — CardPagerAdapter and CardFragmentPagerAdapter follow ViewPager adapter paradigm (similar to RecyclerView.Adapter) with holder binding and efficient view reuse—key pattern for Android list/pager UIs.
🔗Related repos
nickbutcher/plaid— Large-scale Android Material Design app with custom ViewPager transitions and card-based UI; production-ready reference for card animations.Google/material-components-android— Official Material Design library successor to support libraries used here; needed for modern card and transition components.androidx/androidx— AndroidX repository providing ViewPager2, FragmentContainerView, and modern lifecycle-aware paging alternatives to support-v7.chrisbanes/ViewPagerIndicator— Complementary library for adding dot indicators or title strips to ViewPager; often paired with card-based pagers like this one.daimajia/AndroidViewAnimations— General-purpose Android animation library that could extend ShadowTransformer's capabilities with more transition effects.
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add comprehensive unit tests for ShadowTransformer.java
The ShadowTransformer class is a core component that handles page transformations and animations for the card effect, but app/src/test/java/com/github/rubensousa/viewpagercards/ExampleUnitTest.java is empty. Adding tests would ensure the transformation logic works correctly across different scroll positions and prevents regressions when the animation behavior is modified.
- [ ] Create tests in app/src/test/java/com/github/rubensousa/viewpagercards/ShadowTransformerTest.java
- [ ] Add test cases for transformPage() method with various page positions (0, 0.5, 1.0, -1.0, etc.)
- [ ] Test scale, alpha, and translation transformations are applied correctly
- [ ] Add edge case tests for extreme scroll positions and velocity values
- [ ] Verify shadow elevation changes appropriately during page transitions
Add instrumented tests for CardPagerAdapter and CardFragmentPagerAdapter
The app/src/androidTest/ directory only contains a placeholder ApplicationTest.java. The two adapter classes (CardPagerAdapter.java and CardFragmentPagerAdapter.java) are critical for rendering cards but lack automated UI tests. This would verify adapters work correctly with ViewPager and ShadowTransformer across different Android API levels.
- [ ] Create app/src/androidTest/java/com/github/rubensousa/viewpagercards/CardPagerAdapterTest.java
- [ ] Create app/src/androidTest/java/com/github/rubensousa/viewpagercards/CardFragmentPagerAdapterTest.java
- [ ] Test adapter initialization with CardItem objects and proper view binding
- [ ] Test page transitions trigger correct ShadowTransformer animations
- [ ] Verify adapter handles configuration changes (rotation) correctly
- [ ] Test with minSdkVersion 14 compatibility (as specified in build.gradle)
Add instrumented tests for landscape layout variants
The repo includes landscape-specific layout files (app/src/main/res/layout-land/) but the test suite doesn't verify they work correctly. Currently no tests validate the different layouts in app/src/main/res/layout-land/activity_main.xml, app/src/main/res/layout-land/adapter.xml, and app/src/main/res/layout-land/fragment_adapter.xml function properly during orientation changes.
- [ ] Create app/src/androidTest/java/com/github/rubensousa/viewpagercards/OrientationChangeTest.java
- [ ] Test MainActivity loads and renders correctly in portrait orientation
- [ ] Test MainActivity properly transitions to landscape layout with app/src/main/res/layout-land/activity_main.xml
- [ ] Verify ViewPager state and card positions are preserved during rotation
- [ ] Test that adapter layout files (adapter.xml and fragment_adapter.xml) work in both orientations
- [ ] Validate dimens from app/src/main/res/values-land/dimens.xml are applied correctly
🌿Good first issues
- Add unit tests for CardItem and CardAdapter: app/src/test/ is empty. Create CardAdapterTest.java to verify item binding and CardItemTest.java to validate data models.
- Migrate from deprecated Support Library to AndroidX: update build.gradle to use androidx.viewpager.widget.ViewPager, androidx.cardview.widget.CardView, and androidx.fragment.app.FragmentPagerAdapter; update import statements across all Java files.
- Document ShadowTransformer animation parameters: add JavaDoc to ShadowTransformer explaining the scale range, shadow properties, and how to customize the transformation (e.g., speed, max/min scale values).
📝Recent commits
Click to expand
Recent commits
e1d8b18— Fix blog link and add maintenance notice in README (rubensousa)75d8004— Merge remote-tracking branch 'origin/master' (rubensousa)8717fd5— Add example with custom title and text (rubensousa)dfa5bff— Update dependencies (rubensousa)e5663a5— Update README.md (rubensousa)a9e6cd8— Update README.md (rubensousa)3441334— Update README.md (rubensousa)267e6c1— Update README.md (rubensousa)17c3886— Remove unused import (rubensousa)976ab80— Add scaling sample (rubensousa)
🔒Security observations
This codebase has significant security concerns due to extreme age and lack of maintenance. The project uses Android SDK and support libraries from 2016-2017 with known vulnerabilities. Minification is disabled, increasing reverse-engineering risk. The minimum SDK version of 14 is obsolete. Most critically, the project is explicitly no longer maintained, meaning no security updates will be applied. This should only be used as a reference implementation or learning example, not for production applications. Comprehensive modernization is required including SDK updates, AndroidX migration, dependency updates, and enabling code obfuscation.
- High · Outdated Android SDK and Build Tools —
app/build.gradle. The project uses compileSdkVersion 25 and buildToolsVersion 25.0.1, which are from 2016. These versions are significantly outdated and lack critical security patches. Android SDK 25 (Android 7.1) reached end-of-life and contains known vulnerabilities. Fix: Update to the latest stable compileSdkVersion (34+) and buildToolsVersion. Use modern Android SDK versions to receive security updates and patches. - High · Outdated Android Support Libraries with Known Vulnerabilities —
app/build.gradle - dependencies section. The project uses Android Support Libraries version 25.1.0 (released January 2017). These libraries are deprecated and contain known security vulnerabilities. Google ended support for the Android Support Library in favor of AndroidX. Fix: Migrate to AndroidX libraries and update to latest stable versions. Replace 'com.android.support::25.1.0' with 'androidx.' equivalents and update to current versions (e.g., androidx.appcompat:appcompat:1.6.1). - High · Minification Disabled in Release Build —
app/build.gradle - buildTypes.release section. The release build configuration has 'minifyEnabled false', meaning ProGuard/R8 code shrinking and obfuscation is disabled. This makes the app vulnerable to reverse engineering and increases APK size. Fix: Enable minification by setting 'minifyEnabled true' in release builds to enable code obfuscation and shrinking via R8 (successor to ProGuard). - Medium · Low Minimum SDK Version —
app/build.gradle - defaultConfig section. The minSdkVersion is set to 14 (Android 4.0), released in 2011. Supporting such old versions increases attack surface and requires maintaining compatibility with outdated, unpatched Android versions. Fix: Increase minSdkVersion to at least 21 (Android 5.0) or higher. This reduces compatibility burden and allows use of modern security APIs. Modern best practice is minSdkVersion 24+. - Medium · Project No Longer Maintained —
README.md. The README explicitly states 'this project is no longer being maintained'. This means security vulnerabilities and issues will not be patched, and dependencies will not be updated. Fix: If using this code in production, fork the repository and maintain it independently. Regularly update dependencies and apply security patches. Consider using this only as a learning reference. - Low · Missing Security Configuration —
app/src/main/AndroidManifest.xml or app/src/main/res/. No evidence of network security configuration (network_security_config.xml) which is important for controlling HTTPS/certificate pinning policies and cleartext traffic restrictions. Fix: Implement a network security configuration to restrict cleartext traffic and enforce HTTPS. Add network_security_config.xml with appropriate security policies.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.