最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

 更新時(shí)間:2021年08月16日 14:36:54   作者:玖流之輩  
主要的設(shè)計(jì)核心是依賴于傳感器對(duì)手機(jī)晃動(dòng)的監(jiān)聽(重力感應(yīng)監(jiān)聽器),對(duì)每層圖片進(jìn)行不同的移動(dòng),實(shí)現(xiàn)仿3D效果。本文通過實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友參考下吧

描述:這是一個(gè)裸眼3D效果的控件View。
Tips:本項(xiàng)目代碼部分邏輯參考于其他文章(自如的3D裸眼實(shí)現(xiàn)),眾人拾柴火焰高,希望大家能多多補(bǔ)充。

項(xiàng)目代碼:https://gitee.com/jiugeishere/uidesign

控件效果如下:

請(qǐng)?zhí)砑訄D片描述

實(shí)現(xiàn)功能:

  1. 實(shí)現(xiàn)三層圖片疊加效果(裸眼3D效果)
  2. 可設(shè)置每層圖片移動(dòng)速率
  3. 可設(shè)置每層圖片移動(dòng)的限制度數(shù)
  4. 可直接設(shè)置圖片或引入圖片

設(shè)計(jì)核心:

主要的設(shè)計(jì)核心是依賴于傳感器對(duì)手機(jī)晃動(dòng)的監(jiān)聽(重力感應(yīng)監(jiān)聽器),對(duì)每層圖片進(jìn)行不同的移動(dòng),實(shí)現(xiàn)仿3D效果。

核心代碼:

SensorLayout 用以監(jiān)聽傳感器

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;

/**
* 傳感器監(jiān)聽
* author tangxianfeng
* created  2021.8.15
**/
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;//最小偏移度數(shù)  Y
    private double mDegreeYMax = 50;//最大偏移度數(shù)  Y
    private double mDegreeXMin = -50;//最小偏移度數(shù)  X
    private double mDegreeXMax = 50;//最大偏移度數(shù)  X
    private static final double MOVE_DISTANCE_X = 50;//X軸移動(dòng)偏移量 實(shí)際偏移為MOVE_DISTANCE_X*acclerateratio
    private static final double MOVE_DISTANCE_Y = 50;//Y軸移動(dòng)偏移量 實(shí)際偏移為MOVE_DISTANCE_Y*acclerateratio
    private float acclerateratio = 1;//偏移加速的倍率 可以通過設(shè)置此倍率改變偏移速度
    private final float[] values = new float[3];//包含 x,y,z的偏移量
    private final float[] Sensororientation = new float[9];//旋轉(zhuǎn)矩陣

    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);
            // 地磁場(chǎng)傳感器
            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軸的偏轉(zhuǎn)角度
        double degreeX = (float) Math.toDegrees(values[1]);
        // y軸的偏轉(zhuǎn)角度
        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) {

    }

    //移動(dòng)
    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();
        }
    }

    //解綁監(jiān)聽
    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;
/**
* author tangxianfeng
* created  2021.8.15
**/
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);
    }

    //設(shè)置移動(dòng)速度
    public void setAllratio(float backgroundratio, float midratio, float foregroundratio) {
        sensorbackground.setAcclerateratio(backgroundratio);
        sensormid.setAcclerateratio(midratio);
        sensorforeground.setAcclerateratio(foregroundratio);
    }

    //設(shè)置限制角度
    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 設(shè)置限制角度
    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文件中便可,或者可通過代碼設(shè)置其他屬性。

 <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"/>

項(xiàng)目代碼倉庫 UIDesign 開源項(xiàng)目

到此這篇關(guān)于詳解Android 裸眼3D效果View控件的文章就介紹到這了,更多相關(guān)Android 裸眼3D效果內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Android二維碼開發(fā)學(xué)習(xí)教程

    Android二維碼開發(fā)學(xué)習(xí)教程

    這篇文章主要為大家分享了Android二維碼開發(fā)學(xué)習(xí)教程,感興趣的小伙伴們可以參考一下
    2016-07-07
  • Android 輕松獲取CPU型號(hào)的方法

    Android 輕松獲取CPU型號(hào)的方法

    這篇文章主要介紹了在Android設(shè)備上獲取CPU型號(hào)是一項(xiàng)常見的任務(wù)的相關(guān)資料,需要的朋友可以參考下
    2023-10-10
  • Flutter持久化存儲(chǔ)之?dāng)?shù)據(jù)庫存儲(chǔ)(sqflite)詳解

    Flutter持久化存儲(chǔ)之?dāng)?shù)據(jù)庫存儲(chǔ)(sqflite)詳解

    這篇文章主要給大家介紹了關(guān)于Flutter持久化存儲(chǔ)之?dāng)?shù)據(jù)庫存儲(chǔ)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者使用Flutter具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • Android之自定義實(shí)現(xiàn)BaseAdapter(通用適配器三)

    Android之自定義實(shí)現(xiàn)BaseAdapter(通用適配器三)

    這篇文章主要為大家詳細(xì)介紹了Android之自定義實(shí)現(xiàn)BaseAdapter通用適配器第三篇,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-12-12
  • Android Studio給各種控件加邊框的操作方法

    Android Studio給各種控件加邊框的操作方法

    這篇文章主要介紹了Android Studio給各種控件加邊框的操作方法,本文通過圖文實(shí)例相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-12-12
  • Android4.1中BinderService用法實(shí)例分析

    Android4.1中BinderService用法實(shí)例分析

    這篇文章主要介紹了Android4.1中BinderService用法,以實(shí)例形式分析了Android4.1新增BinderService類的功能、原理及使用技巧,具有一定參考借鑒價(jià)值
    2015-10-10
  • Kotlin 集合函數(shù)map 和 first 的使用場(chǎng)景分析

    Kotlin 集合函數(shù)map 和 first 的使用場(chǎng)景分析

    Kotlin 提供了許多強(qiáng)大的集合操作函數(shù),其中 map 適用于轉(zhuǎn)換集合,first 適用于獲取符合條件的第一個(gè)元素,這篇文章給大家介紹Kotlin 集合函數(shù):map 和 first 的使用場(chǎng)景,感興趣的朋友一起看看吧
    2025-04-04
  • 詳細(xì)分析Android中onTouch事件傳遞機(jī)制

    詳細(xì)分析Android中onTouch事件傳遞機(jī)制

    相信不少朋友在剛開始學(xué)習(xí)Android的時(shí)候,對(duì)于onTouch相關(guān)的事件一頭霧水。分不清onTouch(),onTouchEvent()和OnClick()之間的關(guān)系和先后順序,所以覺得有必要搞清onTouch事件傳遞的原理。經(jīng)過一段時(shí)間的琢磨以及相關(guān)博客的介紹,這篇文章就給大家詳細(xì)的分析介紹下。
    2016-10-10
  • Android中3種全屏方法及3種去掉標(biāo)題欄的方法

    Android中3種全屏方法及3種去掉標(biāo)題欄的方法

    這篇文章主要介紹了Android中3種全屏方法及3種去掉標(biāo)題欄的方法,二個(gè)問題各給出了3種解決方法,并給出實(shí)例代碼,需要的朋友可以參考下
    2015-06-06
  • Android仿360桌面手機(jī)衛(wèi)士懸浮窗效果

    Android仿360桌面手機(jī)衛(wèi)士懸浮窗效果

    這篇文章主要介紹了Android仿360手機(jī)衛(wèi)士懸浮窗效果的桌面實(shí)現(xiàn),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-05-05

最新評(píng)論

汾西县| 盐边县| 峨眉山市| 阜宁县| 紫阳县| 仪征市| 沈阳市| 渝北区| 甘肃省| 怀仁县| 昭通市| 荔浦县| 隆安县| 屏山县| 文山县| 旬邑县| 临沂市| 宁海县| 太湖县| 延寿县| 永平县| 枣强县| 信阳市| 新巴尔虎右旗| 辛集市| 汉阴县| 龙海市| 额济纳旗| 齐河县| 黎城县| 吉木乃县| 荥经县| 康乐县| 桐庐县| 普格县| 沧州市| 惠来县| 平塘县| 合江县| 连山| 阜平县|