iis服务器助手广告广告
返回顶部
首页 > 资讯 > 移动开发 >详解Android 裸眼3D效果View控件
  • 669
分享到

详解Android 裸眼3D效果View控件

2024-04-02 19:04:59 669人浏览 泡泡鱼
摘要

描述:这是一个裸眼3D效果的控件View。 Tips:本项目代码部分逻辑参考于其他文章(自如的3D裸眼实现),众人拾柴火焰高,希望大家能多多补充。 项目代码:https://gite

描述:这是一个裸眼3D效果的控件View。
Tips:本项目代码部分逻辑参考于其他文章(自如的3D裸眼实现),众人拾柴火焰高,希望大家能多多补充。

项目代码:https://gitee.com/jiugeishere/uidesign

控件效果如下:

请添加图片描述

实现功能:

  1. 实现三层图片叠加效果(裸眼3D效果)
  2. 可设置每层图片移动速率
  3. 可设置每层图片移动的限制度数
  4. 可直接设置图片或引入图片

设计核心:

主要的设计核心是依赖于传感器对手机晃动的监听(重力感应监听器),对每层图片进行不同的移动,实现仿3D效果。

核心代码:

SensorLayout 用以监听传感器


import Android.content.Context;
import android.content.res.TypedArray;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensORManager;
import android.util.AttributeSet;
import android.widget.FrameLayout;
import android.widget.Scroller;

import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.ui.design.R;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


public class SensorLayout extends FrameLayout implements SensorEventListener {
    private final SensorManager mSensorManager;
    private float[] MaccelerateValues;
    private float[] mMagneticValues;
    private final Scroller mScroller;
    private double mDegreeYMin = -50;//最小偏移度数  Y
    private double mDegreeYMax = 50;//最大偏移度数  Y
    private double mDegreeXMin = -50;//最小偏移度数  X
    private double mDegreeXMax = 50;//最大偏移度数  X
    private static final double MOVE_DISTANCE_X = 50;//X轴移动偏移量 实际偏移为MOVE_DISTANCE_X*acclerateratio
    private static final double MOVE_DISTANCE_Y = 50;//Y轴移动偏移量 实际偏移为MOVE_DISTANCE_Y*acclerateratio
    private float acclerateratio = 1;//偏移加速的倍率 可以通过设置此倍率改变偏移速度
    private final float[] values = new float[3];//包含 x,y,z的偏移量
    private final float[] Sensororientation = new float[9];//旋转矩阵

    public SensorLayout(@NonNull Context context) {
        this(context, null);
    }

    public SensorLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public SensorLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mScroller = new Scroller(context);
        if (attrs != null) {
            TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.SensorLayoutStyle);
            acclerateratio = typedArray.getFloat(R.styleable.SensorLayoutStyle_AccelerateRatio, 1);
        }
        mSensorManager = (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE);
        if (mSensorManager != null) {
            Sensor accelerateSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
            // 地磁场传感器
            Sensor magneticSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
            mSensorManager.reGISterListener(this, accelerateSensor, SensorManager.SENSOR_DELAY_GAME);
            mSensorManager.registerListener(this, magneticSensor, SensorManager.SENSOR_DELAY_GAME);
        }
    }


    @Override
    public void onSensorChanged(SensorEvent event) {
        if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
            mAccelerateValues = event.values;
        }
        if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
            mMagneticValues = event.values;
        }

        if (mMagneticValues != null && mAccelerateValues != null)
            SensorManager.getRotationMatrix(Sensororientation, null, mAccelerateValues, mMagneticValues);
        SensorManager.getOrientation(Sensororientation, values);
        // x轴的偏转角度
        double degreeX = (float) Math.toDegrees(values[1]);
        // y轴的偏转角度
        double degreeY = (float) Math.toDegrees(values[2]);
        int scrollX = mScroller.getFinalX();
        int scrollY = mScroller.getFinalY();
        if (degreeY <= 0 && degreeY > mDegreeYMin) {
            scrollX = (int) (degreeY / Math.abs(mDegreeYMin) * MOVE_DISTANCE_X * acclerateratio);
        } else if (degreeY > 0 && degreeY < mDegreeYMax) {
            scrollX = (int) (degreeY / Math.abs(mDegreeYMax) * MOVE_DISTANCE_X * acclerateratio);
        }
        if (degreeX <= 0 && degreeX > mDegreeXMin) {
            scrollY = (int) (degreeX / Math.abs(mDegreeXMin) * MOVE_DISTANCE_Y * acclerateratio);
        } else if (degreeX > 0 && degreeX < mDegreeXMax) {
            scrollY = (int) (degreeX / Math.abs(mDegreeXMax) * MOVE_DISTANCE_Y * acclerateratio);
        }
        smoothScroll(scrollX, scrollY);
    }


    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {

    }

    //移动
    public void smoothScroll(int destX, int destY) {
        int scrollY = getScrollY();
        int delta = destY - scrollY;
        mScroller.startScroll(destX, scrollY, 0, delta, 200);
        invalidate();
    }

    @Override
    public void computeScroll() {
        if (mScroller.computeScrollOffset()) {
            scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
            postInvalidate();
        }
    }

    //解绑监听
    public void unregister() {
        mSensorManager.unregisterListener(this);
    }

    public void setDegree(double degreeYMin,double degreeYMax,double degreeXMin,double degreeXMax) {
        mDegreeYMin = degreeYMin;
        mDegreeYMax=degreeYMax;
        degreeXMax=degreeYMax;
        degreeXMin=degreeXMin;
    }

    public void setAcclerateratio(float acclerateratio) {
        this.acclerateratio = acclerateratio;
    }

    @IntDef({DIRECTION_LEFT, DIRECTION_RIGHT})
    @Retention(RetentionPolicy.SOURCE)
    @Target(ElementType.PARAMETER)
    public @interface ADirection {

    }

    public static final int DIRECTION_LEFT = 1;
    public static final int DIRECTION_RIGHT = -1;
}

Sensor3DView 三层视图封装


import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;

import androidx.annotation.Nullable;

import com.bumptech.glide.Glide;
import com.ui.design.R;

public class Sensor3DView extends LinearLayout {

    private SensorLayout sensorforeground;//最上层传感器View
    private SensorLayout sensorbackground;//最底层传感器View
    private SensorLayout sensormid;//中间层传感器View

    private ImageView foregroundimg;//最上层图片
    private ImageView backgroundimg;//底层图片
    private ImageView midimg;//中间层图片

    private Context mContext;

    public Sensor3DView(Context context) {
        super(context);
        this.mContext = context;
    }

    public Sensor3DView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        View inflate = LayoutInflater.from(getContext()).inflate(R.layout.sensor3d_item, this);
        this.mContext = context;
        initView(inflate);

        if (attrs != null) {
            TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.Sensor3DViewStyle);
            float forgroundacclerateratio = typedArray.getFloat(R.styleable.Sensor3DViewStyle_foregroundAccelerateRatio, 1);
            float backgroundacclerateratio = typedArray.getFloat(R.styleable.Sensor3DViewStyle_backgroundAccelerateRatio, 1);
            float midacclerateratio = typedArray.getFloat(R.styleable.Sensor3DViewStyle_midAccelerateRatio, 1);
            setAllImg(typedArray.getResourceId(R.styleable.Sensor3DViewStyle_backgrounddrawable,1),typedArray.getResourceId(R.styleable.Sensor3DViewStyle_middrawable,1),typedArray.getResourceId(R.styleable.Sensor3DViewStyle_foregrounddrawable,1));
            setAllratio(backgroundacclerateratio, midacclerateratio, forgroundacclerateratio);
        }
    }

    private void initView(View inflate) {
        sensorforeground = inflate.findViewById(R.id.sensorforeground);
        sensorbackground = inflate.findViewById(R.id.sensorbackground);
        sensormid = inflate.findViewById(R.id.sensormid);
        midimg = inflate.findViewById(R.id.midimg);
        backgroundimg = inflate.findViewById(R.id.backgroundimg);
        foregroundimg = inflate.findViewById(R.id.foregroundimg);
    }

    //加载三张图片
    public void setAllImg(Object backgroundurl, Object midurl, Object foregroundurl) {
        Glide.with(mContext).load(backgroundurl).into(backgroundimg);
        Glide.with(mContext).load(midurl).into(midimg);
        Glide.with(mContext).load(foregroundurl).into(foregroundimg);
    }

    //设置移动速度
    public void setAllratio(float backgroundratio, float midratio, float foregroundratio) {
        sensorbackground.setAcclerateratio(backgroundratio);
        sensormid.setAcclerateratio(midratio);
        sensorforeground.setAcclerateratio(foregroundratio);
    }

    //设置限制角度
    public void setDegree(float MinX,float MinY,float MaxX,float MaxY,View3DLayer layer){
        if (MinX>=MaxX||MinY>=MaxY){
            return;
        }
        switch (layer){
            case all:
                setDegree(MinY,MaxY,MinX,MaxX,sensorforeground);
                setDegree(MinY,MaxY,MinX,MaxX,sensormid);
                setDegree(MinY,MaxY,MinX,MaxX,sensorbackground);
                break;
            case mid:
                setDegree(MinY,MaxY,MinX,MaxX,sensormid);
                break;
            case background:
                setDegree(MinY,MaxY,MinX,MaxX,sensorbackground);
                break;
            case foreground:
                setDegree(MinY,MaxY,MinX,MaxX,sensorforeground);
                break;
        }
    }

    //sensorLayout 设置限制角度
    private void setDegree(float MinY,float MaxY,float MinX,float MaxX,SensorLayout sensorLayout){
        sensorLayout.setDegree(MinY,MaxY,MinX,MaxX);
    }
    @Override
    public void destroyDrawinGCache() {
        super.destroyDrawingCache();
        sensorbackground.unregister();
        sensormid.unregister();
        sensorforeground.unregister();
    }
    public enum View3DLayer{
        foreground,
        background,
        mid,
        all
    }
}

styles.xml


<!--3D裸眼效果-->
    <declare-styleable name="SensorLayoutStyle">
        <attr name="AccelerateRatio" format="float" />
    </declare-styleable>


    <!--3D裸眼效果集合View-->
    <declare-styleable name="Sensor3DViewStyle">
        <attr name="foregroundAccelerateRatio" format="float" />
        <attr name="backgroundAccelerateRatio" format="float" />
        <attr name="midAccelerateRatio" format="float" />
        <attr name="foregrounddrawable" format="reference" />
        <attr name="backgrounddrawable" format="reference" />
        <attr name="middrawable" format="reference" />
    </declare-styleable>

使用示例:

直接引用到layout文件中便可,或者可通过代码设置其他属性。


 <com.ui.design.view.sensor3D.view.Sensor3DView
        android:id="@+id/sensor3Dview"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:layout_centerInParent="true"
        app:foregrounddrawable="@drawable/forground3d"
        app:backgrounddrawable="@drawable/background3d"
        app:middrawable="@drawable/mid3d"
        app:foregroundAccelerateRatio="4.0"
        app:backgroundAccelerateRatio="-2.0"
        app:midAccelerateRatio="1.0"/>

项目代码仓库 UIDesign 开源项目

到此这篇关于详解Android 裸眼3D效果View控件的文章就介绍到这了,更多相关Android 裸眼3D效果内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: 详解Android 裸眼3D效果View控件

本文链接: https://www.lsjlt.com/news/132695.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 详解Android 裸眼3D效果View控件
    描述:这是一个裸眼3D效果的控件View。 Tips:本项目代码部分逻辑参考于其他文章(自如的3D裸眼实现),众人拾柴火焰高,希望大家能多多补充。 项目代码:https://gite...
    99+
    2024-04-02
  • AndroidOpenGL仿自如APP裸眼3D效果详解
    目录原理简介 & OpenGL 的优势具体实现1. 绘制静态图片2. 让图片动起来3. 几个反直觉的细节4. 帕金森综合征?源码原理简介 & OpenGL 的优势 裸...
    99+
    2024-04-02
  • Android OpenGL如何实现APP裸眼3D效果
    Android OpenGL如何实现APP裸眼3D效果,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。原理简介 & OpenGL 的优势裸眼 3D 效果的本质是...
    99+
    2023-06-28
  • 在小程序中如何实现3d裸眼轮播效果
    小编今天带大家了解在小程序中如何实现3d裸眼轮播效果,文中知识点介绍的非常详细。觉得有帮助的朋友可以跟着小编一起浏览文章的内容,希望能够帮助更多想解决这个问题的朋友找到问题的答案,下面跟着小编一起深入学习“在小程序中如何实现3d裸眼轮播效果...
    99+
    2023-06-26
  • Android自定义view之3D正方体效果实例
    目录前言一、小提二、将传感器改成事件分发机制三、使用四、源码总结前言 在之前写了一篇关于3D效果的文章,借助传感器展示,有小伙伴问可不可以改成手势滑动操作(事件分发),所以出一篇文...
    99+
    2024-04-02
  • Android自定义View实现动画效果详解
    目录帧动画补间动画属性动画帧动画 帧动画就是给定一个完整动画的所有关键帧,由大脑想象中间的变化过程的一种动画。 <xml version="1.0" encoding="utf...
    99+
    2023-02-02
    Android自定义View实现动画 Android 动画 Android自定义View
  • Android通过自定义view实现刮刮乐效果详解
    目录前言实现原理关键步骤创建bitmap绘制文字画路径完整代码前言 已经有两个月没有更新博客了,其实这篇文章我早在两个月前就写好了,一直保存在草稿箱里没有发布出来。原因是有一些原理性...
    99+
    2024-04-02
  • Android自定义view实现滚动选择控件详解
    目录前言需求编写代码主要问题前言 上篇文章通过一个有header和footer的滚动控件(Viewgroup)学了下MeasureSpec、onMeasure以及onLayout,接...
    99+
    2022-11-13
    Android滚动选择 Android滚动选择控件 Android自定义view
  • Android实现控件拖动效果
    本文实例为大家分享了Android实现控件拖动效果的具体代码,供大家参考,具体内容如下 1.今天突然想到做个实现个控件拖动效果,就来试试,一查原来还是很简单的 2.原理就是实现OnT...
    99+
    2024-04-02
  • AndroidFlutter实现3D动画效果示例详解
    目录前言AnimatedWidget 简介3D 旋转动画的实现总结前言 上一篇我们介绍了 Animation 和 AnimationController...
    99+
    2024-04-02
  • Android自定义view实现滑动解锁效果
    本文实例为大家分享了Android自定义view实现滑动解锁的具体代码,供大家参考,具体内容如下 1. 需求如下: 近期需要做一个类似屏幕滑动解锁的功能,右划开始,左划暂停。 2. ...
    99+
    2024-04-02
  • Android 通过自定义view实现水波纹效果案例详解
    在实际的开发中,很多时候还会遇到相对比较复杂的需求,比如产品妹纸或UI妹纸在哪看了个让人兴奋的效果,兴致高昂的来找你,看了之后目的很明确,当然就是希望你能给她; 在这样的关键时候,身...
    99+
    2024-04-02
  • Android圆形控件实现画圆效果
    本文实例为大家分享了Android圆形控件实现画圆效果的具体代码,供大家参考,具体内容如下 实现圆形控件 实现如下 package com.example.demo.util;...
    99+
    2024-04-02
  • Android怎么实现控件拖动效果
    这篇文章主要介绍“Android怎么实现控件拖动效果”,在日常操作中,相信很多人在Android怎么实现控件拖动效果问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Android怎么实现控件拖动效果”的疑惑有所...
    99+
    2023-06-20
  • Android View的事件体系教程详解
    目录一、什么是View?什么是ViewGroup?二、View的位置三、View的触摸事件1.MotionEvent2.TouchSlop3.VelocityTracker5.Scr...
    99+
    2024-04-02
  • Android自定义view之利用drawArc方法实现动态效果(思路详解)
    目录前言一、准备1.测量2.初始化画笔3.自定义属性二、关键方法介绍drawArc 三.实现 1.思路2.效果图前言 前几天看了一位字节Android工程师的一篇...
    99+
    2024-04-02
  • android控件Banner实现简单轮播图效果
    本文实例为大家分享了android控件Banner实现简单轮播图效果的具体代码,供大家参考,具体内容如下 实现这个轮播图是在Fragment里实现的,所以要想实现,首先要创建Frag...
    99+
    2024-04-02
  • Android自定义控件实现雷达图效果
    本文实例为大家分享了Android自定义控件实现雷达图的具体代码,供大家参考,具体内容如下 学习了大神的源代码(奈何不知大神的博客地址),觉得必须记录一下,方便以后再次学习。 效果如...
    99+
    2024-04-02
  • Android自定义View事件分发流程详解
    目录正文事件分发流程总结正文 事件传递和事件分发其实就是一个东西,叫法不一致罢了,你不用被名称所迷惑。有的人管这个叫事件传递机制,有的人则叫它事件分发机制。为了避免混淆,我这里统一...
    99+
    2023-02-02
    Android View事件分发 Android自定义View
  • 基于Android自定义控件实现雷达效果
    如何制作出类似雷达扫描的效果,具体方法如下一、效果图二、实现思路 自定义控件RadarView用来画雷达的效果图,可以自定义属性包括 backgroundColor:背景颜色 circleNum:圆的数量 startColor:开始颜色 e...
    99+
    2023-05-30
    android 雷达 roi
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作