欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

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

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

控件效果如下:

請?zhí)砑訄D片描述

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

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

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

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

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

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

相關(guān)文章

  • android操作XML的幾種方法總結(jié)

    android操作XML的幾種方法總結(jié)

    在android中,操作xml文件,一般有幾種方式:SAX操作,Pull操作,DOM操作等。其中DOM的方式,可能是大家最熟悉的,也是符合W3C標(biāo)準(zhǔn)的
    2013-10-10
  • 適配android7.0獲取文件的Uri的方法

    適配android7.0獲取文件的Uri的方法

    本篇文章主要介紹了適配android7.0獲取文件的Uri的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-09-09
  • Android利用Intent實(shí)現(xiàn)讀取圖片操作

    Android利用Intent實(shí)現(xiàn)讀取圖片操作

    這篇文章主要為大家詳細(xì)介紹了Android利用Intent實(shí)現(xiàn)讀取圖片操作的相關(guān)資料,感興趣的小伙伴們可以參考一下
    2016-06-06
  • Win10下Android App安裝配置開發(fā)環(huán)境

    Win10下Android App安裝配置開發(fā)環(huán)境

    這篇文章主要為大家詳細(xì)介紹了Win10下Android App安裝配置開發(fā)環(huán)境,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-07-07
  • Flutter混合開發(fā)詳解

    Flutter混合開發(fā)詳解

    這篇文章主要介紹了Flutter混合開發(fā)詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-01-01
  • 安卓 獲取手機(jī)IP地址的實(shí)現(xiàn)代碼

    安卓 獲取手機(jī)IP地址的實(shí)現(xiàn)代碼

    本篇文章主要介紹 Android 4.0 獲取手機(jī)IP地址的方法,附有實(shí)現(xiàn)代碼,具有參考價(jià)值,希望對有需要的小伙伴有幫助
    2016-07-07
  • Android中Image的簡單實(shí)例詳解

    Android中Image的簡單實(shí)例詳解

    這篇文章主要為大家詳細(xì)介紹了Android中Image的簡單實(shí)例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-12-12
  • Android編程處理窗口控件大小,形狀,像素等UI元素工具類

    Android編程處理窗口控件大小,形狀,像素等UI元素工具類

    這篇文章主要介紹了Android編程處理窗口控件大小,形狀,像素等UI元素工具類,可實(shí)現(xiàn)像素與dp的轉(zhuǎn)換、窗口寬度設(shè)置、彈出窗口中l(wèi)istview高度設(shè)置等功能,需要的朋友可以參考下
    2017-12-12
  • Android編程實(shí)現(xiàn)向SD卡寫入數(shù)據(jù)的方法

    Android編程實(shí)現(xiàn)向SD卡寫入數(shù)據(jù)的方法

    這篇文章主要介紹了Android編程實(shí)現(xiàn)向SD卡寫入數(shù)據(jù)的方法,涉及Android針對SD卡狀態(tài)判斷,文件及權(quán)限操作等相關(guān)技巧,需要的朋友可以參考下
    2016-04-04
  • Android實(shí)現(xiàn)登錄注冊界面框架

    Android實(shí)現(xiàn)登錄注冊界面框架

    這篇文章主要介紹了Android實(shí)現(xiàn)登錄注冊界面的框架,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-09-09

最新評論