版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
【移動應(yīng)用開發(fā)技術(shù)】如何在Android項(xiàng)目中實(shí)現(xiàn)一個(gè)3D立體旋轉(zhuǎn)效果
本文章向大家介紹如何在Android項(xiàng)目中實(shí)現(xiàn)一個(gè)3D立體旋轉(zhuǎn)效果,主要包括如何在Android項(xiàng)目中實(shí)現(xiàn)一個(gè)3D立體旋轉(zhuǎn)效果的使用實(shí)例、應(yīng)用技巧、基本知識點(diǎn)總結(jié)和需要注意事項(xiàng),具有一定的參考價(jià)值,需要的朋友可以參考一下。Android是一種基于Linux內(nèi)核的自由及開放源代碼的操作系統(tǒng),主要使用于移動設(shè)備,如智能手機(jī)和平板電腦,由美國Google公司和開放手機(jī)聯(lián)盟領(lǐng)導(dǎo)及開發(fā)。使用方式此空間繼承與FrameLayout子空間直接添加如同framelayout相同如要如圖效果唯一要求子空間必須位于父控件中心且寬高等大小為了方便擴(kuò)展而做如有其他需求可自行更改(注所有子控件最好添加上背景由于繪制機(jī)制和動畫原因沒有背景會有部分重貼)內(nèi)部子view可為任意ViewGroup。弱使用過程中遇見任何BUG歡迎提出。三實(shí)現(xiàn)原理
實(shí)現(xiàn)原理由Camera與Maxtrix組合修改View的繪制而得具體Camera與Maxtrix的變換過程請自行搜索。在此不班門弄斧。具體修改有@Override
protected
void
dispatchDraw(Canvas
canvas)
{
int
indexleft
=
getWidth()
/
2;//中間顯示視圖
左邊的位置
int
postTranslateX
=
rotationX
*
childWith
/
2
/
rotation;//設(shè)定邊移動
距離
//定點(diǎn)
又稱頂點(diǎn)
//
chilDrawforCamera(canvas,
postTranslateX,
indexleft,
3);//預(yù)繪制
的
縣繪制
防止遮擋
for
(int
i
=
0;
i
<
4;
i++)
chilDrawforCamera(canvas,
postTranslateX,
indexleft,
i);
if
(!isTouch)
handler.sendEmptyMessageDelayed(1,
100);
}重新編寫dispathDraw()從而達(dá)到不必要去修改子view的內(nèi)容而添加擴(kuò)展性具體變換包括private
void
chilDrawforCamera(Canvas
canvas,
int
postTranslateX,
int
indexleft,
int
i)
{
canvas.save();
mCamera.save();
mMaxtrix.reset();
mCamera.translate(postTranslateX,
0,
0);
mCamera.rotateY(rotationX);
mCamera.translate(postTranslateX,
0,
0);
if
(postTranslateX
==
0)
{
if
(isright)
setCameraChange(childWith,
rotation,
i);
else
setCameraChange(-childWith,
-rotation,
i);
}
else
if
(postTranslateX
>
0)
{
setCameraChange(childWith,
rotation,
i);
}
else
if
(postTranslateX
<
0)
{
setCameraChange(-childWith,
-rotation,
i);
}
mCamera.getMatrix(mMaxtrix);
mCamera.restore();
mMaxtrix.preTranslate(-indexleft,
-getHeight()
/
2);//指定在
屏幕上
運(yùn)行的棱
是哪一條
mMaxtrix.postTranslate(indexleft,
getHeight()
/
2);//運(yùn)行路徑
canvas.concat(mMaxtrix);
//繪制
View
childAt
=
getChildAt((swithView(i)
+
2
*
getChildCount())
%
getChildCount());
drawChild(canvas,
childAt,
0);
canvas.restore();
}指定需要繪制的子view先后順序以及哪些子viewprivate
int
swithView(int
i)
{
int
k
=
0;
switch
(i)
{
case
0:
if
(isright)
k
=
index
-
2;
else
k
=
index
+
2;
break;
case
1:
if
(isright)
k
=
index
+
1;
else
k
=
index
-
1;
break;
case
2:
if
(isright)
k
=
index
-
1;
else
k
=
index
+
1;
break;
case
3:
k
=
index;
break;
}
return
k;具體的網(wǎng)上其他類似效果到底有什么不同于優(yōu)勢在此不多做描述實(shí)現(xiàn)方式上有哪些不同嗯下次有空再細(xì)說(由于需要大量圖文描述3D的變換過程才講的清楚,有些間隔的時(shí)間也稍長只記得大概的思路過程)。private
void
setCameraChange(int
translate,
int
roat,
int
i)
{
switch
(i)
{
case
0:
//預(yù)繪制
的VIEW
mCamera.translate(-translate
/
2,
0,
0);
mCamera.rotateY(-roat);
mCamera.translate(-translate
/
2,
0,
0);
mCamera.translate(-translate
/
2,
0,
0);
mCamera.rotateY(-roat);
mCamera.translate(-translate
/
2,
0,
0);
break;
//當(dāng)前位置兩側(cè)的View
case
1:
mCamera.translate(translate
/
2,
0,
0);
mCamera.rotateY(roat);
mCamera.translate(translate
/
2,
0,
0);
break;
case
2:
mCamera.translate(-translate
/
2,
0,
0);
mCamera.rotateY(-roat);
mCamera.translate(-translate
/
2,
0,
0);
break;
//最后繪制
當(dāng)前顯示位置
防止
被遮擋
case
3:
mCamera.rotateY(0);
break;
}
}其他剩下的就是index選中切換以及滑動內(nèi)容和分發(fā)修改等。demo下載有分的相關(guān)小伙伴就下載提供一些沒有的就github下載吧。整個(gè)類復(fù)制也可以package
com.burning.foethedog;
import
android.content.Context;
import
android.graphics.Camera;
import
android.graphics.Canvas;
import
android.graphics.Matrix;
import
android.os.Handler;
import
android.os.Message;
import
android.util.AttributeSet;
import
android.view.MotionEvent;
import
android.view.View;
import
android.widget.FrameLayout;
/**
*
Created
by
burning
on
2017/5/2.
*
When
I
wrote
this,
only
God
and
I
understood
what
I
was
doing
*
Now,
God
only
knows
*
//┏┓┏┓
*
//┏┛┻━━━┛┻┓
*
//┃┃
*
//┃━┃
*
//┃┳┛┗┳┃
*
//┃┃
*
//┃┻┃
*
//┃┃
*
//┗━┓┏━┛
*
//┃┃
神獸保佑
*
//┃┃
代碼無BUG!
*
//┃┗━━━┓
*
//┃┣┓
*
//┃┏┛
*
//┗┓┓┏━┳┓┏┛
*
//
┃┫┫┃┫┫
*
//
┗┻┛┗┻┛
*/
public
class
Rota3DSwithView
extends
FrameLayout
{
Camera
mCamera;
Matrix
mMaxtrix;
public
Rota3DSwithView(Context
context)
{
super(context);
initRoat3D();
}
private
void
initRoat3D()
{
mCamera
=
new
Camera();
mMaxtrix
=
new
Matrix();
setWillNotDraw(false);
}
public
Rota3DSwithView(Context
context,
AttributeSet
attrs)
{
super(context,
attrs);
initRoat3D();
}
public
Rota3DSwithView(Context
context,
AttributeSet
attrs,
int
defStyleAttr)
{
super(context,
attrs,
defStyleAttr);
initRoat3D();
}
public
Rota3DSwithView(Context
context,
AttributeSet
attrs,
int
defStyleAttr,
int
defStyleRes)
{
super(context,
attrs,
defStyleAttr,
defStyleRes);
initRoat3D();
}
int
childWith;
@Override
protected
void
onLayout(boolean
changed,
int
left,
int
top,
int
right,
int
bottom)
{
childWith
=
getChildAt(0).getMeasuredWidth();
super.onLayout(changed,
left,
top,
right,
bottom);
}
//攝像機(jī)
為點(diǎn)光源
正真的直角
反而看起來
并不是直角
static
int
rotation
=
60;//
設(shè)定外角
int
rotationX
=
00;
int
index
=
0;
@Override
protected
void
dispatchDraw(Canvas
canvas)
{
int
indexleft
=
getWidth()
/
2;//中間顯示視圖
左邊的位置
int
postTranslateX
=
rotationX
*
childWith
/
2
/
rotation;//設(shè)定邊移動
距離
//定點(diǎn)
又稱頂點(diǎn)
//
chilDrawforCamera(canvas,
postTranslateX,
indexleft,
3);//預(yù)繪制
的
縣繪制
防止遮擋
for
(int
i
=
0;
i
<
4;
i++)
chilDrawforCamera(canvas,
postTranslateX,
indexleft,
i);
if
(!isTouch)
handler.sendEmptyMessageDelayed(1,
100);
}
private
void
setCameraChange(int
translate,
int
roat,
int
i)
{
switch
(i)
{
case
0:
//預(yù)繪制
的VIEW
mCamera.translate(-translate
/
2,
0,
0);
mCamera.rotateY(-roat);
mCamera.translate(-translate
/
2,
0,
0);
mCamera.translate(-translate
/
2,
0,
0);
mCamera.rotateY(-roat);
mCamera.translate(-translate
/
2,
0,
0);
break;
//當(dāng)前位置兩側(cè)的View
case
1:
mCamera.translate(translate
/
2,
0,
0);
mCamera.rotateY(roat);
mCamera.translate(translate
/
2,
0,
0);
break;
case
2:
mCamera.translate(-translate
/
2,
0,
0);
mCamera.rotateY(-roat);
mCamera.translate(-translate
/
2,
0,
0);
break;
//最后繪制
當(dāng)前顯示位置
防止
被遮擋
case
3:
mCamera.rotateY(0);
break;
}
}
boolean
isright
=
false;
Handler
handler
=
new
Handler()
{
@Override
public
void
handleMessage(Message
msg)
{
switch
(msg.what)
{
case
1:
if
(isTouch)
return;
if
(isright)
rotationX++;
else
rotationX--;
if
(Math.abs(rotationX)
==
rotation)
{
rotationX
=
0;
index
=
index
%
getChildCount();
if
(isright)
index--;
else
index++;
}
Rota3DSwithView.this.invalidate();
break;
}
}
};
private
void
chilDrawforCamera(Canvas
canvas,
int
postTranslateX,
int
indexleft,
int
i)
{
canvas.save();
mCamera.save();
mMaxtrix.reset();
mCamera.translate(postTranslateX,
0,
0);
mCamera.rotateY(rotationX);
mCamera.translate(postTranslateX,
0,
0);
if
(postTranslateX
==
0)
{
if
(isright)
setCameraChange(childWith,
rotation,
i);
else
setCameraChange(-childWith,
-rotation,
i);
}
else
if
(postTranslateX
>
0)
{
setCameraChange(childWith,
rotation,
i);
}
else
if
(postTranslateX
<
0)
{
setCameraChange(-childWith,
-rotation,
i);
}
mCamera.getMatrix(mMaxtrix);
mCamera.restore();
mMaxtrix.preTranslate(-indexleft,
-getHeight()
/
2);//指定在
屏幕上
運(yùn)行的棱
是哪一條
mMaxtrix.postTranslate(indexleft,
getHeight()
/
2);//運(yùn)行路徑
canvas.concat(mMaxtrix);
//繪制
View
childAt
=
getChildAt((swithView(i)
+
2
*
getChildCount())
%
getChildCount());
drawChild(canvas,
childAt,
0);
canvas.restore();
}
private
int
swithView(int
i)
{
int
k
=
0;
switch
(i)
{
case
0:
if
(isright)
k
=
index
-
2;
else
k
=
index
+
2;
break;
case
1:
if
(isright)
k
=
index
+
1;
else
k
=
index
-
1;
break;
case
2:
if
(isright)
k
=
index
-
1;
else
k
=
index
+
1;
break;
case
3:
k
=
index;
break;
}
return
k;
}
boolean
isTouch
=
false;
int
downX
=
0;
public
boolean
dispatchTouchEvent(MotionEvent
event)
{
//這里我們就
就只分發(fā)給當(dāng)前index子View
isTouch
=
event.getAction()
==
MotionEvent.ACTION_MOVE;
if
(!onInterceptTouchEvent(event))
{
index
=
index
%
getChildCount();
return
getChildAt((index
+
getChildCount())
%
getChildCount()).dispatchTouchEvent(event);
}
return
super.dispatchTouchEvent(event);
}
int
thisRx
=
0;
int
thisindex;
@Override
public
boolean
onInterceptTouchEvent(MotionEvent
event)
{
switch
(event.getAction())
{
case
MotionEvent.ACTION_DOWN:
downX
=
(int)
event.getX();
thisindex
=
index;
thisRx
=
rotationX;
break;
case
MotionEvent.ACTION_MOVE:
if
(Math.abs(event.getX()
-
downX)
>
50)
{
return
true
/*onTouchEvent(event)*/;
}
break;
}
return
false;
}
@Override
public
boolean
onT
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 應(yīng)急消防演練領(lǐng)導(dǎo)講話稿(6篇)
- 開學(xué)典禮活動總結(jié)范文15篇
- 愚人節(jié)文案(匯編15篇)
- 收銀培訓(xùn)資料
- 中國電動汽車充電站行業(yè)政策、市場規(guī)模及投資前景研究報(bào)告(智研咨詢發(fā)布)
- 肝升肺降湯治療慢性腎衰竭升降失?;颊叩呐R床療效觀察
- 組合式長周期光纖光柵傳感器及其特性研究
- 二零二五年度家政服務(wù)與家庭寵物養(yǎng)護(hù)合同3篇
- 二零二五年度城市消防管網(wǎng)消火栓安裝施工協(xié)議3篇
- 無人機(jī)分群的任務(wù)分配與拓?fù)淇刂萍夹g(shù)研究
- 蛋糕店服務(wù)員勞動合同
- 土地買賣合同參考模板
- 2025高考數(shù)學(xué)二輪復(fù)習(xí)-專題一-微專題10-同構(gòu)函數(shù)問題-專項(xiàng)訓(xùn)練【含答案】
- 沈陽理工大學(xué)《數(shù)》2022-2023學(xué)年第一學(xué)期期末試卷
- 北京三甲中醫(yī)疼痛科合作方案
- QCT957-2023洗掃車技術(shù)規(guī)范
- 新外研版高中英語選擇性必修1單詞正序英漢互譯默寫本
- 自愿斷絕父子關(guān)系協(xié)議書電子版
- 人教版高中物理必修二同步練習(xí)及答案
- 2024年高考英語讀后續(xù)寫高分寶典專題08讀后續(xù)寫肢體動作描寫積累1(詞-句-文)講義
- 時(shí)政述評培訓(xùn)課件
評論
0/150
提交評論