RepoPilotOpen in app →

KeepSafe/TapTargetView

An implementation of tap targets from the Material Design guidelines for feature discovery.

Mixed

Stale — last commit 2y ago

weakest axis
Use as dependencyMixed

last commit was 2y ago; no tests detected…

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-isMixed

last commit was 2y ago; no CI workflows detected

  • 26+ active contributors
  • Apache-2.0 licensed
  • Stale — last commit 2y ago
Show all 6 evidence items →
  • Concentrated ownership — top contributor handles 52% of recent commits
  • No CI workflows detected
  • No test directory detected
What would change the summary?
  • Use as dependency MixedHealthy if: 1 commit in the last 365 days; add a test suite
  • Deploy as-is MixedHealthy if: 1 commit in the last 180 days

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.

Variant:
RepoPilot: Forkable
[![RepoPilot: Forkable](https://repopilot.app/api/badge/keepsafe/taptargetview?axis=fork)](https://repopilot.app/r/keepsafe/taptargetview)

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

Onboarding doc

Onboarding: KeepSafe/TapTargetView

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/KeepSafe/TapTargetView 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 — Stale — last commit 2y ago

  • 26+ active contributors
  • Apache-2.0 licensed
  • ⚠ Stale — last commit 2y ago
  • ⚠ Concentrated ownership — top contributor handles 52% of recent commits
  • ⚠ No CI workflows detected
  • ⚠ No test directory 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 KeepSafe/TapTargetView repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/KeepSafe/TapTargetView.

What it runs against: a local clone of KeepSafe/TapTargetView — 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 KeepSafe/TapTargetView | 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 ≤ 607 days ago | Catches sudden abandonment since generation |

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

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "KeepSafe/TapTargetView(\\.git)?\\b" \\
  && ok "origin remote is KeepSafe/TapTargetView" \\
  || miss "origin remote is not KeepSafe/TapTargetView (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 "taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTargetView.java" \\
  && ok "taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTargetView.java" \\
  || miss "missing critical file: taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTargetView.java"
test -f "taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTarget.java" \\
  && ok "taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTarget.java" \\
  || miss "missing critical file: taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTarget.java"
test -f "taptargetview/src/main/java/com/getkeepsafe/taptargetview/ViewTapTarget.java" \\
  && ok "taptargetview/src/main/java/com/getkeepsafe/taptargetview/ViewTapTarget.java" \\
  || miss "missing critical file: taptargetview/src/main/java/com/getkeepsafe/taptargetview/ViewTapTarget.java"
test -f "taptargetview/src/main/java/com/getkeepsafe/taptargetview/ToolbarTapTarget.java" \\
  && ok "taptargetview/src/main/java/com/getkeepsafe/taptargetview/ToolbarTapTarget.java" \\
  || miss "missing critical file: taptargetview/src/main/java/com/getkeepsafe/taptargetview/ToolbarTapTarget.java"
test -f "taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTargetSequence.java" \\
  && ok "taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTargetSequence.java" \\
  || miss "missing critical file: taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTargetSequence.java"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 607 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~577d)"
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/KeepSafe/TapTargetView"
  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

TapTargetView is an Android library that implements Material Design's feature discovery tap targets—circular overlays with text that highlight UI elements to guide users through new features. It draws an outer dimmed circle with a centered target circle around a specified view, displaying title and description text to direct user attention without blocking interaction. Simple two-module structure: a core library module (taptargetview/) containing the View implementation, and an app module (app/src/main) with MainActivity.java demonstrating all features. The library exports TapTargetView (a custom View subclass) and TapTarget (a fluent builder); no complex state management or multiple packages.

👥Who it's for

Android app developers building feature discovery experiences who need Material Design-compliant onboarding without building custom overlay logic. Primarily used by apps requiring non-intrusive, accessible feature highlighting (e.g., KeepSafe, other Android apps at scale).

🌱Maturity & risk

Production-ready. The library is distributed via Maven Central with semantic versioning (see gradle/libs.versions.toml), has a clear RELEASING.md workflow, and supports API 14+. The codebase is 87KB of Java with a sample app in app/src/main/java/com/getkeepsafe/taptargetviewsample/. No recent commit data visible, but the stable Maven/JitPack presence and documented API suggest it's actively maintained by KeepSafe.

Low risk for stable usage, but limited by single-maintainer stewardship (KeepSafe org). The API surface is narrow (TapTargetView and TapTarget builder classes), reducing breaking-change surface. Dependency footprint is minimal—only androidx.appcompat and Material Design library in the sample app (see app/build.gradle). No visible CI/CD pipeline file (.github/workflows) hints at manual release process; this may slow critical security updates.

Active areas of work

No active development data visible in the provided file structure. The presence of CHANGELOG.md and README.md suggests releases are documented, but no recent PRs, issues, or milestones are shown. The repo appears to be in maintenance mode—stable and used, but not under active feature development.

🚀Get running

git clone https://github.com/KeepSafe/TapTargetView.git
cd TapTargetView
./gradlew build
./gradlew :app:installDebug  # or open in Android Studio and run the sample app

Daily commands: Open the project in Android Studio, select the 'app' build variant, and click Run. Or use ./gradlew :app:installDebug to build and deploy to a connected device/emulator. The sample MainActivity.java in app/src/main/java/com/getkeepsafe/taptargetviewsample/ demonstrates all API usage.

🗺️Map of the codebase

  • taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTargetView.java — Core custom View implementing the entire tap target overlay rendering, animation, and touch interaction logic—all feature discovery happens here.
  • taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTarget.java — Abstract base class defining the tap target specification (position, text, styling); all concrete targets inherit from this.
  • taptargetview/src/main/java/com/getkeepsafe/taptargetview/ViewTapTarget.java — Concrete TapTarget subclass that targets arbitrary Views; enables feature discovery on any UI element.
  • taptargetview/src/main/java/com/getkeepsafe/taptargetview/ToolbarTapTarget.java — Concrete TapTarget subclass that targets Toolbar menu items; specialized for toolbar-based discovery.
  • taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTargetSequence.java — Orchestrates sequential display of multiple tap targets in order; essential for multi-step feature discovery flows.
  • taptargetview/build.gradle — Library module configuration with Android SDK versions and dependency declarations; controls what's published to Maven Central.

🛠️How to make changes

Add a new Tap Target for a View

  1. Create a new TapTarget by calling ViewTapTarget.forView(view) with the View to highlight. (app/src/main/java/com/getkeepsafe/taptargetviewsample/MainActivity.java)
  2. Call .setTitle() and .setDescription() to add instructional text to the target. (taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTarget.java)
  3. Optionally customize colors with .setOuterCircleColor(), .setTargetCircleColor(), or .setTextColor(). (taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTarget.java)
  4. Pass the TapTarget to TapTargetView.showFor() or add to TapTargetSequence.addTarget() for sequential display. (taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTargetView.java)

Add a Toolbar menu item Tap Target

  1. Create a ToolbarTapTarget.forToolbarMenuItem(toolbar, menuItemId) pointing to your Toolbar and menu resource ID. (taptargetview/src/main/java/com/getkeepsafe/taptargetview/ToolbarTapTarget.java)
  2. Configure with .setTitle() and .setDescription() as needed. (taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTarget.java)
  3. Display via TapTargetView.showFor() or add to TapTargetSequence for multi-step flows. (taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTargetView.java)

Create a multi-step feature discovery flow

  1. Instantiate TapTargetSequence with a lifecycle owner (Activity or Fragment). (taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTargetSequence.java)
  2. Chain .addTarget(tapTarget1).addTarget(tapTarget2)... to define the sequence in order. (taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTargetSequence.java)
  3. Set .setOnSequenceFinishListener() callback to handle completion or cancellation. (taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTargetSequence.java)
  4. Call .start() to begin displaying targets; user navigates through by tapping. (taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTargetSequence.java)

🔧Why these technologies

  • Custom View + Canvas rendering — Provides pixel-perfect control over spotlight overlay and text layout; necessary for Material Design feature discovery visual spec
  • ValueAnimator — Enables smooth, frame-based animations of circle expansion and opacity without dependency on animation libraries
  • Reflection (ReflectUtil) — Allows targeting of Toolbar menu items that don't have direct View references; fragile but necessary for toolbar integration
  • Android Support Library (AppCompat, Material Components) — Ensures compatibility across Android versions and provides Material Design theming support

⚖️Trade-offs already made

  • Reflection for Toolbar menu item access

    • Why: Toolbar menu items are not directly accessible as Views in the public API
    • Consequence: Fragile across Android/library updates; may break on version changes; requires careful error handling
  • Single full-screen overlay View per target

    • Why: Simplifies rendering and touch event handling; clean separation of concerns
    • Consequence: Cannot show multiple simultaneous tap targets; requires sequential display for multi-target flows
  • No built-in persistence of viewed targets

    • Why: Keeps library minimal and focused on UI rendering
    • Consequence: Apps must implement their own tracking of which targets have been shown; risk of showing same target repeatedly
  • Min SDK 14 (legacy support)

    • Why: Broad device coverage when library was created
    • Consequence: Must avoid modern Android features; adds complexity for backward compatibility

🚫Non-goals (don't propose these)

  • Real-time analytics or event tracking (client app provides callbacks only)
  • Persistence of feature discovery state (no SharedPreferences/database integration)
  • Animated text rendering or advanced typography effects
  • Support for simultaneous multiple tap targets on screen
  • Built-in onboarding flow orchestration beyond sequential playback

🪤Traps & gotchas

No significant hidden traps. The minSdk 14 constraint is declared in gradle/libs.versions.toml—ensure your app targets API 14+. The library requires a parent ViewGroup in the Activity (TapTargetView.showFor() adds overlay to window); ensure your Activity does not use edge-to-edge fullscreen without proper overlay container. Proguard rules are pre-configured in app/proguard-rules.pro, but the core library rules are likely in the taptargetview/ module (not shown in file list) — check these if minification breaks the overlay.

🏗️Architecture

💡Concepts to learn

  • Canvas-based Custom View Drawing — TapTargetView extends Android View and uses Canvas.drawCircle() to render concentric circles; understanding invalidate(), onDraw(), and Paint styling is core to modifying the visual appearance.
  • Builder Pattern — The TapTarget class uses a fluent builder chain (outerCircleColor().targetCircleColor()...) to configure overlay behavior; this is essential to understanding the API and extending it with new options.
  • Window-level Overlay / DecorView Integration — TapTargetView.showFor() must attach the overlay to the Activity's window (DecorView) to render above all other views; understanding this prevents z-order issues and interaction blocking.
  • Touch Event Interception & Propagation — The library allows tapping the target or canceling outside the outer circle (cancelable option); implementing correct onTouchEvent() and delegating to child views requires understanding Android's event dispatch chain.
  • Alpha Compositing & Dimming (outerCircleAlpha, dimColor) — The outer circle and dimming effect use Paint alpha blending (setAlpha(), PorterDuff modes); tweaking these requires knowledge of Android's compositing model to avoid visual artifacts.
  • Typeface & Text Rendering (TextPaint, drawText) — The library renders title and description text with custom sizes, colors, and typefaces; the TapTarget.textTypeface() and TextPaint configuration affect layout and appearance.
  • Material Design Feature Discovery UX Pattern — TapTargetView is a direct implementation of Google's Material Design guidelines for feature discovery; understanding the UX intent (highlight, guide, not block) is essential for using the library correctly in app flows.
  • material-components/material-components-android — Official Material Design library for Android; TapTargetView implements custom overlays atop Material Design guidelines
  • amlcurran/Showdown — Alternative Android feature discovery library using spotlight/circular highlight pattern; direct competitor with similar use case
  • Tapadoo/Alerter — Android alert/notification library; complementary for non-modal feature communication alongside tap targets
  • google/material-design-lite — Original Material Design web implementation; TapTargetView adapts the web 'Feature Discovery' pattern to Android

🪄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 unit tests for TapTargetView core functionality

The repo has no visible test directory despite having complex animation and UI logic in taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTargetView.java, TapTargetSequence.java, and FloatValueAnimatorBuilder.java. Adding instrumented tests would improve reliability for feature discovery animations, tap detection, and state management across Android API levels.

  • [ ] Create taptargetview/src/androidTest/java/com/getkeepsafe/taptargetview/ directory structure
  • [ ] Add instrumented tests for TapTargetView lifecycle (show/dismiss animations)
  • [ ] Add tests for TapTargetSequence sequential display and callbacks
  • [ ] Add tests for FloatValueAnimatorBuilder animation values
  • [ ] Set up test dependencies in taptargetview/build.gradle (AndroidX Test, Espresso)
  • [ ] Document test setup in .github/CONTRIBUTING.md

Add GitHub Actions CI workflow for automated testing and lint checks

The repo lacks CI automation. With a sample app (app/) and library module (taptargetview/), a GitHub Actions workflow would catch regressions early. Currently RELEASING.md and CONTRIBUTING.md exist but there's no .github/workflows/ directory, so contributors can't verify their changes pass checks before submission.

  • [ ] Create .github/workflows/ci.yml with Android build matrix (API 21+, 28+, latest)
  • [ ] Add Gradle lint and unit test steps in the workflow
  • [ ] Run ./gradlew build, ./gradlew lint, ./gradlew test for both app and taptargetview modules
  • [ ] Configure workflow to trigger on PR and push to main branches
  • [ ] Document CI requirements in .github/CONTRIBUTING.md

Add ProGuard/R8 configuration tests for taptargetview library

The app has proguard-rules.pro but the core library taptargetview/ lacks a build.gradle configuration for consumer ProGuard rules. Since TapTargetView uses reflection (ReflectUtil.java exists), shrinking/obfuscation could break it. Apps using this library need proper R8/ProGuard keep rules distributed with the AAR.

  • [ ] Create taptargetview/proguard-rules.pro with keep rules for TapTargetView, TapTarget, TapTargetSequence public APIs
  • [ ] Add keep rules for ReflectUtil.java reflection targets
  • [ ] Configure taptargetview/build.gradle to consume and distribute proguard-rules.pro in AAR
  • [ ] Add consumerProguardFiles configuration to taptargetview/build.gradle
  • [ ] Document ProGuard setup in README.md and CONTRIBUTING.md

🌿Good first issues

  • Add unit tests for TapTarget builder validation (e.g., null checks for view, title, description); currently no test directory visible in the file structure.
  • Document accessibility features (TalkBack support) with a code example in README.md or add a new 'Accessibility' section to show how to set content descriptions on tap targets.
  • Create a detailed Javadoc comment block for the TapTargetView.showFor() static method in the core library module, explaining the lifecycle, cancellation behavior, and listener callback timing with code examples.

Top contributors

Click to expand

📝Recent commits

Click to expand
  • 101e89d — Release version 1.15.0 (emarc-m)
  • 06a93c1 — Support Force Centered Target (#409) (dylan-keepsafe)
  • f4363a6 — updated releasing guide (emarc-m)
  • 5123886 — Release version 1.14.0 (emarc-m)
  • 726d85e — configured plugin for publishing (emarc-m)
  • 11ea0b5 — Modernize project (#407) (dylan-keepsafe)
  • e08def0 — Release version 1.13.3 (emarc-m)
  • 6fba8cd — Remove all jcenter dependencies (#388) (emarc-m)
  • df697f2 — updated releasing guide (emarc-m)
  • bb9c8ad — Release version 1.13.2 (emarc-m)

🔒Security observations

The TapTargetView codebase demonstrates reasonable security practices as a UI library with minimal external dependencies. Primary concerns are: (1) Code obfuscation is disabled in release builds, increasing reverse engineering risk, (2) Reflection utilities require validation review, (3) Debug tools (Stetho) included in production dependencies, and (4) Missing network security hardening. No critical vulnerabilities detected such as hardcoded secrets, SQL injection risks, or XSS vectors. The library appears to be well-maintained with no apparent injection attacks or credential leakage in the provided file structure.

  • Medium · Use of Reflection Utility Without Validation — taptargetview/src/main/java/com/getkeepsafe/taptargetview/ReflectUtil.java. The codebase includes a ReflectUtil.java file which performs reflection operations. Reflection can be exploited if not properly validated, potentially allowing access to private members or methods that should not be exposed. The file structure suggests reflection is being used, which increases attack surface if input is not properly sanitized. Fix: Review ReflectUtil.java to ensure all reflective operations validate inputs, use allowlists for accessible classes/methods, and implement proper exception handling. Consider minimizing reflection usage where possible.
  • Medium · Minification Disabled in Release Build — app/build.gradle. The app/build.gradle file shows that minifyEnabled is set to false in the release build type. This disables ProGuard/R8 obfuscation, making the compiled code more vulnerable to reverse engineering and decompilation attacks. Fix: Set minifyEnabled to true in the release buildType to enable code obfuscation and shrinking: minifyEnabled true
  • Low · Missing Network Security Configuration — app/src/main/res/. No network security configuration file is visible in the res/xml directory. While the app targets Material Design guidelines, lack of explicit network security policy could allow unencrypted HTTP connections depending on targetSdk level. Fix: Create a network_security_config.xml file in res/xml/ that enforces HTTPS and pins certificates if communicating with known endpoints. Configure appropriate domain policies.
  • Low · Potential Debugging Inclusion (Stetho Dependency) — app/build.gradle - dependencies. The app includes 'libs.stetho' as a dependency, which is a debugging bridge for Android applications. While useful for development, including debug tools in production builds can expose sensitive information about app structure and data. Fix: Move stetho dependency to debugImplementation instead of implementation to exclude it from release builds: debugImplementation libs.stetho
  • Low · No Explicit ProGuard Rules for Library — taptargetview/. The taptargetview library module does not show a proguard-rules.pro file, which could lead to important classes being obfuscated incorrectly or exposed when included as a dependency in other apps. Fix: Create a proguard-rules.pro file in the taptargetview module to specify which public API classes should be preserved and protected.

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.

Mixed signals · KeepSafe/TapTargetView — RepoPilot