
Android簡單實現?定義的動畫效果
我??公司的業務需求上是基本不會涉及動畫相關的,也可以說基本兩年沒怎么做過動畫相關的開發,這次寫這篇?章是因為讀到?篇?較好的?
章,想把它記錄下來,以后有做動畫效果的需求的話就能快速上?。
參考《Android開發藝術探索》7.3.4對任意屬性做動畫
眾所周知Android??動畫有3種,View動畫、幀動畫和屬性動畫。不同的場景使?不同的動畫,對控件??,你想實現?個?定義動畫的效果,
也就是隨?,那就使?屬性動畫會?較好,因為View動畫只提供了簡單的平移、翻轉、縮放、透明度。
當然這?也不會去介紹?些基礎的內容。為什么單獨說這??節,因為我覺得這個地?是這章(第七章)最經典的地?。
?.對任意屬性做動畫
按照書上的邏輯來講。
?開始舉了?個栗?,給Button加個動畫,讓這個Button的寬度增加500px。
直接寫屬性動畫的代碼:
(mButton,"width",500).tDuration(5000).start();
這?是對這個Button的width屬性做動畫,也就是對寬度這個屬性做動畫,但是并不能實現我們想要的寬度增加500px的效果。這時候就先引出
了?個重要的結論:
屬性動畫要求動畫作?的對象提供該屬性的get和t?法
這個很重要,意思就是說,這個mButton對象,沒有提供getWidth和tWidth?法。其實這說法有點那啥,因為Button是有getWidth和
tWidth的?法,但是為什么沒?效呢?
這是展?了tWidth的源碼
publicvoidtWidth(intpixels){
mMaxWidth=mMinWidth=pixels;
mMaxWidthMode=mMinWidthMode=PIXELS;
requestLayout();
invalidate();
}
發現這?并不是設置Button的寬度,?是設置Button的最?寬度和最?寬度。
也就是說在上?的動畫中:真的的是隨著時間的改變去改變控件的最?最?寬度,所以視覺看不出效果,因為實際作?的屬性不是你想要去讓它作
?的屬性
所以想要實現效果,應該要提供該屬性正確的get/t?法
書上?寫出了這樣的?個結論(原話):
針對上訴問題,官??檔上告訴我們有3種解決?法:
給你的對象加上get和t?法,如果你有權限的話
??個類來包裝原始對象,間接為其提供get和t?法
采?ValueAnimator,監聽動畫過程,??實現屬性的變化
第?個?案肯定不可?,系統的View不是我們說改就改的,然后?兩個Demo分別來描述?法2和?法3(不能復制要?寫,好不想寫)
?法2:
privatestaticclassViewWrapper{
privateViewmTarget;
publicViewWrapper(Viewtarget){
mTarget=target;
}
publicintgetWidth(){
outParams().width;
}
publicvoidtWidth(intwidth){
outParams().width=width;
tLayout();
}
}
調?的時候
ViewWrapperwrapper=newViewWrapper(mButton);
(wrapper,"width",500).tDuration(5000).start();
這樣就能正常展?我們想要的動畫效果,對象是wrapper,它確實為width屬性提供了get/t?法。動畫內部在執?過程中會拿到傳給它的屬
性,然后?反射去調?它的get/st?法。但是怎么說呢,具體的屬性改變的算法還是要你去?動寫。
?法3:
ValueAnimatorvalueAnimator=(1,100);
ateListener(orUpdateListener(){
privateIntEvaluatormEvaluator=newIntEvaluator();
@Override
publicvoidonAnimationUpdate(ValueAnimatoranimation){
intcurrentValue=(Integer)matedValue();
floatfraction=matedFraction();
outParams().width=te(fraction,start,end);
tLayout();
}
});
這個?法就是對動畫進?監聽,每監聽到?幀的時候再做具體的操作。可以看到這?也沒寫get/t?法,?概就那么?個意思就得了,也不是?
得說?定要這樣寫,或者不?這兩種?法也還有其它?法能實現。
總之,屬性的具體的變化,是需要我們??去寫邏輯(如果要實現?定義的效果),?ObjectAnimator、ValueAnimator這些屬性?告的類,
能告訴我們這個動畫執?的整個過程,簡單的說就是我們知道播放到哪?幀,就能做到在這?幀做什么效果。
這兩個Demo也是我覺得這章最有意思的地?。
?.??實現?個?定義動畫
光看肯定是3天忘,??動?寫個簡單的?定義動畫效果。
我弄?個圓形View,可以拖動它,點擊下去的時候圓會放?并變成正?形,然后移動,松開時正?形會縮?并變回圓,?且我們要讓圓變成正?
形不是秒變,要有個漸變的效果(只實現了簡單的漸變效果,因為懶得去計算)。
最終的效果也沒有做成gif,想看效果的直接復制代碼去試就?,不多。
1.繪制view的初始位置
我這Demo再補充?些細節的東西,還是《Android開發藝術探索》3.1.2View的位置參數
不是什么難點,就是有些細節要注意,這個view的位置參數列舉了3套
(1)Left,Right,Top,Bottom,當成?個矩形看(圓也是矩形),就是4條邊距離?容器xy軸的距離。
(2)x,y左上點的坐標
(3)translationX,translationY距離?View坐標的偏移量
我就直接貼代碼講吧。
先看Activity布局
xmlns:android="/apk/res/android"
android:id="@+id/fl_content"
android:padding="100px"
android:layout_width="match_parent"
android:layout_height="match_parent">
這?padding?個100px,是為了?便介紹這些?位,單位相同容易看,實際開發中肯定最好?dp做單位。
然后看Activity代碼
publicclassRsActivityextendsActivity{
privateFrameLayoutflContent;
privateRoundSquareViewroundSquareView;
@Override
protectedvoidonCreate(BundlesavedInstanceState){
te(savedInstanceState);
tContentView(ty_rs);
initView();
}
privatevoidinitView(){
flContent=findViewById(_content);
roundSquareView=newRoundSquareView(this);
Paramslp=Params(150,150);
outParams(lp);
w(roundSquareView);
(100);
(100);
}
@Override
protectedvoidonResume(){
me();
Handlerhandler=newHandler();
layed(newRunnable(){
@Override
publicvoidrun(){
Log.v("mmp","getLeft"+t());
Log.v("mmp","getTranslationX"+nslationX());
Log.v("mmp","getX"+());
(0);
}
},1000);
}
}
RoundSquareView是?個?定義View,先不?管它。
第?個問題來了,為什么要寫個延遲,重點啊,因為getLeft,就是獲取第?套的那4個屬性,要在view繪制完成之后才能獲取到,不然獲取到的
會是0,加個延遲是為了保證繪制完成(這只是Demo,真實開發中判斷繪制完成肯定不能?延時這樣玩)
看看顯?結果
再看看打印結果
距離頂部和左邊都是200px,但是left打印是100,如果把?布局中的padding去掉的話,left會打印0,這就是第?個地?,使?Left的時候要注
意padding,并且它不算translationX偏移的部分。
然后translationX也打印的是100,他也不算是padding的部分。
最后getX是200,他是正常的相對于?布局的部分距離,不受任何影響。
也證實了x=left+translationX
這?只是為了介紹?些細節上的東西?已,onResume??的代碼對我們要實現的功能沒有任何意義,所以使?時請屏蔽掉。
2.?定義View
看看代碼
publicclassRoundSquareViewextendsView{
privatefloatoldRawX=0;
privatefloatoldRawY=0;
privateintcurrentValue=0;
privatebooleanisExpand;
publicRoundSquareView(Contextcontext){
super(context);
}
publicRoundSquareView(Contextcontext,AttributeSetattrs){
super(context,attrs);
}
publicRoundSquareView(Contextcontext,AttributeSetattrs,intdefStyleAttr){
super(context,attrs,defStyleAttr);
}
@Override
publicvoiddraw(Canvascanvas){
(canvas);
Paintpaint=newPaint();
or();
le();
okeWidth(1);
intw=getWidth()/2;
inth=getHeight()/2;
if(!isExpand){
if(!isExpand){
//?擴?狀態下的繪制
rcle(w,h,w+currentValue,paint);
}el{
//擴?狀態下的繪制
rcle(w,h,w+(100-currentValue),paint);
}
}
@Override
publicbooleanonTouchEvent(MotionEventevent){
switch(ion()){
_DOWN:
isExpand=fal;
expand();
oldRawX=X();
oldRawY=Y();
returntrue;
_MOVE:
moveView(X(),Y());
returntrue;
_UP:
oldRawX=0;
oldRawX=0;
isExpand=true;
narrow();
returntrue;
}
hEvent(event);
}
@Override
publicbooleanperformClick(){
mClick();
}
privatevoidmoveView(floatrawX,floatrawY){
//計算偏移量
floatofftX=rawX-oldRawX;
floatofftY=rawY-oldRawY;
//更改位置
tX(getX()+offtX);
tY(getY()+offtY);
//更新位置
oldRawX=rawX;
oldRawY=rawY;
}
/**
*擴?
*/
privatevoidexpand(){
intw=getWidth();
inth=getHeight();
Paramslp=outParams();
ValueAnimatorvalueAnimator=(1,100);
ateListener(orUpdateListener(){
@Override
publicvoidonAnimationUpdate(ValueAnimatoranimation){
currentValue=(int)matedValue();
Log.v("mmp","動畫進度"+currentValue);
=w+(w/100*currentValue);
=h+(h/100*currentValue);
outParams(lp);
}
});
ation(300).start();
}
/**
*縮?
*/
privatevoidnarrow(){
intw=getWidth();
inth=getHeight();
Paramslp=outParams();
ValueAnimatorvalueAnimator=(1,100);
ateListener(orUpdateListener(){
@Override
publicvoidonAnimationUpdate(ValueAnimatoranimation){
currentValue=(int)matedValue();
Log.v("mmp","動畫進度"+currentValue);
=w-(w/200*currentValue);
=h-(h/200*currentValue);
outParams(lp);
}
});
ation(300).start();
}
}
?定義View,在draw中?Paint畫個圓,這個,這個沒什么好說的,都能看懂,最后
if(!isExpand){
//?擴?狀態下的繪制
rcle(w,h,w+currentValue,paint);
}el{
//擴?狀態下的繪制
rcle(w,h,w+(100-currentValue),paint);
}
先不?管,先看成
rcle(w,h,w,paint);
這樣就畫成?個圓了。
然后寫onTouchEvent讓view隨?指移動?移動。記錄改變前的?指的點擊位置oldRawX,oldRawY,去獲取當前的位置減去舊的位置就能得到
?個偏移量,然后再?這個偏移量去改變x和y屬性,這是最簡單的view隨?指移動的?式。
然后在按下時調?expand()做放?的屬性動畫,再抬起時調?narrow()做縮?的屬性動畫。
這?是?了上?的?法3去實現屬性動畫,這?離就不多說了,定義了?個變量isExpand來記錄當前是否處于放?的狀態。
最后,這個Demo只是簡單的實現動畫的效果,會存在?些問題,?如說在放?動畫的執?過程中抬起,這些都沒做處理,時間問題,就不打算花
太多時間在這個Demo上。
本文發布于:2023-03-02 05:42:24,感謝您對本站的認可!
本文鏈接:http://m.newhan.cn/zhishi/a/16777069445623.html
版權聲明:本站內容均來自互聯網,僅供演示用,請勿用于商業和其他非法用途。如果侵犯了您的權益請與我們聯系,我們將在24小時內刪除。
本文word下載地址:自定義動畫.doc
本文 PDF 下載地址:自定義動畫.pdf
| 留言與評論(共有 0 條評論) |