Android library that can trace views to create silhouettes. Written in Kotlin.
Trace will iterate through the views in a given View
hierarchy and create
silhouettes based on whether or not the View implements the interface Traceable
:
-
If a View does implement
Traceable
, Trace will create a silhouette from the result of thePath
object returned by theTraceable.trace
call. -
If a View does not implement the
Traceable
interface, Trace will try to use the user-providedTraceDelegate
, if one was supplied. If a delegate isn't provided or ifTraceDelegate.handle
does not return true, then Trace will hand-off to theDefaultTraceDelegate
. The default delegate will handle some basic views elegantly but otherwise utilizes rounded rectangles to create a silhouette based on the boundaries of the view.
If the lambda shouldExcludeView
is defined and returns true for a given View, it will be
ignored and not drawn. Said lambda can be specified when calling TraceContainer.startShimmer
or when identifying the target for tracing via Trace.of
.
Additionally, Trace
instances can have their shimmer animations synchronized by the use of a
ShimmerSynchronizer
- which can be designated either through TraceContainer.startShimmer
or
Trace.syncWith
.
Trace
uses aPath
object with fill typeWINDING
(non-zero). Thus, please consider the ramifications when creating Paths.- The default implementation of
TraceDelegate
will ignore views whose visibilities are set to eitherView.INVISIBLE
orView.GONE
.
Available via JitPack: https://jitpack.io/#prateem/Trace
dependencies {
implementation "com.github.prateem:Trace:$traceVersion"
}
// in root build.gradle
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
An example app is available that will build the following to a device:
Pseudo-code is used for clarity of mapping to the visual(s) above. See activity_main.xml for full/proper xml.
<Screen>
<Toggle />
<TraceContainer id="traceContainer">
<LinearLayout>
<TextView lines="1" gravity="center" />
<TextView lines="2" />
<Square size="200dp" color="accent" />
<Button />
<RadioButton enabled="false" />
<TraceableView
nonTraceOutput="none"
traceableOutput="doubleBubble" />
</LinearLayout>
</TraceContainer>
</Screen>
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val toggle = findViewById<Checkbox>(R.id.toggle)
val traceContainer = findViewById<TraceContainer>(R.id.traceContainer)
toggle.setOnCheckedChangeListener { _, isChecked ->
if (isChecked)
traceContainer.startShimmer()
else
traceContainer.stopShimmer()
}
// Internally, TraceContainer calls Trace with a similar setup to the following...
// (defaults shown here are for clarification only)
val trace = Trace(this) // `this` here is context, since Trace inherits from View
.of(target, delegate = null, shouldExcludeView = null)
.setColorResource(android.R.color.darker_gray) // Same as default
.setShimmerColorResource(android.R.color.white) // Same as default
.also { it.startShimmer(1200) } // Same as default
// container.addView(trace)
}
}
As in the example above, Trace
is most easily utilized by wrapping a ViewGroup
with
a TraceContainer
. Alternatively, it can be created and used manually by instantiating Trace
and
calling Trace.of()
. Shimmer must be controlled programmatically.
Type | Definition |
variable |
@ColorInt traceSilhouetteColor: Int
The color of the traced silhouette. |
variable |
@ColorInt traceShimmerColor: Int
The color of the shimmer that runs across the traced silhouette. |
variable |
crossFadeEnabled: Boolean
Toggle for enabling or disabling cross-fade animation when starting or stopping shimmer. Default: |
variable |
crossFadeDuration: Long
If Default: |
function |
startShimmer( shimmerSpeed: Long = 1200L, delegate: TraceDelegate? = null, shouldExcludeView: ((View) -> Boolean)? = null, crossFade: Boolean = true, synchronizer: ShimmerSynchronizer? = null ): Unit Start the shimmer animation with the given synchronizer (if provided), and with period duration for the shimmer in milliseconds. Trace will be performed with the given delegate, if provided. Views for which lambda invocations return true will be ignored during trace. |
function |
stopShimmer(crossFade: Boolean = true): Unit
Stops any active shimmer animation. |
Type | Definition |
function |
of( root: View, delegate: TraceDelegate? = null, shouldExcludeView: ((View) -> Boolean)? = null ): Trace Identify the given Views for which lambda invocations return true will be ignored during trace. |
function |
syncWith(sync: ShimmerSynchronizer?): Trace
Set the |
function |
colored(@ColorInt color: Int): Trace setColorResource(@ColorRes color: Int): Trace
Set the color for the traced silhouette segments. |
function |
shimmerColored(@ColorInt color: Int): Trace setShimmerColorResource(@ColorRes color: Int): Trace
Set the color for the shimmer that animates when |
function |
startShimmer(shimmerSpeed: Long): Unit
Start the shimmer animation over the traced silhouette. |
function |
stopShimmer(): Unit
Stop the shimmer animation over the traced silhouette. |