orientation
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
project(ux_keyboard)
|
||||
|
||||
add_library(ux_keyboard SHARED keyboard_bridge.c)
|
||||
add_library(ux_keyboard SHARED keyboard_bridge.c sensor_bridge.c)
|
||||
target_link_libraries(ux_keyboard log)
|
||||
|
||||
# 16KB page size support (required for Android 15+)
|
||||
|
||||
18
android/src/main/jni/sensor_bridge.c
Normal file
18
android/src/main/jni/sensor_bridge.c
Normal file
@@ -0,0 +1,18 @@
|
||||
#include <jni.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// Shared state — Kotlin writes, Dart reads via FFI.
|
||||
// Encoded as Surface rotation convention:
|
||||
// 0 = portraitUp, 1 = landscapeLeft, 2 = portraitDown, 3 = landscapeRight.
|
||||
static int32_t g_device_orientation = 0;
|
||||
|
||||
// --- Dart FFI reads ---
|
||||
|
||||
int32_t ux_device_orientation(void) { return g_device_orientation; }
|
||||
|
||||
// --- Kotlin JNI writes ---
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_io_swipelab_ux_SensorBridge_nSetDeviceOrientation(JNIEnv *env, jclass cls, jint v) {
|
||||
g_device_orientation = v;
|
||||
}
|
||||
@@ -7,12 +7,11 @@ import android.view.ViewTreeObserver
|
||||
import android.view.WindowInsets
|
||||
import android.view.WindowInsetsAnimation
|
||||
import io.flutter.embedding.engine.plugins.FlutterPlugin
|
||||
import io.flutter.embedding.engine.plugins.activity.ActivityAware
|
||||
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
|
||||
import io.flutter.plugin.common.MethodCall
|
||||
import io.flutter.plugin.common.MethodChannel
|
||||
|
||||
class KeyboardPlugin : FlutterPlugin, MethodChannel.MethodCallHandler, ActivityAware {
|
||||
class KeyboardPlugin : NativePlugin, MethodChannel.MethodCallHandler {
|
||||
private var methodChannel: MethodChannel? = null
|
||||
private var activity: Activity? = null
|
||||
private var windowFocusListener: ViewTreeObserver.OnWindowFocusChangeListener? = null
|
||||
|
||||
13
android/src/main/kotlin/io/swipelab/ux/NativePlugin.kt
Normal file
13
android/src/main/kotlin/io/swipelab/ux/NativePlugin.kt
Normal file
@@ -0,0 +1,13 @@
|
||||
package io.swipelab.ux
|
||||
|
||||
import io.flutter.embedding.engine.plugins.FlutterPlugin
|
||||
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
|
||||
|
||||
interface NativePlugin {
|
||||
fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) {}
|
||||
fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {}
|
||||
fun onAttachedToActivity(binding: ActivityPluginBinding) {}
|
||||
fun onDetachedFromActivity() {}
|
||||
fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) = onAttachedToActivity(binding)
|
||||
fun onDetachedFromActivityForConfigChanges() = onDetachedFromActivity()
|
||||
}
|
||||
9
android/src/main/kotlin/io/swipelab/ux/SensorBridge.kt
Normal file
9
android/src/main/kotlin/io/swipelab/ux/SensorBridge.kt
Normal file
@@ -0,0 +1,9 @@
|
||||
package io.swipelab.ux
|
||||
|
||||
object SensorBridge {
|
||||
init {
|
||||
System.loadLibrary("ux_keyboard")
|
||||
}
|
||||
|
||||
@JvmStatic external fun nSetDeviceOrientation(v: Int)
|
||||
}
|
||||
55
android/src/main/kotlin/io/swipelab/ux/SensorPlugin.kt
Normal file
55
android/src/main/kotlin/io/swipelab/ux/SensorPlugin.kt
Normal file
@@ -0,0 +1,55 @@
|
||||
package io.swipelab.ux
|
||||
|
||||
import android.app.Activity
|
||||
import android.view.OrientationEventListener
|
||||
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
|
||||
|
||||
class SensorPlugin : NativePlugin {
|
||||
private var listener: OrientationEventListener? = null
|
||||
private var current: Int = 0
|
||||
|
||||
override fun onAttachedToActivity(binding: ActivityPluginBinding) {
|
||||
attach(binding.activity)
|
||||
}
|
||||
|
||||
override fun onDetachedFromActivity() {
|
||||
detach()
|
||||
}
|
||||
|
||||
private fun attach(activity: Activity) {
|
||||
detach()
|
||||
val l = object : OrientationEventListener(activity) {
|
||||
override fun onOrientationChanged(degrees: Int) {
|
||||
if (degrees == ORIENTATION_UNKNOWN) return
|
||||
val bucket = bucketFor(degrees, current)
|
||||
if (bucket == current) return
|
||||
current = bucket
|
||||
SensorBridge.nSetDeviceOrientation(bucket)
|
||||
}
|
||||
}
|
||||
if (l.canDetectOrientation()) l.enable()
|
||||
listener = l
|
||||
}
|
||||
|
||||
private fun detach() {
|
||||
listener?.disable()
|
||||
listener = null
|
||||
}
|
||||
|
||||
companion object {
|
||||
internal fun bucketFor(degrees: Int, previous: Int): Int {
|
||||
val d = ((degrees % 360) + 360) % 360
|
||||
return when {
|
||||
d in 0..30 || d in 330..359 -> 0
|
||||
d in 60..120 -> 3
|
||||
d in 150..210 -> 2
|
||||
d in 240..300 -> 1
|
||||
d in 31..59 -> if (previous == 0 || previous == 3) previous else 0
|
||||
d in 121..149 -> if (previous == 3 || previous == 2) previous else 3
|
||||
d in 211..239 -> if (previous == 2 || previous == 1) previous else 2
|
||||
d in 301..329 -> if (previous == 1 || previous == 0) previous else 1
|
||||
else -> previous
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
30
android/src/main/kotlin/io/swipelab/ux/UxPlugin.kt
Normal file
30
android/src/main/kotlin/io/swipelab/ux/UxPlugin.kt
Normal file
@@ -0,0 +1,30 @@
|
||||
package io.swipelab.ux
|
||||
|
||||
import io.flutter.embedding.engine.plugins.FlutterPlugin
|
||||
import io.flutter.embedding.engine.plugins.activity.ActivityAware
|
||||
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
|
||||
|
||||
class UxPlugin : FlutterPlugin, ActivityAware {
|
||||
private val plugins: List<NativePlugin> = listOf(
|
||||
KeyboardPlugin(),
|
||||
SensorPlugin(),
|
||||
)
|
||||
|
||||
override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) =
|
||||
plugins.forEach { it.onAttachedToEngine(binding) }
|
||||
|
||||
override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) =
|
||||
plugins.forEach { it.onDetachedFromEngine(binding) }
|
||||
|
||||
override fun onAttachedToActivity(binding: ActivityPluginBinding) =
|
||||
plugins.forEach { it.onAttachedToActivity(binding) }
|
||||
|
||||
override fun onDetachedFromActivity() =
|
||||
plugins.forEach { it.onDetachedFromActivity() }
|
||||
|
||||
override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) =
|
||||
plugins.forEach { it.onReattachedToActivityForConfigChanges(binding) }
|
||||
|
||||
override fun onDetachedFromActivityForConfigChanges() =
|
||||
plugins.forEach { it.onDetachedFromActivityForConfigChanges() }
|
||||
}
|
||||
Reference in New Issue
Block a user