Androidplot

repository·master·Indexed 19 days ago

https://github.com/halfhp/androidplot

A library for creating high-quality, customizable dynamic and static charts in Android applications. It supports various plot types including Line, Scatter, Bar, Pie, Step, Candlestick, and Bubble charts. Compatible with Android 1.6+, Kotlin, Java, and Jetpack Compose, it features built-in pan and zoom interactivity and provides specialized series implementations like FixedSizeEditableXYSeries, FastXYSeries, and SampledXYSeries for optimizing performance with large or high-frequency datasets.

Tokens
15.9K
Snippets
39
Records
68
Agent score
68%

What's inside androidplot

  1. Overview of Androidplot features

    master

    Androidplot is a library for creating both dynamic and static charts in Android applications. It supports a wide variety of chart types and interactive features.

    Supported Chart Types:

    • Line Charts
    • Scatter Charts
    • Bar Charts
    • Pie Charts
    • Step Charts
    • Candlestick Charts
    • Bubble Charts

    Key Features:

    • Dynamic Plots: Support for data that changes over time.
    • Interactivity: Built-in support for Pan & Zoom.
    • Compatibility: Works with Android 1.6+, Kotlin, Java, and is compatible with Jetpack Compose.
  2. Choose the right XYSeriesRenderer

    master

    Androidplot provides different renderers for XYSeries depending on your performance and feature requirements:

    • LineAndPointRenderer: The standard, robust, and optimized renderer for most use cases.
    • FastLineAndPointRenderer: Optimized for high-performance apps displaying large amounts of dynamic data where fast refresh rates are critical.
    • AdvancedLineAndPointRenderer: Supports advanced features like dynamically coloring individual line segments. Refer to the ECGExample in the demo app for implementation details.
  3. How custom renderers work in Androidplot

    master

    Androidplot allows you to extend visual functionality by creating custom renderers. This process involves two main components that work together:

    1. Formatter: A class that extends a base formatter (e.g., BarFormatter). It serves two purposes: providing visual configuration (like colors and paints) and acting as a factory that maps a series to a specific renderer type via getRendererClass() and doGetRendererInstance(XYPlot).
    2. Renderer: A class that extends a base renderer (e.g., BarRenderer). It contains the actual drawing logic. You typically override specific drawing methods (like drawBar) to implement custom shapes or styles using the Android Canvas API.

    When you add a series to a plot using your custom Formatter, Androidplot uses the Formatter to instantiate and use your custom Renderer for that series.

    // The Formatter links the series to the Renderer
    class MyFormatter extends BarFormatter {
        @Override
        public Class<MyRenderer> getRendererClass() {
            return MyRenderer.class;
        }
    
        @Override
        public MyRenderer doGetRendererInstance(XYPlot xyPlot) {
            return new MyRenderer(xyPlot);
        }
    }
    
    // The Renderer performs the custom drawing
    class MyRenderer extends BarRenderer<MyFormatter> {
        public MyRenderer(XYPlot plot) {
            super(plot);
        }
    }
  4. How Plot composition and Widgets work

    master

    All plots in Androidplot inherit from the abstract base class Plot. A Plot is composed of one or more Widget instances, which are visual components that can be positioned and scaled within the plot's visible area.

    For example, an XYPlot typically includes these widgets:

    • Title
    • Graph
    • Domain Label
    • Range Label
    • Legend

    Every Plot implementation contains at least one default Widget providing its core behavior. Developers can extend these widgets and replace the default instance with a derived implementation to achieve custom behavior.

  5. Configure legend layout with TableModel

    master

    The TableModel determines how legend items are organized into a grid. All TableModel implementations use a TableOrder to decide how items are populated:

    • TableOrder.ROW_MAJOR: Items are added left-to-right, then top-down.
    • TableOrder.COLUMN_MAJOR: Items are added top-down, then left-to-right.

    Androidplot provides two primary implementations:

    DynamicTableModel

    Subdivides the LegendWidget's visible space into a fixed number of rows and columns. Use this when you want the legend to fill a specific grid shape regardless of pixel size.

    FixedTableModel

    Uses a fixed pixel size for each cell. It automatically wraps items to the next row or column when the available space is exceeded.

    Note: When using pixel values, it is recommended to use PixelUtils.dpToPix() to ensure consistent sizing across different screen densities.

    // Example: 2x2 grid using ROW_MAJOR
    plot.getLegend().setTableModel(new DynamicTableModel(2, 2, TableOrder.ROW_MAJOR));
    
    // Example: Fixed cell size (300w x 100h) using COLUMN_MAJOR
    plot.getLegend().setTableModel(new FixedTableModel(
        PixelUtils.dpToPix(300), 
        PixelUtils.dpToPix(100), 
        TableOrder.COLUMN_MAJOR
    ));
  6. How GroupRenderer works with multiple XYSeries

    master

    A GroupRenderer is a specialized implementation of XYSeriesRenderer designed to combine multiple XYSeries instances into a single virtual series of a higher dimension.

    When you add series to a plot using formatters associated with a renderer that extends GroupRenderer, all series sharing the same formatter type are automatically grouped together during the rendering process. This allows for the representation of complex data points that require multiple dimensions per X-value.

    Common examples of GroupRenderer implementations include:

    • BarRenderer
    • CandlestickRenderer
  7. Representing complex data with CandlestickRenderer

    master

    The CandlestickRenderer is a GroupRenderer used to create candlestick charts. It represents a complex value for every X-coordinate by grouping four distinct dimensions (series) into a single candlestick:

    • open
    • close
    • high
    • low

    To use this, ensure that the series you add to the plot use formatters compatible with the CandlestickRenderer so they are correctly grouped into these four-dimensional data points.

  8. Understand Androidplot's versioning scheme

    master

    Androidplot uses a Major.Minor.Rev versioning scheme. Understanding the impact of updates depends on which part of the version number changes:

    • Revisional Releases (Major.Minor.Rev where Rev increases): These are fully backwards compatible with the same minor version. Updating to the latest revisional release should require no code changes.
    • Minor Releases (Major.Minor.Rev where Minor increases): These may include new features, bug fixes, or the removal of methods that were previously deprecated. Updating to a new minor release may require code changes.
    • Major Releases (Major.Minor.Rev where Major increases): These are typically complete rewrites of core elements. Unless specified otherwise in the release notes, updating to a new major release will require significant code changes.
  9. How candlestick charts work in Androidplot

    master

    Candlestick charts are a specialized type of XYPlot used for financial data. In Androidplot, a candlestick is represented by four values: high, low, open, and close.

    Internally, the implementation uses four separate XYSeries instances. To ensure the chart renders correctly, you must satisfy these constraints:

    1. Equal Size: Each of the four series must have the same number of data points.
    2. Matching X-coordinates: For any given index i, getX(i) must return the same value across all four series.
    3. Strict Order: You must add exactly four series in this specific order: high, low, open, and close.
    4. Logical Data: For every candlestick, the high value must be $\ge$ all other values, and the low value must be $\le$ all other values.
    5. Consistent Formatting: All four series belonging to the same candlestick chart must use the same CandlestickFormatter instance when added to the XYPlot.
  10. Use BoundaryMode to control axis scaling

    master

    Androidplot provides four BoundaryMode options for domain and range axes:

    • FIXED: Boundaries are locked to the user-defined value.
    • AUTO (default): Boundaries automatically adjust to the min/max values of the data.
    • GROW: Boundaries automatically increase to the maximum value encountered. The initial boundary serves as the starting point.
    • SHRINK: Boundaries automatically shrink to the minimum value encountered. The initial boundary serves as the starting point.
  11. Understand Formatters and Renderers

    master

    Androidplot uses a separation of concerns between data, styling, and drawing:

    1. Series: Encapsulates the numeric data model (e.g., XYSeries for XYPlot).
    2. Formatter: Maps Series data to visual styles. It tells Androidplot which Renderer to use and defines colors, line thicknesses, and text styles.
    3. Renderer: The component responsible for actually drawing the Series data onto the Plot.

    Users can implement custom rendering by creating a custom Renderer and a corresponding Formatter that returns the new renderer class via Formatter.getRendererClass().

  12. How to render dynamic data: Render Loops vs Event Driven

    master

    There are two primary patterns for updating plots in real-time. In both cases, the actual redraw is triggered by calling Plot.redraw().

    Render Loops

    Best for maintaining a stable refresh rate or continuous updates. Androidplot provides a Redrawer utility which is a convenience implementation of a render loop running at a fixed frequency.

    Event Driven Redraws

    Best for updates triggered by specific events (e.g., GPS updates, button clicks). Simply call Plot.redraw() from the event callback after updating your data. Androidplot handles high-frequency events gracefully by ignoring subsequent redraw() calls if a previous redraw is already in progress.