Android Kaki

Build beautiful, usable products using required Components for Android.

How we constructed person interplay monitoring for Jetpack Compose | by Markus Hintersteiner | April 2023


Jetpack Compose and Monitor

Finish outcome: Mechanically flip clicks into breadcrumbs

Our request for declarative programming assist

  1. Detect each click on, swipe or scroll globally
  2. Know which UI parts the person has interacted with
  3. Outline an identifier for the UI aspect and create the corresponding breadcrumb
  4. Minimal setup necessities

Detect clicks, scrolls and swipes

  1. On the Sentry SDK init, register a ActivityLifecycleCallbacks to get maintain present seen Exercise
  2. entry Window via Exercise.getWindow()
  3. Put a Window.Callback use window.setCallback()
val previousCallback = window.getCallback() ?: EmptyCallback()
val newCallback = SentryWindowCallback(previousCallback)
window.setCallback(newCallback)
class SentryWindowCallback(val delegate: Window.Callback) : Window.Callback {
override enjoyable dispatchTouchEvent(occasion: MotionEvent?): Boolean {
// our logic ...


return delegate.dispatchTouchEvent(occasion)
}
}

Find and establish widgets

  1. Iterate the View Hierarchy and discover the View that matches the contact coordinates
  2. Retrieve numeric view ID by way of view.getId()
  3. Translate the ID again to its useful resource identify to get a readable identifier
enjoyable coordinatesWithinBounds(view: View, x: Float, y: Float): Boolean 


enjoyable isViewTappable(view: View) {
return view.isClickable() && view.getVisibility() == View.VISIBLE
}


val x = motionEvent.getX()
val y = motionEvent.getY()


if (coordinatesWithinBounds(view, x, y) && isViewTappable(view)) {
val viewId = view.getId()
return view.getContext()
.getResources()?
.getResourceEntryName(viewId); // e.g. button_login
)

Left: Conventional Android Format, Proper: Jetpack Compose UI
// From 
/**
* Hit check the format tree for semantics wrappers.
* The return worth is a digital view id, or InvalidId if an embedded Android View was hit.
*/
@OptIn(ExperimentalComposeUiApi::class)
@VisibleForTesting
inside enjoyable hitTestSemanticsAt(x: Float, y: Float): Int

// From 
/**
* This droop perform loops for the whole lifetime of the Compose occasion: it consumes
* current format adjustments and sends occasions to the accessibility framework in batches separated
* by a 100ms delay.
*/
droop enjoyable boundsUpdatesEventLoop() {
// ...
}

Dive into the contents of Compose

// From: 
/**
* The place of this format relative to the window.
*/
enjoyable LayoutCoordinates.positionInWindow(): Offset
@Immutable
@kotlin.jvm.JvmInline
worth class Offset inside constructor(inside val packedValue: Lengthy) {
@Steady
val x: Float
get() // ...
@Steady
val y: Float
get() // ...
}

personal static boolean layoutNodeBoundsContain(@NotNull LayoutNode node, last float x, last float y) {
last int nodeHeight = node.getHeight();
last int nodeWidth = node.getWidth();
// positionInWindow() returns an Offset in Kotlin
// if accessed in Java, you may get a protracted!
last lengthy nodePosition = LayoutCoordinatesKt.positionInWindow(node.getCoordinates());


last int nodeX = (int) Float.intBitsToFloat((int) (nodePosition >> 32));
last int nodeY = (int) Float.intBitsToFloat((int) (nodePosition));


return x >= nodeX && x <= (nodeX + nodeWidth) && y >= nodeY && y <= (nodeY + nodeHeight);
}

Decide Composables

@Composable
enjoyable EmptyComposable() {
}

import androidx.compose.runtime.Composer;
import androidx.compose.runtime.ComposerKt;
import androidx.compose.runtime.ScopeUpdateScope;
import kotlin.Metadata;
public last class EmptyComposableKt {
public static last void EmptyComposable(Composer $composer, int $modified) {
Composer $composer2 = $composer.startRestartGroup(103603534);
ComposerKt.sourceInformation($composer2, "C(EmptyComposable):EmptyComposable.kt#llk8wg");
if ($modified != 0 || !$composer2.getSkipping()) {
if (ComposerKt.isTraceInProgress()) {
ComposerKt.traceEventStart(103603534, $modified, -1, "com.instance.EmptyComposable (EmptyComposable.kt:5)");
}
if (ComposerKt.isTraceInProgress()) {
ComposerKt.traceEventEnd();
}
} else {
$composer2.skipToGroupEnd();
}
ScopeUpdateScope endRestartGroup = $composer2.endRestartGroup();
if (endRestartGroup == null) {
return;
}
endRestartGroup.updateScope(new EmptyComposableKt$EmptyComposable$1($modified));
}
}

enjoyable retrieveTestTag(node: LayoutNode) : String? {
for (modifier in node.modifiers) {
if (modifier is SemanticsModifier) {
val testTag: String? = modifier
.semanticsConfiguration
.getOrNull(SemanticsProperties.TestTag)
if (testTag != null) {
return testTag
}
}
}
return null
}

pack it up




Subsequent step

Subsequent step

Jetpack Compose + Sentry Sources

John Wick: Chapter 4 (FREE) FULLMOVIE The Super Mario Bros Movie avatar 2 Where To Watch Creed 3 Free At Home Knock at the Cabin (2023) FullMovie Where To Watch Ant-Man 3 and the Wasp: Quantumania Cocaine Bear 2023 (FullMovie) Scream 6 Full Movie
Updated: April 17, 2023 — 12:03 pm

Leave a Reply

Your email address will not be published. Required fields are marked *

androidkaki.com © 2023 Android kaki