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

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

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

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

項目代碼:https://gitee.com/jiugeishere/uidesign

控件效果如下:

請?zhí)砑訄D片描述

實現(xiàn)功能:

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

設(shè)計核心:

主要的設(shè)計核心是依賴于傳感器對手機晃動的監(jiān)聽(重力感應(yīng)監(jiān)聽器),對每層圖片進行不同的移動,實現(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軸移動偏移量 實際偏移為MOVE_DISTANCE_X*acclerateratio
    private static final double MOVE_DISTANCE_Y = 50;//Y軸移動偏移量 實際偏移為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);
            // 地磁場傳感器
            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) {

    }

    //移動
    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è)置移動速度
    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"/>

項目代碼倉庫 UIDesign 開源項目

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

相關(guān)文章

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

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

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

    Android 輕松獲取CPU型號的方法

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

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

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

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

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

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

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

    Android4.1中BinderService用法實例分析

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

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

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

    詳細分析Android中onTouch事件傳遞機制

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

    Android中3種全屏方法及3種去掉標題欄的方法

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

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

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

最新評論

江北区| 樟树市| 绩溪县| 明光市| 环江| 宜丰县| 罗江县| 图木舒克市| 平谷区| 泰顺县| 安福县| 凌源市| 香河县| 洪泽县| 鄱阳县| 新田县| 烟台市| 仁怀市| 历史| 米林县| 朝阳区| 甘南县| 上虞市| 尤溪县| 奇台县| 白朗县| 施秉县| 罗江县| 营口市| 拜泉县| 千阳县| 辽阳县| 宁波市| 武邑县| 丁青县| 恩施市| 德惠市| 万源市| 丹阳市| 望城县| 兴安盟|