裸眼 3D 效果 Compose 版本

简介: 裸眼 3D 效果 Compose 版本

前因后果

今天在博客中看见自如客APP研发团队发的一篇文章:自如客APP裸眼3D效果的实现,看了看效果感觉很炫,然后又看到已经有人使用 Flutter 实现了这个效果,Flutter 能实现,Compose 肯定也没问题,来吧,说干就干。

实现思路

先来看看实现的效果吧,没有人家的那么好看,大家将就着看吧😂。

b6ac22e946784c2a95c6fc2f823851ae.gif

实现思路其实很简单,就是放了两层布局(当然自如客APP中实现是三层布局,原理是一样的),姑且叫背景和前景吧,背景不动,前景跟随设备旋转的角度来进行位置偏移就可以了。

码代码

实现思路有了,下面就来码代码吧,先来注册下传感器吧:

mSensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
// 陀螺仪传感器
mMagneticSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD)
mSensorManager.registerListener(this, mMagneticSensor, SensorManager.SENSOR_DELAY_GAME)

再来在回调中获取下需要偏移的坐标:

override fun onSensorChanged(event: SensorEvent?) {
    if (event == null) return
    when (event.sensor.type) {
        Sensor.TYPE_ACCELEROMETER -> {
            // x,y,z分别存储坐标轴x,y,z上的加速度
            val x = event.values[0]
            val y = event.values[1]
            val z = event.values[2]
            refreshState(x, y)
            Log.d(TAG, "TYPE_ACCELEROMETER x:$x y:$y z:$z")
        }
        Sensor.TYPE_MAGNETIC_FIELD -> {
            // 三个坐标轴方向上的电磁强度,单位是微特拉斯(micro-Tesla),用uT表示,也可以是高斯(Gauss),1Tesla=10000Gauss
            val x = event.values[0]
            val y = event.values[1]
            val z = event.values[2]
            refreshState(x, y)
            Log.d(TAG, "TYPE_MAGNETIC_FIELD x:$x y:$y z:$z")
        }
    }
}

获取完坐标后就需要思考一个问题,在 Compose 中我们一直说数据驱动 UI 改变,这里也同样是,先来创建一个 ViewModel:

class MainViewModel : ViewModel() {
    private val _xState = MutableLiveData(0f)
    val xState: LiveData<Float> = _xState
    fun onxStateChanged(position: Float) {
        _xState.value = position
    }
    private val _yState = MutableLiveData(0f)
    val yState: LiveData<Float> = _yState
    fun onyStateChanged(position: Float) {
        _yState.value = position
    }
}

ViewModel 中提供了两个方法,分别来修改 x 和 y 的坐标,上面的 refreshState 方法中就调用的是这两个方法:

private fun refreshState(x: Float, y: Float) {
    viewModel.onxStateChanged(x)
    viewModel.onyStateChanged(y)
}

好了,万事具备,只欠东风,下面就来画布局吧:

@Composable
fun ThreeDImage(x: Float, y: Float) {
    Box(modifier = Modifier.fillMaxSize()) {
        Image(
            modifier = Modifier
                .fillMaxSize(),
            contentScale = ContentScale.Crop,
            painter = painterResource(id = R.drawable.icon_three_bg),
            contentDescription = "背景",
        )
        Image(
            modifier = Modifier
                .fillMaxSize()
                .offset(x = x.dp, y = y.dp),
            painter = painterResource(id = R.drawable.icon_three_small),
            contentDescription = "前景",
        )
    }
}

ThreeDImage 可组合项中接受两个参数,分别是前景需要偏移的 x 和 y 值,整个布局使用 Box 进行包裹,里面依次放了背景和前景,然后根据传进来需要偏移的 x 和 y 值来对前景做偏移。

是不是非常简单,这还是多亏了 Compose 中万能的 Modifier ,调用 Modifier 的扩展方法 offset 即可调整布局的偏移量。

最后把 ViewModel 中的 LiveData 数据转为 Compose 中可观察的 State 类型即可:

setContent {
    BannerTheme {
        val xState by viewModel.xState.observeAsState(0f)
        val yState by viewModel.yState.observeAsState(0f)
        Surface(color = MaterialTheme.colors.background) {
            ThreeDImage(xState, yState)
        }
    }
}

OK,到这里代码就写完了,是不是很简单,核心代码只有一行: Modifier .offset(x = x.dp, y = y.dp)。

写在最后

本文只是给大家提供一个实现的思路,大家跟着文中的代码再优化下效果会更好的。

本文中所有代码都在 Github 中进行托管:https://github.com/zhujiang521/Banner ,有需要的可以进行查看。



目录
相关文章
|
移动开发 JavaScript Java
H5与App使用WebViewJavascriptBridge进行交互
H5与App使用WebViewJavascriptBridge进行交互
1069 0
|
弹性计算 缓存 数据库
2024年2核4G云服务器多少钱?有优惠吗?非常便宜!
2024年2核4G云服务器多少钱?有优惠吗?非常便宜!2核4G配置1个月多少钱?2核4G服务器30元3个月、轻量应用服务器2核4G4M带宽165元一年、企业用户2核4G5M带宽199元一年
|
开发框架 JavaScript 前端开发
在Vue前端界面中,几种数据表格的展示处理,以及表格编辑录入处理操作。
在Vue前端界面中,几种数据表格的展示处理,以及表格编辑录入处理操作。
idea右击项目却不显示svn提交按钮菜单Subversion选项,无法提交代码
idea右击项目却不显示svn提交按钮菜单Subversion选项,无法提交代码
2397 0
idea右击项目却不显示svn提交按钮菜单Subversion选项,无法提交代码
|
KVM 虚拟化 云计算
Windows 10 |VMware开启虚拟化的最全面说明
Windows 10 |VMware开启虚拟化的最全面说明
1805 0
|
Web App开发 安全 Shell
【异常解决】浏览器无法访问此网站ERR_UNSAFE_PORT/网页可能无法连接,或者它已永久性地移动到了新网址问题解决方案
【异常解决】浏览器无法访问此网站ERR_UNSAFE_PORT/网页可能无法连接,或者它已永久性地移动到了新网址问题解决方案
3464 0
|
缓存 前端开发 Java
卡顿监测 · 方案篇 · Android卡顿监测指导原则
卡顿监测 · 方案篇 · Android卡顿监测指导原则
1077 0
卡顿监测 · 方案篇 · Android卡顿监测指导原则
|
存储 数据管理 数据处理
阿里云oss流量费用是怎么算的?
阿里云oss流量费用是怎么算的?OSS回源下行流量包价格,OSS流量包100G 49元/月
3460 0
|
Android开发 UED 开发者
两种方法,教你解决 ViewPager 嵌套 ViewPager滑动冲突(二)
两种方法,教你解决 ViewPager 嵌套 ViewPager滑动冲突
|
Linux Windows
svn 钩子 hooks 的 pre-commit 配置递交文件格式,文件大小,备注必填
svn 钩子 hooks 的 pre-commit 配置递交文件格式,文件大小,备注必填