# MPAndroidChart Admin & Developer Guide

This guide is the architectural and operational reference for MPAndroidChart — for developers integrating it deeply, architects evaluating it, and contributors extending it. It covers the internal design, the rendering pipeline, the coordinate-transform system, extension points, performance characteristics, security considerations, and the contribution workflow.

For day-to-day usage (drawing each chart type, configuring axes, handling gestures), see the companion **User Guide**.

---

## Table of Contents

1. [Executive Summary](#1-executive-summary)
2. [Architecture Overview](#2-architecture-overview)
3. [Requirements & Build Configuration](#3-requirements--build-configuration)
4. [Repository Structure](#4-repository-structure)
5. [The Rendering Pipeline](#5-the-rendering-pipeline)
6. [The Coordinate-Transform System](#6-the-coordinate-transform-system)
7. [Class Hierarchies (Module Reference)](#7-class-hierarchies-module-reference)
8. [Extension Points](#8-extension-points)
9. [Performance Engineering](#9-performance-engineering)
10. [Security Analysis](#10-security-analysis)
11. [Testing Strategy](#11-testing-strategy)
12. [Integration & Deployment](#12-integration--deployment)
13. [Contributing](#13-contributing)
14. [Known Limitations & Improvement Opportunities](#14-known-limitations--improvement-opportunities)
15. [Quick Reference](#15-quick-reference)

---

## 1. Executive Summary

**MPAndroidChart** is a self-contained Android charting library that renders charts directly onto a `Canvas` using the Android 2D graphics API. It ships nine chart types (line, bar, horizontal bar, pie, scatter, bubble, candlestick, radar, combined) as `View` subclasses that integrate into standard Android layouts.

| Attribute | Value |
|---|---|
| Library version | 3.1.0 |
| Group / artifact | `com.github.philjay` / `MPAndroidChart` (consumed via JitPack as `com.github.PhilJay:MPAndroidChart:v3.1.0`) |
| Language | Java |
| Min SDK / Target SDK | 14 / 28 |
| Compile SDK | 28 |
| Runtime dependencies | `androidx.annotation:annotation` only |
| Test dependencies | `junit:junit:4.12` |
| License | Apache License 2.0 |
| Build system | Gradle (Android Gradle Plugin 7.0.4) |
| Distribution | JitPack (source-built AAR) |

**Architectural essence:** the library cleanly separates four concerns — **data** (what to draw), **chart views** (the public API and lifecycle), **renderers** (how to paint it), and **coordinate transforms** (where pixels go). This separation is what allows the same gesture, animation, and axis machinery to serve every chart type, and it is the seam along which the library is extended.

> [!NOTE]
> There is **no networking, persistence, reflection, or dynamic code loading** anywhere in the library. It is a pure, offline rendering component. This sharply narrows its security and dependency surface (see [Security Analysis](#10-security-analysis)).

---

## 2. Architecture Overview

The library is built around a Model–View–Renderer decomposition, with a dedicated coordinate-transform layer underneath.

```text
                         ┌─────────────────────────────────────────────┐
                         │            Chart (extends ViewGroup)         │
   YOUR DATA             │   public API · lifecycle · onDraw() · touch  │
  ┌──────────┐  setData  │                                              │
  │ ChartData │ ────────►│  ┌────────────┐   ┌──────────────────────┐   │
  │  ▲        │          │  │ Animator   │   │ ChartTouchListener   │   │
  │  │ holds  │          │  │ (Easing)   │   │ (drag/zoom/highlight)│   │
  │ DataSet[] │          │  └────────────┘   └──────────────────────┘   │
  │  ▲        │          │         │ onDraw() orchestrates:             │
  │  │ holds  │          │         ▼                                    │
  │ Entry[]   │          │  ┌────────────┐  ┌────────────┐  ┌────────┐  │
  └──────────┘          │  │DataRenderer│  │AxisRenderer│  │Legend  │  │
                         │  └─────┬──────┘  └─────┬──────┘  │Renderer│  │
                         │        │               │         └────────┘  │
                         │        ▼               ▼                     │
                         │   ┌─────────────────────────────────────┐   │
                         │   │ Transformer  +  ViewPortHandler      │   │
                         │   │ (value↔pixel matrices, zoom/pan)     │   │
                         │   └─────────────────────────────────────┘   │
                         │                    │                         │
                         │                    ▼                         │
                         │              Android Canvas                  │
                         └─────────────────────────────────────────────┘
```

### The four layers

| Layer | Responsibility | Key classes |
|---|---|---|
| **Data model** | Holds values and per-series styling; computes min/max. | `ChartData`, `BaseDataSet`/`DataSet`, `Entry`/`BaseEntry` |
| **Chart views** | Public API, Android `View` lifecycle, dispatching draw, handling touch. | `Chart`, `BarLineChartBase`, `PieRadarChartBase`, the 9 concrete charts |
| **Renderers** | Paint data, axes, legend, grid, limit lines, markers onto the `Canvas`. | `DataRenderer` (+ subclasses), `AxisRenderer`, `LegendRenderer` |
| **Transform** | Convert data values to screen pixels and back; manage zoom/pan state. | `Transformer`, `ViewPortHandler` |

### Two parallel chart families

The chart hierarchy splits early into two families with fundamentally different geometry:

- **Cartesian charts** (`BarLineChartBase`): line, bar, horizontal bar, scatter, bubble, candlestick, combined. They have X and dual Y axes, support drag/pinch-zoom, and use `Transformer` matrices.
- **Radial charts** (`PieRadarChartBase`): pie and radar. They have a center, a rotation angle, and angular/distance math instead of axis transforms.

This bifurcation is the single most important fact for understanding why some features (zoom, dual axes) exist only on some charts.

---

## 3. Requirements & Build Configuration

### Library module (`MPChartLib/build.gradle`)

```gradle
apply plugin: 'com.android.library'
group = 'com.github.philjay'

android {
    compileSdkVersion 28
    buildToolsVersion '28.0.3'
    defaultConfig {
        minSdkVersion 14
        targetSdkVersion 28
        versionCode 3
        versionName '3.1.0'
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    testOptions {
        unitTests.returnDefaultValues = true   // allows JVM unit tests without mocking Android
    }
}

dependencies {
    implementation 'androidx.annotation:annotation:1.0.0'
    testImplementation 'junit:junit:4.12'
}
```

The build also defines `sourcesJar`, `javadoc`, and `javadocJar` tasks, publishing sources and Javadoc alongside the AAR — which is how JitPack serves the `-sources` and `-javadoc` artifacts.

### Project requirements (`gradle.properties`)

```properties
android.enableJetifier=true
android.useAndroidX=true
org.gradle.jvmargs=-Xmx2048M
```

> [!IMPORTANT]
> The library is AndroidX-based. Consuming projects must have `android.useAndroidX=true`. The `proguard-rules.pro` file ships empty — the library has no special keep-rules, because it uses no reflection. Standard R8/ProGuard shrinking is safe without custom configuration.

---

## 4. Repository Structure

```text
MPAndroidChart/
├── MPChartLib/                        # the published library module
│   └── src/main/java/com/github/mikephil/charting/
│       ├── charts/        (12 files)  # public View classes + 2 base classes
│       ├── data/          (29 files)  # ChartData, DataSet, Entry families
│       ├── components/    (11 files)  # XAxis, YAxis, Legend, LimitLine, Description, MarkerView
│       ├── interfaces/                # data-provider + dataset interfaces (decoupling)
│       │   ├── dataprovider/ (8)
│       │   └── datasets/     (11)
│       ├── renderer/      (22 + 8)    # all painting logic (+ scatter shape renderers)
│       ├── highlight/     (10 files)  # touch-to-value hit testing
│       ├── formatter/     (11 files)  # value & axis label formatting
│       ├── listener/      (7 files)   # touch & gesture listeners
│       ├── animation/     (2 files)   # ChartAnimator, Easing
│       ├── jobs/          (6 files)   # pooled viewport-animation jobs
│       ├── buffer/        (3 files)   # reusable draw buffers
│       ├── utils/         (13 files)  # transforms, pools, color templates, geometry
│       ├── matrix/, model/, exception/
│       └── (test) src/test/...        # 7 JUnit test classes
├── MPChartExample/                    # demo app (not published) — 30+ example activities
├── design/, screenshots/              # marketing assets
├── README.md, CONTRIBUTING.md, LICENSE
└── build.gradle, settings.gradle, gradle/
```

The `MPChartExample` app is the de-facto integration test and living documentation: each activity (e.g. `LineChartActivity1`, `PieChartActivity`, `CombinedChartActivity`) demonstrates one chart type with sliders that mutate the data live.

---

## 5. The Rendering Pipeline

All drawing happens inside the chart's overridden `onDraw(Canvas)`. The base `Chart.onDraw()` handles the empty-data placeholder and one-time offset calculation; each family then orchestrates its renderers in a fixed order.

### Cartesian render order (`BarLineChartBase.onDraw`)

1. `drawGridBackground()` — optional grey backdrop + borders.
2. Auto-scale Y axis if `setAutoScaleMinMaxEnabled(true)`.
3. Compute axis intervals (`AxisRenderer.computeAxis`) for X, left Y, right Y.
4. Render axis lines, then grid lines (order depends on `setDrawGridLinesBehindData`).
5. Render limit lines behind data (if configured).
6. **Clip to content rect** (unless disabled) and `mRenderer.drawData(canvas)` — the actual series.
7. Draw highlighted values (`drawHighlighted`) if anything is selected.
8. `drawExtras()`, then limit lines on top, then axis labels.
9. `drawValues()` — per-point value text.
10. `LegendRenderer.renderLegend()`, then description, then markers.

> [!NOTE]
> The library tracks per-frame draw time when `setLogEnabled(true)` is set, logging average draw time and cycle count. This is the built-in profiling hook for diagnosing slow charts.

### Renderer class family

```text
Renderer (base, holds ViewPortHandler)
├── DataRenderer (abstract: drawData/drawValues/drawHighlighted/drawExtras + paints)
│   ├── LineRadarRenderer ──► LineChartRenderer, RadarChartRenderer
│   ├── BarLineScatterCandleBubbleRenderer
│   │     ├── BarChartRenderer ──► HorizontalBarChartRenderer
│   │     ├── ScatterChartRenderer, CandleStickChartRenderer, BubbleChartRenderer
│   ├── PieChartRenderer
│   └── CombinedChartRenderer (delegates to a list of sub-renderers)
├── AxisRenderer ──► XAxisRenderer, YAxisRenderer (+ HorizontalBarChart / RadarChart variants)
└── LegendRenderer
```

Scatter shapes are themselves pluggable: `IShapeRenderer` has implementations `CircleShapeRenderer`, `SquareShapeRenderer`, `TriangleShapeRenderer`, `CrossShapeRenderer`, `XShapeRenderer`, `ChevronUpShapeRenderer`, `ChevronDownShapeRenderer`. You can supply your own via `ScatterDataSet.setShapeRenderer()`.

---

## 6. The Coordinate-Transform System

The most architecturally significant subsystem. Two cooperating classes convert between **data space** (your `Entry` x/y values) and **pixel space** (screen coordinates), and manage zoom/pan.

### `ViewPortHandler`

Owns a `Matrix` (`mMatrixTouch`) representing the current zoom and translation, plus the content rectangle (the drawable area inside the axis margins). It enforces zoom/scroll limits.

| Concern | Methods |
|---|---|
| Dimensions | `setChartDimens()`, `restrainViewPort()` |
| Zoom | `zoomIn/Out`, `zoom`, `setZoom`, `fitScreen`, `resetZoom` |
| Limits | `setMinimumScaleX/Y`, `setMaximumScaleX/Y`, `setMinMaxScaleX/Y` |
| Translate | `translate`, `centerViewPort`, `limitTransAndScale` |
| Drag bounds | `setDragOffsetX/Y` |

### `Transformer`

Holds two matrices — `mMatrixValueToPx` (data→pixels) and `mMatrixOffset` (applies the content offset) — combined with the `ViewPortHandler`'s touch matrix. This is what `chart.getPixelForValues()` and `chart.getValuesByTouchPoint()` use.

```text
data value (x, y)
   │  mMatrixValueToPx     (scale to content size, flip Y)
   ▼
   │  ViewPortHandler.mMatrixTouch   (apply user zoom + pan)
   ▼
   │  mMatrixOffset        (shift into the content rect)
   ▼
screen pixel
```

Cartesian charts keep **two** transformers — `mLeftAxisTransformer` and `mRightAxisTransformer` — so the left and right Y axes can have independent scales. `HorizontalBarChart` swaps in a `TransformerHorizontalBarChart` and `HorizontalViewPortHandler` to achieve the 90° rotation without changing any data code.

> [!TIP]
> When debugging "my point is in the wrong place," the issue is almost always in the transform chain: check which `AxisDependency` the dataset uses, and whether the axis min/max were set manually (which fixes the value-to-pixel scale).

---

## 7. Class Hierarchies (Module Reference)

### Chart views

```text
View → ViewGroup → Chart<T extends ChartData>  (implements ChartInterface)
   ├── BarLineChartBase<T>  (implements BarLineScatterCandleBubbleDataProvider)
   │     ├── LineChart, BarChart → HorizontalBarChart
   │     ├── ScatterChart, BubbleChart, CandleStickChart
   │     └── CombinedChart
   └── PieRadarChartBase<T>
         ├── PieChart
         └── RadarChart
```

`Chart` provides the cross-cutting API: `setData`, `invalidate`, highlighting, markers, animation, description/legend access, image export, and offset management. `BarLineChartBase` adds axes, zoom/pan, and viewport jobs. `PieRadarChartBase` adds rotation and angular geometry.

### Data model

```text
BaseEntry (y, data, icon)
   └── Entry (adds x)  → BarEntry, BubbleEntry, CandleEntry, PieEntry, RadarEntry

IDataSet → BaseDataSet → DataSet
   └── LineScatterCandleRadarDataSet → LineRadarDataSet → LineDataSet / RadarDataSet
   └── BarLineScatterCandleBubbleDataSet → BarDataSet, ScatterDataSet, CandleDataSet, BubbleDataSet
   └── PieDataSet

ChartData → BarLineScatterCandleBubbleData → {Bar,Line,Scatter,Candle,Bubble}Data
         └── PieData, RadarData, CombinedData
```

> [!NOTE]
> Charts depend on **interfaces** (`ILineDataSet`, `LineDataProvider`, etc.), not concrete classes. This `interfaces/dataprovider` + `interfaces/datasets` indirection is what lets `CombinedChart` reuse the line/bar/scatter renderers, and lets you substitute custom dataset implementations.

### Supporting subsystems

| Subsystem | Classes | Purpose |
|---|---|---|
| Highlighting | `ChartHighlighter` + per-type (`Bar`, `Pie`, `Radar`, `Combined`, …), `Highlight`, `Range` | Map a touch point to the nearest entry. |
| Touch | `ChartTouchListener` → `BarLineChartTouchListener`, `PieRadarChartTouchListener` | Gesture state machines. |
| Animation | `ChartAnimator`, `Easing` (30+ `EasingFunction`s) | Phase-based value animation. |
| Viewport jobs | `ViewPortJob` → `MoveViewJob`, `ZoomJob`, `AnimatedMoveViewJob`, `AnimatedZoomJob` | Deferred/animated viewport changes, object-pooled. |
| Formatters | `IValueFormatter`/`IAxisValueFormatter` + `LargeValueFormatter`, `PercentFormatter`, `IndexAxisValueFormatter`, `StackedValueFormatter` | Label text generation. |
| Utilities | `ColorTemplate`, `Fill`, `MPPointF`, `MPPointD`, `ObjectPool`, `Utils`, `FSize`, `EntryXComparator` | Colors, pooled geometry, dp conversion. |

---

## 8. Extension Points

The library is designed to be extended without forking. The principal seams:

| To customize… | Override / supply | Set via |
|---|---|---|
| How a series is painted | A `DataRenderer` subclass | `chart.setRenderer(...)` |
| Axis painting | `XAxisRenderer` / `YAxisRenderer` subclass | `chart.setXAxisRenderer(...)`, `setRendererLeftYAxis(...)` |
| Scatter point shape | `IShapeRenderer` implementation | `scatterDataSet.setShapeRenderer(...)` |
| Value / axis label text | `IValueFormatter` / `IAxisValueFormatter` | `dataSet.setValueFormatter(...)`, `axis.setValueFormatter(...)` |
| Fill position under a line | `IFillFormatter` | `lineDataSet.setFillFormatter(...)` |
| Hit-testing logic | `IHighlighter` implementation | `chart.setHighlighter(...)` |
| Tooltip content/layout | `MarkerView` subclass (or raw `IMarker`) | `chart.setMarker(...)` |
| A custom dataset backing store | implement `I*DataSet` | pass to the matching `*Data` |

This interface-first design (every collaborator is referenced through an interface) is the architectural property that makes the library so extensible despite being a closed AAR.

---

## 9. Performance Engineering

Charting redraws the entire view every frame during gestures, so the library invests heavily in allocation avoidance.

- **Reusable draw buffers** (`buffer/AbstractBuffer` and subclasses): the bar/line renderers pre-fill a flat `float[]` of `x,y,x,y,…` coordinates and **replace rather than recreate** it each frame. The class comment is explicit: *"Concept: Replace instead of recreate … This needs to run FAST."*
- **Object pooling** (`utils/ObjectPool`, `MPPointF`, `MPPointD`): geometry points are borrowed from pools (`MPPointF.getInstance(...)`) and returned (`MPPointF.recycleInstance(...)`), keeping per-frame allocation near zero to avoid GC pauses.
- **Viewport clipping**: data is clipped to the content rect (`setClipDataToContent`, default on) so off-screen geometry isn't painted.
- **Visible-range windowing**: `setVisibleXRangeMaximum()` + `moveViewToX()` let large datasets render only a slice.
- **Value-label suppression**: `mMaxVisibleCount` (default 100) automatically stops drawing value labels when too many entries are visible.

### Performance trade-offs to document for operators

| Setting | Cost |
|---|---|
| `setDrawBarShadow(true)` | ~50% slower bar rendering |
| `enableDashedLine(...)` | Requires hardware acceleration **off** (slower overall) |
| `TRIANGLE` scatter shape | Slowest shape; prefer `CIRCLE`/`SQUARE` |
| Drawing value labels | Per-point text layout each frame; disable for dense data |
| `setHardwareAccelerationEnabled(false)` | Needed for some effects, but disables GPU compositing |

> [!WARNING]
> All values are stored as 32-bit `float`. For large magnitudes or high precision (currency, epoch-millis), precision is lost. Normalize/scale data into a friendly range and use a formatter to display real magnitudes. There is no `double`/`BigDecimal` path.

---

## 10. Security Analysis

MPAndroidChart has an exceptionally small attack surface for an Android library.

| Concern | Finding |
|---|---|
| Network access | **None.** No HTTP, sockets, or URL usage in the library. |
| Reflection / dynamic loading | **None.** Hence the empty ProGuard rules — safe to shrink/obfuscate. |
| Permissions required | **None for rendering.** Only `saveToGallery()`/`saveToPath()` need `WRITE_EXTERNAL_STORAGE`. |
| File system writes | Only via the explicit image-export methods, into external storage. |
| Untrusted input | Charts render numeric data only; there is no parser/eval path to exploit. |
| Dependencies | One runtime dep (`androidx.annotation`) — minimal supply-chain exposure. |

### Hardening guidance

- **Storage permission:** `saveToGallery()` writes to `Environment.getExternalStorageDirectory()` using the legacy storage model. On Android 10+ (scoped storage), this path is restricted; if you export images, prefer capturing `getChartBitmap()` and writing through `MediaStore`/`Storage Access Framework` yourself, and request the runtime permission on API 23+.
- **No data leaves the device** through this library — any analytics/telemetry would be in your own code, not here.
- **Obfuscation** is fully supported; do not add reflective keep-rules (none are needed).

> [!IMPORTANT]
> The only OS-version-sensitive code path is image export (legacy external-storage API). Treat it as the single integration point requiring permission handling and scoped-storage awareness on modern Android.

---

## 11. Testing Strategy

The library ships **7 JVM JUnit 4 tests** under `MPChartLib/src/test/`:

| Test | Covers |
|---|---|
| `ApproximatorTest` | Data reduction / Douglas-Peucker approximation. |
| `AxisRendererTest` | Axis interval computation. |
| `BarDataTest` | Bar data min/max and grouping math. |
| `ChartDataTest` | Multi-dataset aggregation, min/max across sets. |
| `DataSetTest` | Entry insertion/ordering, binary search by x. |
| `LargeValueFormatterTest` | `1.2k`/`3.4m` formatting. |
| `ObjectPoolTest` | Pool borrow/recycle correctness. |

Tests run on the JVM (no instrumented device) thanks to `testOptions.unitTests.returnDefaultValues = true`, which stubs Android framework calls. Coverage is concentrated on **pure-logic** components (data math, formatters, pools); rendering and gesture code is validated manually through the example app.

> [!NOTE]
> The contribution guidelines require testing changes by **actually running the example app** (or adding a new example activity), reflecting the reality that visual/gesture behavior is not unit-testable here.

---

## 12. Integration & Deployment

### Consuming the library

The library is **not on Maven Central**; JitPack builds the AAR from the tagged source on first request. Consumers must add the JitPack repository (see User Guide → Installation). Pinning a release tag (`v3.1.0`) ensures a cached, reproducible build rather than a freshly compiled `-SNAPSHOT`.

### Embedding a chart

A chart is a plain `View`. Two integration modes:

=== "XML layout"

    ```xml
    <com.github.mikephil.charting.charts.LineChart
        android:id="@+id/chart"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    ```

=== "Programmatic"

    ```java
    LineChart chart = new LineChart(context);
    container.addView(chart);
    ```

=== "Jetpack Compose"

    ```kotlin
    AndroidView(factory = { ctx -> LineChart(ctx) }, update = { it.data = lineData; it.invalidate() })
    ```

### Lifecycle considerations

- Charts hold bitmaps in some renderers; `LineChart`/`PieChart` release them in `onDetachedFromWindow()`.
- For memory-tight screens, enable `chart.setUnbindEnabled(true)` to unbind drawables on detach, and call `chart.clear()` when discarding data.
- `setKeepPositionOnRotation(true)` preserves zoom/scroll across configuration changes.

---

## 13. Contributing

The project accepts community PRs under a defined workflow (`CONTRIBUTING.md`):

- [ ] Search existing issues and PRs before starting.
- [ ] Fork; branch from `master`, named for the change.
- [ ] Make commits of logical units; conform to the surrounding code style.
- [ ] Commit titles ≤ 50 characters; body after a blank line for non-obvious changes.
- [ ] **Test by running the example app**, or add a new example activity demonstrating the change.
- [ ] Open a PR following the auto-generated template.

Issue templates exist for **bugs** and **feature requests** — the maintainers ask that "how do I…" questions go to Stack Overflow (`mpandroidchart` tag), not the issue tracker.

> [!NOTE]
> The repository also documents that this is the **Android** library; the iOS sibling is [danielgindi/Charts](https://github.com/danielgindi/Charts), which mirrors the same architecture in Swift.

---

## 14. Known Limitations & Improvement Opportunities

Derived from the source and the community issue tracker:

- **`float`-only precision.** No `double`/`BigDecimal` support. Repeatedly reported (huge values rendering wrong, lost precision in `CandleEntry`, requests for `BigDecimal` in `BarEntry`). The fix would be invasive — the entire data model and transform matrices are `float`-based.
- **No Jetpack Compose API.** Compose users must wrap charts in `AndroidView`. A first-class Compose surface is a long-standing feature request.
- **Legacy external-storage image export.** `saveToGallery()` predates scoped storage; modernizing it to `MediaStore` would remove the `WRITE_EXTERNAL_STORAGE` requirement on API 29+.
- **Accessibility gaps.** TalkBack/screen-reader support for selecting individual bars/slices is limited — a noted issue for a11y-sensitive apps.
- **Targets API 28.** `compileSdkVersion`/`targetSdkVersion 28` predate current Play Store target-API requirements; consuming apps set their own target SDK, but the library's own modernization (AGP, SDK levels) lags.
- **Dashed lines vs. hardware acceleration.** The requirement to disable HW acceleration for dashes is a usability sharp edge inherent to the Android `Canvas` API.
- **Manual rendering tests.** No instrumented/screenshot tests; visual regressions can only be caught by running the example app.

---

## 15. Quick Reference

### Package map

| Package | Role |
|---|---|
| `charts` | Public `View` classes + 2 base classes |
| `data` | `ChartData`, `DataSet`, `Entry` families |
| `components` | Axes, legend, limit lines, description, markers |
| `interfaces` | Dataset + data-provider interfaces (decoupling) |
| `renderer` | All `Canvas` painting (+ `scatter/` shape renderers) |
| `highlight` | Touch-to-value hit testing |
| `formatter` | Value & axis label formatting |
| `listener` | Touch / gesture listeners |
| `animation` | `ChartAnimator`, `Easing` |
| `jobs` | Pooled viewport-animation jobs |
| `buffer` | Reusable draw buffers |
| `utils` | Transforms, pools, color templates, geometry |

### Extension cheat sheet

| Override | Interface/class | Setter |
|---|---|---|
| Series painting | `DataRenderer` | `setRenderer` |
| Axis painting | `AxisRenderer` | `setXAxisRenderer` / `setRendererLeftYAxis` |
| Scatter shape | `IShapeRenderer` | `setShapeRenderer` |
| Value text | `IValueFormatter` | `setValueFormatter` |
| Axis text | `IAxisValueFormatter` | `setValueFormatter` (on axis) |
| Hit testing | `IHighlighter` | `setHighlighter` |
| Tooltip | `MarkerView` | `setMarker` |

### Key facts

| Fact | Value |
|---|---|
| Min SDK | 14 |
| Animations require | API 11+ |
| Runtime deps | `androidx.annotation` only |
| Value type | 32-bit `float` |
| Permissions | none (except image export) |
| Reflection | none (empty ProGuard rules) |
| License | Apache 2.0 |

---

_Generated June 2026 from PhilJay/MPAndroidChart at 9c7275a. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
