# spine-android Runtime Documentation
> **Licensing**
>
> Please see the [Spine Runtimes License](/spine-runtimes-license) before integrating the Spine Runtimes into your applications.

# Getting Started
The spine-android runtime is implemented on top of [spine-libgdx](/git/runtimes/spine-libgdx). It supports loading, playback and manipulation of animations created with Spine.

## Installation
It supports a minimum SDK version of 24 (Android 7.0, Nougat). Please ensure your project targets at least this SDK version to utilize Spine’s features. 

To use spine-android in your Android app project, first add the mavenCentral and the SonaType snapshot repositories to your Gradle project:

```gradle
repositories {
    mavenCentral()
    maven {
        url = uri("https://oss.sonatype.org/content/repositories/snapshots")
    }
}
```

Next, add the spine-android dependency to your app's `build.gradle` file:

```gradle
dependencies {
    implementation(""com.esotericsoftware.spine:spine-android:4.2.+"")
}
```

This will pull in the latest spine-android version compatible with Spine Editor version 4.2. Generally, this will be a snapshot version based on the latest commit in the [spine-runtimes](https://github.com/esotericsoftware/spine-runtimes) repository. Our snapshot releases are considered stable and published frequently. If you still want or need to depend on a release instead of a snapshot version, you can find the latest release version for your Spine Editor version on [Maven Central](https://central.sonatype.com/artifact/com.esotericsoftware.spine/spine-android).

Ensure that the `major.minor` version of spine-android matches the `major.minor` Spine Editor version you are exporting from. See [Spine Versioning](/spine-versioning#Synchronizing-versions) for more information.

## Samples
The spine-android runtime includes several samples that showcase its feature set. You can run the example project following these steps:

1. Install [Android Studio](https://developer.android.com/studio)
2. Clone the spine-runtimes repository: `git clone https://github.com/esotericsoftware/spine-runtimes`
3. Open the `spine-android/` folder within Android Studio.
4. Run the `app` configuration.

All examples are written using Kotlin in combination with [Jetpack Compose](https://developer.android.com/develop/ui/compose), but spine-android is also compatible with `Java` and plain Android views. The example project contains the following examples:

* [`SimpleAnimation.kt`](/git/spine-runtimes/spine-android/app/src/main/java/com/esotericsoftware/spine/SimpleAnimation.kt): demonstrates the basic use of `SpineView` and `SpineController` to load an exported Spine skeleton, display it in the view, and playback a specific animation.
* [`PlayPause.kt`](/git/spine-runtimes/spine-android/app/src/main/java/com/esotericsoftware/spine/PlayPause.kt): demonstrates how to pause and resume an animation.
* [`AnimationStateEvents.kt`](/git/spine-runtimes/spine-android/app/src/main/java/com/esotericsoftware/spine/AnimationStateEvents.kt): demonstrates how to set a slot's color, how to queue multiple animations, and how to listen for animation state events.
* [`DebugRendering.kt`](/git/spine-runtimes/spine-android/app/src/main/java/com/esotericsoftware/spine/DebugRendering.kt): shows how to perform custom drawing on top of the rendered skeleton via the `SpineController` `onAfterPaint` callback.
* [`DressUp.kt`](/git/spine-runtimes/spine-android/app/src/main/java/com/esotericsoftware/spine/DressUp.kt): demonstrates Spine's skins feature as well as rendering a skeleton to a thumbnail for use in a character creation UI.
* [`IKFollowing.kt`](/git/spine-runtimes/spine-android/app/src/main/java/com/esotericsoftware/spine/IKFollowing.kt): demonstrates how to let the user drag one of the skeleton's bones via mouse or touch input.
* [`DisableRendering.kt`](/git/spine-runtimes/spine-android/app/src/main/java/com/esotericsoftware/spine/DisableRendering.kt): Demonstrates how to disable rendering when the `SpineView` moves off screen. This is important if you need to preserve CPU/GPU resources.
* [`SimpleAnimationActivity.java`](/git/spine-runtimes/spine-android/app/src/main/java/com/esotericsoftware/spine/SimpleAnimationActivity.java): Demonstrates how to use spine-android with `Java` a `SpineView` within a `XML` based relative layout.

## Updating the spine-android Runtime
Before updating your project's spine-android runtime, please consult our [guide on Spine editor and runtime version management](/spine-runtime-architecture#Versioning).

To update the spine-android runtime, simply modify the version string of the spine-android package in your `build.gradle` dependencies.

> **Note:** If you change the `major.minor` version of the spine-android package, you have to re-export your Spine skeletons with the same Spine Editor `major.minor` version!

# Using spine-android
The spine-android runtime builds on top of [spine-libgdx](/git/runtimes/spine-libgdx), which also depends on [libGDX](https://github.com/libgdx/libgdx). It supports loading, playback and manipulation of animations created with Spine. The spine-android runtime uses `spine-libgdx` to easily display and interact with Spine skeletons in Android.

## Asset Management
### Exporting for spine-android
![](/img/spine-runtimes-guide/spine-ue4/export.png)
Please follow the instructions in the Spine User Guide on how to

1. [Export skeleton & animation data](/spine-export)
2. [Export texture atlases containing the images of your skeleton](/spine-texture-packer)

An export of the skeleton data and texture atlas of your skeleton will yield the following files:

![](/img/spine-runtimes-guide/spine-ue4/exported-files.png)

1. `skeleton-name.json` or `skeleton-name.skel`, containing your skeleton and animation data.
2. `skeleton-name.atlas`, containing information about the texture atlas.
3. One or more `.png` files, each representing on page of your texture atlas containing the packed images your skeleton uses.

> **Note**: You should prefer binary skeleton exports over JSON exports, as they are smaller in size and faster to load.

The files can be loaded via spine-android classes like `AndroidTextureAtlas`, `SkeletonDataUtils`, `AndroidSkeletonDrawable`, `SpineView`.

> **Note**: The spine-android runtime currently does not support atlases exported using pre-multiplied alpha due to technical limitations in Android. Android's rendering engine ensures that common non-premultiplied alpha artifacts are avoided.

### Updating Spine Assets
During development, you may frequently update your Spine skeleton data and texture atlas files. You can simply overwrite these source files (`.json`, `.skel`, `.atlas`, `.png`) by re-exporting from the Spine Editor and replacing the existing files in your Android project.

Ensure that the `major.minor` version of spine-android matches the `major.minor` Spine Editor version you are exporting from. See [Spine Versioning](/spine-versioning#Synchronizing-versions) for more information.

## Core classes
The spine-android API is built on top of [spine-libgdx](/git/runtimes/spine-libgdx), which provides core classes and algorithms to load, query, modify, and animate Spine skeletons.

Here, we will briefly discuss the most important core classes that you will encounter in your day-to-day use of spine-android. Please consult the [Spine Runtimes Guide](/spine-runtimes-guide) for a detailed overview of the Spine Runtimes architecture, core classes, and API usage.

### spine-android classes
The [`AndroidSkeletonDrawable`](/git/spine-runtimes/spine-android/spine-android/src/main/java/com/esotericsoftware/spine/android/AndroidTextureAtlas.java) class bundles loading and updating `AndroidTextureAtlas`, `Skeleton`, and `AnimationState` into a single easy-to-use class.

The [`AndroidTextureAtlas`](/git/spine-runtimes/spine-android/spine-android/src/main/java/com/esotericsoftware/spine/android/AndroidTextureAtlas.java) class stores the data loaded from an `.atlas` file and its corresponding `.png` image files.

The [`SkeletonDataUtils`](/git/spine-runtimes/spine-android/spine-android/src/main/java/com/esotericsoftware/spine/android/util/SkeletonDataUtils.java) class exposes static functions to load a `SkeletonData` class from skeleton file assets.

The [`SkeletonRenderer`](/git/spine-runtimes/spine-android/spine-android/src/main/java/com/esotericsoftware/spine/android/SkeletonRenderer.java) class is responsible to transform the `Skeleton` with its current pose to `SkeletonRenderer.RenderCommand` commands and render them to a `Canvas`.

These are part of spine-android and are either extensions of `spine-libgdx` or add Android specific functionality on top of them.

### spine-libgdx classes
The [`SkeletonData`](/git/spine-runtimes/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonData.java) class stores the data loaded from a `.json` or `.skel` skeleton file. The skeleton data contains information about the bone hierarchy, slots, attachments, constraints, skins, and animations. A `SkeletonData` instance is usually loaded by also providing an `Atlas` from which it sources the images to be used by the skeleton it represents. It serves as a blueprint for creating `Skeleton` instances. Multiple skeletons can be instantiated from the same atlas and skeleton data, which then share the loaded data, minimizing both load times and memory consumption at runtime.

The [`Skeleton`](/git/spine-runtimes/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonData.java) class stores an instance of a skeleton, created from a `SkeletonData` instance. A skeleton stores its current pose, that is the position of bones and the current configuration of slots, attachments, and active skin. The current pose can be computed by either manually modifying the bone hierarchy, or, more commonly, by applying animations via an `AnimationState`.

The [`AnimationState`](/git/spine-runtimes/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/AnimationState.java) class is responsible for keeping track of which animation(s) should be applied to a skeleton, advancing and mixing those animations based on the elapsed time between the last and current rendering frame, and applying the animations to a skeleton instance, thereby setting its current pose. The `AnimationState` queries an [`AnimationStateData`](/git/spine-runtimes/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/AnimationStateData.java) instance to retrieve mixing times between animations, or fetches the default mix time if no mixing time is available for a pair of animations.

The spine-android runtime builds on top of these core classes.

## SpineView
![/img/spine-runtimes-guide/spine-android/simple-animation.png](/img/spine-runtimes-guide/spine-android/simple-animation.png)

A [`SpineView `](/git/spine-runtimes/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SpineView.java) is an Android [View](https://developer.android.com/reference/android/view/View) responsible for loading and displaying a Spine skeleton. At a minimum, the view needs to know from where to load the skeleton and atlas files, and it must receive a `SpineController` instance that is responsible for modifying the state of the view, such as setting an animation, or changing the skin of the skeleton.

When using `Jetpack Compose`, a `SpineView` can be instantiated within an `AndroidView`:

```kotlin
AndroidView(
    factory = { context ->
        SpineView.loadFromAssets(
            "spineboy.atlas",
            "spineboy-pro.json",
            context,
            SpineController {
                it.animationState.setAnimation(0, "walk", true)
            }
        )
    }
)
```

Upon instantiation, the `SpineView` will asynchronously load the specified files and construct the underlying core class instances from them, namely instances of `AndroidTextureAtlas`, `SkeletonData`, `Skeleton`, `AnimationStateData`, and `AnimationState`.

Once loading is complete, the `SpineController` constructor callback `onInitialized` is called, allowing it to modify the state of the view, such as setting one or more animations, manipulating the bone hierarchy, or modifying the skin of the skeleton. See the section on `SpineController` below.

The `SpineView` class provides multiple static factory methods to load skeleton and atlas files from different sources:

* `SpineView.loadFromAsset()` loads files from the root bundle, or a provided bundle.
* `SpineView.loadFromFile()` loads files from the file system.
* `SpineView.loadFromHttp()` loads files from URLs.
* `SpineView.loadFromDrawable()` constructs a view from a `AndroidSkeletonDrawable`. This is useful when the skeleton data should be preloaded, cached, and/or shared between `SpineView` instances. See the [`DisableRendering.kt`](/git/spine-runtimes/spine-android/app/src/main/java/com/esotericsoftware/spine/DisableRendering.kt) example for more information.

When you need to further define how the Spine skeleton is fitted and aligned inside the widget, you can either use the setters of `SpineView`:

```kotlin
val spineView = SpineView.loadFromAssets("dragon.atlas", "dragon-ess.skel", ctx, controller)
spineView.setContentMode(ContentMode.FILL)
spineView.setAlignment(Alignment.BOTTOM_CENTER)
spineView.setBoundsProvider(SkinAndAnimationBounds("flying"))
```

or the `SpineView.Builder`:

```kotlin
SpineView.Builder(ctx, controller)
	.setLoadFromAssets("dragon.atlas", "dragon-ess.skel")
	.setContentMode(ContentMode.FILL)
	.setAlignment(Alignment.BOTTOM_CENTER)
	.setBoundsProvider(SkinAndAnimationBounds("flying"))
	.build()
```

* `setContentMode` sets the [`ContentMode`](/git/spine-runtimes/spine-android/spine-android/src/main/java/com/esotericsoftware/spine/android/bounds/ContentMode.java) to use to fit the skeleton inside the view.
* `setAlignment` sets the [`Alignment`](/git/spine-runtimes/spine-android/spine-android/src/main/java/com/esotericsoftware/spine/android/bounds/Alignment.java) to use to align the skeleton inside the view.
* `setBoundsProvider` sets the [`BoundsProvider`](/git/spine-runtimes/spine-android/spine-android/src/main/java/com/esotericsoftware/spine/android/bounds/BoundsProvider.java) used to calculate the pixel size of the bounding box to be used for the skeleton when computing the fit and alignment. By default, the skeleton's setup pose bounding box is used. See the class documentation for [`SetupPoseBounds`](/git/spine-runtimes/spine-android/spine-android/src/main/java/com/esotericsoftware/spine/android/bounds/SetupPoseBounds.java), and [`SkinAndAnimationBounds`](/git/spine-runtimes/spine-android/spine-android/src/main/java/com/esotericsoftware/spine/android/bounds/SkinAndAnimationBounds.java) for additional information.

The `SpineView` has an getter/setter pair `isRendering/setRendering`, through which rendering can be disabled. To update properties of the `SpineView`, like `isRendering` in `Jetpack Compose`, add the `AndroidView.update` parameter:

```kotlin
AndroidView(
    factory = ...
    update = { spineView ->
        spineView.isRendering = isSpineBoyVisible.value
    }
)
```

See the [`DisableRendering.kt`](/git/spine-runtimes/spine-android/app/src/main/java/com/esotericsoftware/spine/DisableRendering.kt) example for more information.

## SpineController
A [`SpineController`](/git/spine-runtimes/spine-android/spine-android/src/main/java/com/esotericsoftware/spine/android/SpineController.java) controls how the skeleton of a `SpineView` is animated and rendered. The controller can be provided with a set of optional callbacks through method injection or the [`SpineController.Builder`](/git/spine-runtimes/spine-android/spine-android/src/main/java/com/esotericsoftware/spine/android/SpineController.java) class. The callbacks are called at specific times during the life-time of the `SpineView`.

The controller exposes the skeleton state through getters returning Spine Runtimes API objects such as the `AndroidTextureAtlas`, `SkeletonData`, `Skeleton`, and `AnimationState`, through which the state can be manipulated. See the [Spine Runtimes Guide](/spine-runtimes-guide), and the documentation of those classes for more information.

Upon initialization of a `SpineView`, the controller's `onInitialized()` callback method is invoked once. This method can be used to setup the initial animation(s) to be played back, or set the skin of the skeleton, among other things.

After initialization is complete, the `SpineView` is rendered continuously at the screen refresh rate. Each frame, the `AnimationState` is updated based on the currently queued animations, and applied to the `Skeleton`.

Next, the optional `onBeforeUpdateWorldTransforms()` callback is invoked, which can modify the skeleton before its current pose is calculated using `Skeleton.updateWorldTransform()`. It is set using `SpineController.setOnBeforeUpdateWorldTransforms()` or `SpineController.Builder.setOnBeforeUpdateWorldTransforms()`.

After the current pose has been calculated, the optional `onAfterUpdateWorldTransforms()` callback is invoked, which can further modify the current pose before the skeleton is rendered. This is a good place to manually position bones. It is set using `SpineController.setOnAfterUpdateWorldTransforms()` or `SpineController.Builder.setOnAfterUpdateWorldTransforms()`.

Before the skeleton is rendered by the `SpineView`, the optional `onBeforePaint()` callback is invoked, which allows rendering backgrounds or other objects that should go behind the skeleton on the [`Canvas`](https://developer.android.com/reference/android/graphics/Canvas). It is set using `SpineController.setOnBeforePaint()` or `SpineController.Builder.setOnBeforePaint()`.

After the `SpineView` has rendered the current skeleton pose to the `Canvas`, the optional `onAfterPaint()` callback is invoked, which allows rendering additional objects on top of the skeleton. It can be set using `SpineController.setOnAfterPaint()` or `SpineController.Builder.setOnAfterPaint()`.

By default, the view updates and renders the skeleton every frame. The `SpineController.pause()` method can be used to pause updating and rendering the skeleton. The `SpineController.resume()` method resumes updating and rendering the skeleton. The `SpineController.isPlaying()` getter reports the current playback state. See the [`PlayPause.kt`](/git/spine-runtimes/spine-android/app/src/main/java/com/esotericsoftware/spine/PlayPause.kt) example.

## AndroidSkeletonDrawable
An `AndroidSkeletonDrawable` bundles loading, storing, updating, and rendering a `Skeleton` and its associated `AnimationState` into a single, easy to use class. The class can be used as the basis for a custom view implementation. The `SpineView` encapsulates the state of the skeleton it displays via an instance of a `AndroidSkeletonDrawable`.

Use the `fromAsset()`, `fromFile()`, or `fromHttp()` static functions to construct a `AndroidSkeletonDrawable` from file assets. To share `AndroidTextureAtlas` and `SkeletonData` among multiple `AndroidSkeletonDrawable` instances, instantiate the drawables via the constructor, passing the same atlas and skeleton data to each of them.

The `AndroidSkeletonDrawable` exposes the `Skeleton` and `AnimationState` to query, modify, and animate the skeleton. It also exposes the `AndroidTextureAtlas` and `SkeletonData` from which the skeleton and animation state have been constructed.

To animate the skeleton, queue animations on one or more tracks via the `AnimationState` API, such as `AnimationState.setAnimation()` or `AnimationState.addAnimation()`.

To update the animation state, apply it to the skeleton, and update the current skeleton pose, call the `AndroidSkeletonDrawable.update()` method, providing it a delta time in seconds to advance the animations.

## Applying Animations
Applying animations to a skeleton displayed by a `SpineView` is done through the `AnimationState` in the callbacks of a `SpineController`.

> **Note:** See [Applying Animations](/spine-applying-animations#AnimationState-API) in the Spine Runtimes Guide for more in-depth information, specifically about animation tracks and animation queueing.

To set a specific animation on track 0, call `AnimationState.setAnimation()`:

```kotlin
 SpineController { initializedController ->
	 // Set the walk animation on track 0, let it loop
    initializedController.animationState.setAnimation(0, "walk", true)
}
```

The first parameter specifies the track, the second parameter is the name of the animation, and the third parameter defines whether to loop the animation.

You can queue multiple animations:

```kotlin
controller.animationState.setAnimation(0, "walk", true)
controller.animationState.addAnimation(0, "jump", false, 2f)
controller.animationState.addAnimation(0, "run", true, 0f)
```

The first parameter to `addAnimationByName()` is the track. The second parameter is the name of the animation. The third parameter defines whether to loop the animation. The final parameter specifies the delay in seconds, after which this animation should replace the previous animation on the track.

In the example above, the `"walk"` animation is played back first. 2 seconds later, the `"jump"` animation is played back once, followed by a transition to the `"run"` animation, which will be looped.

When transitioning from one animation to another, `AnimationState` will mix the animations for a specificable duration. These mix times are defined in an `AnimationStateData` instance, from which the `AnimationState` retrieves mix times.

The `AnimationStateData` instance is also available through the controller. You can set the default mix time, or the mix time for a specific pair of animations:

```kotlin
controller.animationStateData.setDefaultMix(0.2f)
controller.animationStateData.setMix("walk", "jump", 0.1f)
```

When setting or adding an animation, a `AnimationState.TrackEntry` object is returned, which allows further modification of that animation's playback. For example, you can set the track entry to reverse the animation playback:

```kotlin
val entry = controller.animationState.setAnimation(0, "walk", true)
entry.setReverse(true)
```

See the [`AnimationState.TrackEntry` class documentation](/git/spine-runtimes/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/AnimationState.java) for more options.

> **Note:** Do not hold on to `AnimationState.TrackEntry` instances outside the function you are using them in. Track entries are re-used internally and will thus become invalid once the animation it represents has been completed.

You can set or queue empty animations on an animation track to smoothly reset the skeleton back to its setup pose:

```kotlin
controller.animationState.setEmptyAnimation(0, 0.5f)
controller.animationState.addEmptyAnimation(0, 0.5f, 0.5f)
```

The first parameter to `setEmptyAnimation()` specifies the track. The second parameter specifies the mix duration in seconds used to mix out the previous animation and mix in the "empty" animation.

The first parameter to `addEmptyAnimation()` specifies the track. The second parameter specifies the mix duration. The third parameter is the delay in seconds, after which the empty animation should replace the previous animation on the track via mixing.

All animations on a track can be cleared immediately via `AnimationState.clearTrack()`. To clear all tracks at once, `AnimationState.clearTracks()` can be used. This will leave the skeleton in the last pose it was in.

To reset the pose of a skeleton to the setup pose, use `Skeleton.setToSetupPose()`:

```kotlin
controller.skeleton.setToSetupPose()
```

This will reset both the bones and slots to their setup pose configuration. Use `Skeleton.setSlotsToSetupPose()` to only reset the slots to their setup pose configuration.

## AnimationState Events
An `AnimationState` emits events during the life-cycle of an animation that is being played back. You can listen for this events to react as needed. The Spine Runtimes API defines the [`AnimationState.AnimationStateListener`](/git/spine-runtimes/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/AnimationState.java) interface with callbacks for the events:

* `start`: emitted when an animation is started.
* `interrupt`: emitted when an animation's track was cleared, or a new animation was set.
* `end`: emitted when an animation will never be applied again.
* `dispose`: emitted when the animation's track entry is disposed.
* `complete`: emitted when an animation completes a loop.
* `event`: emitted when a user defined [event](/spine-events#Events) happened.

To receive events, you can register an [`AnimationState.AnimationStateListener`](/git/spine-runtimes/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/AnimationState.java) callback with either the `AnimationState` to receive events across all animations, or with the `AnimationState.TrackEntry` of a specific animation queued for playback:

```kotlin
val entry = controller.animationState.setAnimation(0, "walk", true)
entry.setListener(object : AnimationState.AnimationStateListener {
    override fun start(entry: AnimationState.TrackEntry?) {}

    override fun interrupt(entry: AnimationState.TrackEntry?) {}

    override fun end(entry: AnimationState.TrackEntry?) {}

    override fun dispose(entry: AnimationState.TrackEntry?) {}

    override fun complete(entry: AnimationState.TrackEntry?) {}

    override fun event(entry: AnimationState.TrackEntry?, event: Event?) {
        if (event != null) {
            print("User defined event: ${event.data.name}");
        }
    }
})
controller.animationState.addListener(object : AnimationState.AnimationStateListener {
    override fun start(entry: AnimationState.TrackEntry?) {}

    override fun interrupt(entry: AnimationState.TrackEntry?) {}

    override fun end(entry: AnimationState.TrackEntry?) {}

    override fun dispose(entry: AnimationState.TrackEntry?) {}

    override fun complete(entry: AnimationState.TrackEntry?) {}

    override fun event(entry: AnimationState.TrackEntry?, event: Event?) {
        if (event != null) {
            print("Animation state event $event")
        }
    }
})
```

See the [`AnimationStateEvents.kt`](/git/spine-runtimes/spine-android/app/src/main/java/com/esotericsoftware/spine/AnimationStateEvents.kt) example.

## Skins
![/img/spine-runtimes-guide/spine-android/skins.png](/img/spine-runtimes-guide/spine-android/skins.png)

Many applications and games allow users to create custom avatars out of many individual items, such as hair, eyes, pants, or accessories like earrings or bags. With Spine, this can be achived by [mixing and matching skins](/spine-examples-mix-and-match).

You can create custom skins from other skins like this:

```kotlin
val data = controller.skeletonData
val skeleton = controller.skeleton
val customSkin = Skin("custom-skin");
customSkin.addSkin(data.findSkin("skin-base"))
customSkin.addSkin(data.findSkin("nose/short"))
customSkin.addSkin(data.findSkin("eyelids/girly"))
customSkin.addSkin(data.findSkin("eyes/violet"))
customSkin.addSkin(data.findSkin("hair/brown"))
customSkin.addSkin(data.findSkin("clothes/hoodie-orange"))
customSkin.addSkin(data.findSkin("legs/pants-jeans"))
customSkin.addSkin(data.findSkin("accessories/bag"))
customSkin.addSkin(data.findSkin("accessories/hat-red-yellow"))
skeleton.setSkin(customSkin)
skeleton.setSlotsToSetupPose()
```

Create a custom skin with the `Skin()` constructor.

Next, fetch the `SkeletonData` from the controller. It is used to look up skins by name via `SkeletonData.findSkin()`.

Add all the skins you want to combine into the new custom skin via `Skin.addSkin()`.

Finally, set the new skin on the `Skeleton` and call `Skeleton.setSlotsToSetupPose()` to ensure no attachments from previous skins and/or animations are left over.

See the  [`DressUp.kt`](/git/spine-runtimes/spine-android/app/src/main/java/com/esotericsoftware/spine/DressUp.kt) example, which also demonstrate how to render thumbnail previews of skins using `AndroidSkeletonDrawable`.

## Setting Bone Transforms
![/img/spine-runtimes-guide/spine-android/simple-animation.png](/img/spine-runtimes-guide/spine-android/bone-transform.png)

When authoring a skeleton in the Spine Editor, the skeleton is defined in what is called the skeleton coordinate system. This coordinate system may not align with the coordinate system of the `SpineView` the skeleton is rendered by. Touch coordinates relative to the `SpineView` need thus be converted to the skeleton coordinate system, e.g. if a user should be able to move a bone by touch.

The `SpineController` offers the method `toSkeletonCoordinates()` which takes an [`Point`](https://developer.android.com/reference/android/graphics/Point) relative to the `SpineView` it is associated with, and converts it to the skeleton's coordinate system.

See the [`IKFollowing.kt`](/git/spine-runtimes/spine-android/app/src/main/java/com/esotericsoftware/spine/IKFollowing.kt) example.

## Rendering with SpineRenderer
If you need to render a skeleton outside of a `SpineView`, rendering it into a `Cavas` or `Bitmap`, you can use the [`SkeletonRenderer`](/git/spine-runtimes/spine-android/app/src/main/java/com/esotericsoftware/spine/SkeletonRenderer.kt).

To render the current pose of the skeleton, use the rendering methods `SkeletonDrawable.render()` to create a list of [`SkeletonRenderer.RenderCommand`](/git/spine-runtimes/spine-android/app/src/main/java/com/esotericsoftware/spine/SkeletonRenderer.kt) objects. Use those and call to either render to a `Canvas` with `SkeletonDrawable.renderToCanvas()` or `Bitmap` with `SkeletonDrawable.renderToBitmap()`.

# Spine Runtimes API access
The spine-android API is built on top of the [spine-libgdx](/git/runtimes/spine-libgdx) and you can thus use the whole API it provides. Please consult the [Spine Runtimes Guide](/spine-runtimes-guide) for more information.