RepoPilotOpen in app →

ChadCSong/ShineButton

This is a UI lib for Android. Effects like shining.

Healthy

Healthy across all four use cases

weakest axis
Use as dependencyHealthy

Permissive license, no critical CVEs, actively maintained — safe to depend on.

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • Last commit 8mo ago
  • 7 active contributors
  • MIT licensed
Show all 7 evidence items →
  • CI configured
  • Tests present
  • Slowing — last commit 8mo ago
  • Single-maintainer risk — top contributor 89% of recent commits

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 "Healthy" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Healthy
[![RepoPilot: Healthy](https://repopilot.app/api/badge/chadcsong/shinebutton)](https://repopilot.app/r/chadcsong/shinebutton)

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/chadcsong/shinebutton on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: ChadCSong/ShineButton

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:

  1. 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.
  2. 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.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/ChadCSong/ShineButton 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

GO — Healthy across all four use cases

  • Last commit 8mo ago
  • 7 active contributors
  • MIT licensed
  • CI configured
  • Tests present
  • ⚠ Slowing — last commit 8mo ago
  • ⚠ Single-maintainer risk — top contributor 89% of recent commits

<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 ChadCSong/ShineButton repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/ChadCSong/ShineButton.

What it runs against: a local clone of ChadCSong/ShineButton — 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 ChadCSong/ShineButton | Confirms the artifact applies here, not a fork | | 2 | License is still MIT | 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 ≤ 272 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>ChadCSong/ShineButton</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of ChadCSong/ShineButton. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/ChadCSong/ShineButton.git
#   cd ShineButton
#
# 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 ChadCSong/ShineButton and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "ChadCSong/ShineButton(\\.git)?\\b" \\
  && ok "origin remote is ChadCSong/ShineButton" \\
  || miss "origin remote is not ChadCSong/ShineButton (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
  && ok "license is MIT" \\
  || miss "license drift — was MIT 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 "shinebuttonlib/src/main/java/com/sackcentury/shinebuttonlib/ShineButton.java" \\
  && ok "shinebuttonlib/src/main/java/com/sackcentury/shinebuttonlib/ShineButton.java" \\
  || miss "missing critical file: shinebuttonlib/src/main/java/com/sackcentury/shinebuttonlib/ShineButton.java"
test -f "shinebuttonlib/src/main/java/com/sackcentury/shinebuttonlib/ShineAnimator.java" \\
  && ok "shinebuttonlib/src/main/java/com/sackcentury/shinebuttonlib/ShineAnimator.java" \\
  || miss "missing critical file: shinebuttonlib/src/main/java/com/sackcentury/shinebuttonlib/ShineAnimator.java"
test -f "shinebuttonlib/src/main/java/com/sackcentury/shinebuttonlib/ShineView.java" \\
  && ok "shinebuttonlib/src/main/java/com/sackcentury/shinebuttonlib/ShineView.java" \\
  || miss "missing critical file: shinebuttonlib/src/main/java/com/sackcentury/shinebuttonlib/ShineView.java"
test -f "shinebuttonlib/src/main/java/com/sackcentury/shinebuttonlib/PorterShapeImageView.java" \\
  && ok "shinebuttonlib/src/main/java/com/sackcentury/shinebuttonlib/PorterShapeImageView.java" \\
  || miss "missing critical file: shinebuttonlib/src/main/java/com/sackcentury/shinebuttonlib/PorterShapeImageView.java"
test -f "shinebuttonlib/src/main/res/values/attrs.xml" \\
  && ok "shinebuttonlib/src/main/res/values/attrs.xml" \\
  || miss "missing critical file: shinebuttonlib/src/main/res/values/attrs.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 272 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~242d)"
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/ChadCSong/ShineButton"
  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).

</details>

TL;DR

ShineButton is an Android UI library that renders interactive buttons with particle shine/sparkle animation effects triggered on click. It uses PNG mask resources to define custom button shapes (hearts, smiles, etc.) and animates colored particles radiating outward when the button is tapped, with optional random color generation for the shine effect. Two-module structure: app/ is a demo application showcasing ShineButton usage across MainActivity.java, ListDemoActivity.java, and FragmentDemo.java; shinebuttonlib/ (referenced in build.gradle as a local project dependency) contains the core library. Raw PNG mask resources live in app/src/main/res/raw/ for shape definitions.

👥Who it's for

Android app developers building UX-rich applications who want to add delightful touch feedback animations to buttons without building custom canvas drawing and particle system code from scratch. Used by developers targeting API 14+ Android devices.

🌱Maturity & risk

Moderately mature but aging: the repo shows 42K Java LOC, Travis CI integration, and MIT license, but the file structure suggests a 2015-era codebase (compileSdkVersion 28, AppCompat v1.5.1). No visible recent commits in the provided data. Production-ready for feature use but may need dependency updates for modern Android versions.

Low-to-moderate risk: single-maintainer GitHub repo (ChadCSong) with no visible test coverage beyond a stub ExampleUnitTest.java, no open issue visibility provided, and compileSdkVersion 28 (from 2019) suggests potential API deprecation issues on Android 13+. Particle animation on older devices (API 14) may have performance implications.

Active areas of work

No active development signals visible from the file list. The codebase appears stable/archived with no pending changes, open PRs, or recent commits indicated. Last meaningful activity likely occurred when AndroidX migration happened (appcompat 1.5.1, constraintlayout 2.1.4 are current versions).

🚀Get running

Clone and build via Gradle: git clone https://github.com/ChadCSong/ShineButton.git && cd ShineButton && ./gradlew assembleDebug or open in Android Studio and click Build → Make Project. Requires JDK 1.8+ and Android SDK 28.

Daily commands: From project root: ./gradlew installDebug to deploy app/ demo to connected device/emulator, then launch via Android Studio or adb shell am start -n com.sackcentury.shinebutton/.MainActivity. No background services or build servers required.

🗺️Map of the codebase

  • shinebuttonlib/src/main/java/com/sackcentury/shinebuttonlib/ShineButton.java — Core widget class that extends View and implements the shining button behavior; all contributors must understand this entry point
  • shinebuttonlib/src/main/java/com/sackcentury/shinebuttonlib/ShineAnimator.java — Orchestrates the animation lifecycle and particle effects; critical for understanding the visual behavior
  • shinebuttonlib/src/main/java/com/sackcentury/shinebuttonlib/ShineView.java — Responsible for rendering the shine effect particles; directly impacts visual quality and performance
  • shinebuttonlib/src/main/java/com/sackcentury/shinebuttonlib/PorterShapeImageView.java — Uses PorterDuff blending for shape masking; essential for custom button shapes and fill effects
  • shinebuttonlib/src/main/res/values/attrs.xml — Defines all custom XML attributes for ShineButton configuration; required reading for understanding customization options
  • app/src/main/java/com/sackcentury/shinebutton/MainActivity.java — Demo application showing typical ShineButton usage patterns and configuration

🧩Components & responsibilities

  • ShineButton (View, PorterShapeImageView, ShineAnimator) — Main widget facade; handles click events, state toggling, integration with parent Activity, and delegation to animators
    • Failure mode: Null pointer if init() not called; animation may

🛠️How to make changes

Add a new shape/icon for the button

  1. Place your PNG resource in shinebuttonlib/src/main/res/raw/ (e.g., your_shape.png) (shinebuttonlib/src/main/res/raw/)
  2. Reference it in XML layout via android:tag or in code via setShapeResource(R.raw.your_shape) (app/src/main/res/layout/activity_main.xml)
  3. Call shineButton.setShapeResource(R.raw.your_shape) in Java code (app/src/main/java/com/sackcentury/shinebutton/MainActivity.java)

Customize the shine animation timing and colors

  1. Define custom attributes in attrs.xml for new animation properties if needed (shinebuttonlib/src/main/res/values/attrs.xml)
  2. Modify ShineButton.java to read these attributes in the constructor and pass to ShineAnimator (shinebuttonlib/src/main/java/com/sackcentury/shinebuttonlib/ShineButton.java)
  3. Update ShineAnimator.java to apply the custom timing and color values during animation (shinebuttonlib/src/main/java/com/sackcentury/shinebuttonlib/ShineAnimator.java)
  4. Test in MainActivity by setting the custom attributes or calling setter methods (app/src/main/java/com/sackcentury/shinebutton/MainActivity.java)

Support ShineButton in a ListView or RecyclerView

  1. Create a list item layout containing ShineButton (reference ListDemoActivity) (app/src/main/res/layout/list_item.xml)
  2. In the adapter's onBindViewHolder, call shineButton.init(activity) for each ShineButton instance (app/src/main/java/com/sackcentury/shinebutton/ListDemoActivity.java)
  3. Ensure ShineButton state is managed per item (enabled/disabled on toggle, reset on recycle) (shinebuttonlib/src/main/java/com/sackcentury/shinebuttonlib/ShineButton.java)

Add animation listeners for state change callbacks

  1. Extend SimpleAnimatorListener in your code or implement AnimatorListener directly (shinebuttonlib/src/main/java/com/sackcentury/shinebuttonlib/listener/SimpleAnimatorListener.java)
  2. Pass the listener to ShineAnimator or add it via ShineButton's setListener method (shinebuttonlib/src/main/java/com/sackcentury/shinebuttonlib/ShineButton.java)
  3. Handle onAnimationStart, onAnimationEnd callbacks in your listener implementation (app/src/main/java/com/sackcentury/shinebutton/MainActivity.java)

🔧Why these technologies

  • Android View system (Canvas drawing) — Provides direct pixel control for smooth particle rendering without heavyweight frameworks
  • ObjectAnimator (ValueAnimator) — Built-in Android animation framework ensures smooth 60fps animations tied to system vsync
  • PorterDuff blend modes (PorterDuffXfermode) — Enables efficient shape masking and color blending without additional texture operations
  • XML custom attributes (attrs.xml) — Allows declarative UI configuration consistent with Android conventions (colors, dimensions, resources)

⚖️Trade-offs already made

  • Animation particles rendered via Canvas.drawCircle() instead of using ImageView

    • Why: Direct Canvas drawing is lower-overhead for dynamic particle generation vs. View hierarchy inflation
    • Consequence: Slightly more complex coordinate math but significantly better performance in rapid sequences
  • ShineView added/removed dynamically from parent during animation

    • Why: Avoids keeping a persistent overlay View that would consume memory and event handling
    • Consequence: Requires proper cleanup and state management to prevent memory leaks or lingering overlays
  • Single-threaded UI thread animation (no background threads)

    • Why: Simplifies synchronization and keeps rendering on the main thread per Android best practices
    • Consequence: Heavy custom View drawing on main thread could block if particle count is very high (mitigated by reasonable defaults)

🚫Non-goals (don't propose these)

  • Real-time network synchronization or state persistence across app restarts
  • Support for animated vector drawables (VectorDrawable) as shapes; PNG raster shapes only
  • Accessibility features (TalkBack) beyond standard Button semantics
  • Widget support (home screen widgets)

🪤Traps & gotchas

PNG mask resources in app/src/main/res/raw/ must be pure black-and-white (no anti-aliasing) for reliable shape extraction; gray or blurred edges cause rendering artifacts. The library performs init(activity) which requires Activity context—using application context will fail. Particle animations can cause jank on API 16-19 devices without hardware acceleration explicitly enabled in AndroidManifest.xml.

🏗️Architecture

💡Concepts to learn

  • Canvas particle system — ShineButton animates dozens of small particles (circles, shapes) simultaneously using Canvas.drawCircle() in onDraw(); understanding particle lifetime, velocity, and fade-out is essential to modifying animation behavior
  • ObjectAnimator value interpolation — ShineButton uses ObjectAnimator (not ValueAnimator) to animate particle properties over fixed durations; understanding @IntDef animators and evaluators is needed to customize shine timing
  • PNG alpha mask extraction — Raw PNG resources in app/src/main/res/raw/ are used as binary masks to trace button silhouettes; modifying shapes requires understanding how BitmapFactory + alpha channel parsing creates shape definitions
  • View hardware acceleration — Particle animations on low-API devices (14-19) can stutter without GPU rendering; ShineButton likely needs android:hardwareAccelerated tuning in AndroidManifest.xml for smooth 60fps animation
  • Random color generation (HSV color space) — The allow_random_color feature generates perceptually distinct shine colors; likely uses Color.HSVToColor() to vary hue while maintaining consistent saturation/value for visual cohesion
  • Custom View inflation and styling — ShineButton extends View and reads XML attributes via TypedArray in the constructor; understanding obtainStyledAttributes() and attr resource parsing is needed to add new customizable properties
  • tyrantgit/ExplosionField — Older Android particle explosion animation library (2013-2015 era) solving similar visual feedback problem with custom Canvas drawing
  • facebook/rebound — Spring dynamics physics library for Android animations that could enhance ShineButton particle trajectories beyond linear interpolation
  • lottie-android/lottie-android — Modern alternative for complex animations (including particle effects) using vector graphics composition instead of custom Canvas code
  • square/android-times-square — Contemporary Android UI library (similar era, MIT license) showing gradle module structure and AppCompat migration patterns

🪄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 AndroidTest cases for ShineButton core animations and state management

The repo has empty androidTest directories (shinebuttonlib/src/androidTest/java and app/src/androidTest/java/com/sackcentury/shinebutton/) with only a basic ApplicationTest.java. ShineButton's core functionality involves complex animations and UI state changes that need proper instrumented testing to catch regressions across Android versions (API 14+). This will improve reliability for contributors.

  • [ ] Create ShineButtonInstrumentedTest.java in shinebuttonlib/src/androidTest/java/com/sackcentury/shinebutton/
  • [ ] Add tests for button initialization, shine animation triggering, and color state changes
  • [ ] Add tests for button behavior in ListViews (relevant to ListDemoActivity.java)
  • [ ] Verify tests pass on minSdkVersion 14 and targetSdkVersion 28

Migrate Travis CI to GitHub Actions with API level matrix testing

The .travis.yml exists but is outdated. GitHub Actions is now the standard and allows better Android testing with matrix builds across multiple API levels (14, 21, 28, 33). This will catch API compatibility issues early, especially important given the library's wide API support (14+) and would replace the broken Travis badge in README.md.

  • [ ] Create .github/workflows/android-ci.yml with matrix strategy for API levels 14, 21, 28, 33
  • [ ] Configure gradle build and test execution for both app and shinebuttonlib modules
  • [ ] Add linting checks using Android Lint
  • [ ] Update README.md badge from Travis CI to GitHub Actions

Create unit tests for ShineButton animation calculations and particle physics

The repo has empty test directories (app/src/test/java and shinebuttonlib likely has similar structure) with only placeholder ExampleUnitTest.java. ShineButton's core value is complex animation logic with particle effects and shine calculations. Unit tests for animation parameters, particle trajectories, and timing would help maintainers and contributors understand the math and prevent regressions.

  • [ ] Create ExampleUnitTest.java in shinebuttonlib/src/test/java/com/sackcentury/shinebutton/
  • [ ] Add unit tests for particle animation mathematics (trajectory, speed, lifetime calculations)
  • [ ] Add tests for color interpolation and alpha channel calculations
  • [ ] Add tests for animation duration and timing configurations
  • [ ] Ensure tests run with JUnit 4.13.2 (already in dependencies)

🌿Good first issues

  • Add unit tests for ShineButton color interpolation logic in app/src/test/java/: ExampleUnitTest.java is a stub. Write tests verifying setBtnColor(), setBtnFillColor(), and allow_random_color combination outputs actual Color values.
  • Create comprehensive Javadoc comments for public ShineButton methods (currently absent): document setShapeResource(int), setAnimDuration(long), setAllowRandomColor(boolean) with @param and @return tags in the library source.
  • Add XML attribute documentation to README.md: create a table mapping app: attributes (siShape, btn_color, btn_fill_color, shine_animation_duration) to Java setters with code examples for each.

Top contributors

Click to expand

📝Recent commits

Click to expand
  • e558b65 — Update README.md (ChadCSong)
  • 428893c — Update README.md (ChadCSong)
  • b883497 — clear demo code (ChadCSong)
  • bdd0e9d — Upgrade lib version (ChadCSong)
  • 87e96b7 — 更新库版本 (ChadCSong)
  • 315a724 — 去掉无效脚本 (ChadCSong)
  • 493c383 — Update README (ChadCSong)
  • f501a2f — Merge pull request #58 from i-Taozi/Modify_GRADLE_1 (ChadCSong)
  • caa327f — reset the value of "maxParallelForks" (i-Taozi)
  • a689b66 — Improve GRADLE build Performance (chenzhang22)

🔒Security observations

The ShineButton Android UI library has a moderate security posture with several concerns related to outdated build tools and lack of code obfuscation. The primary risks are: (1) using compileSdkVersion 28 which misses 6+ years of Android security updates, (2) disabled minification in release builds exposing code to reverse engineering, and (3) very low minSdkVersion supporting deprecated Android versions. No hardcoded credentials, injection vulnerabilities, or suspicious dependencies were identified. Immediate actions should focus on updating the SDK version and enabling minification for production builds.

  • Medium · Outdated Gradle Plugin and Build Tools — app/build.gradle, shinebuttonlib/build.gradle. The project uses compileSdkVersion 28 (Android 9.0, released 2018) which is significantly outdated. Current stable versions are 34+ (Android 14). This may miss critical security patches and modern security features. Fix: Update compileSdkVersion to 34 or higher, and update targetSdkVersion accordingly. Review and update all dependencies to their latest stable versions.
  • Medium · Minify Not Enabled in Release Build — app/build.gradle (buildTypes.release section). The release build has minifyEnabled set to false, which means the code is not obfuscated. This makes it easier for attackers to reverse engineer the application and discover sensitive logic, hardcoded values, or security mechanisms. Fix: Set minifyEnabled to true and properly configure ProGuard/R8 rules in proguard-rules.pro to obfuscate the code in production builds.
  • Low · Old Minimum SDK Version — app/build.gradle (defaultConfig section). minSdkVersion is set to 14 (Android 4.0, released 2011). Supporting very old Android versions increases the attack surface and prevents the use of modern security APIs introduced in newer Android versions. Fix: Consider raising minSdkVersion to at least 21 (Android 5.0) or higher to benefit from modern security features and reduce maintenance burden.
  • Low · Missing Security-Relevant Dependency Versions — app/build.gradle (dependencies section). While dependencies are present, there is no explicit version pinning strategy. The use of 'implementation fileTree(dir: 'libs', include: ['*.jar'])' could lead to unexpected JAR files being included without version control. Fix: Remove or restrict the fileTree dependency declaration. Explicitly specify all dependencies with exact versions in the build.gradle file instead of relying on loose JAR file inclusion.
  • Low · No Security Testing Framework — Project root - dependency configuration. The project includes unit tests (JUnit 4.13.2) but lacks security-specific testing frameworks or SAST tooling integration. No evidence of automated security analysis in the CI/CD pipeline (.travis.yml is present but not analyzed). Fix: Integrate security testing tools such as Android Lint security checks, OWASP Dependency-Check, or Checkmarx. Add security unit tests for sensitive components.

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Healthy signals · ChadCSong/ShineButton — RepoPilot