日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

实践自定义UI—View

發(fā)布時(shí)間:2025/6/15 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 实践自定义UI—View 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

?目前IOS和Android兩個(gè)系統(tǒng)的交互設(shè)計(jì)都在相互的借鑒,所以有的時(shí)候我們需要在Android系統(tǒng)中實(shí)現(xiàn)IOS的一些UI效果,那我們就必須自己實(shí)現(xiàn)啦(沒有現(xiàn)成的控件)。現(xiàn)在也看到很多公司也把能夠自定義UI放到招聘要求中,可見我們還是要學(xué)習(xí)如何去自定義。當(dāng)然我們自定義UI的過程中,可以讓我們對Android系統(tǒng)的一些機(jī)制理解的更加透徹。那么自定義UI真的很難嗎,我感覺沒有那么難,只要多練習(xí),自然就可以了。按照我的理解,其實(shí)我們自定義UI是可以通過這三種方法實(shí)現(xiàn):

1.繼承View,直接在Canvas上面繪制。

2.繼承ViewGroup,根據(jù)ViewGroup的繪制流程實(shí)現(xiàn)自己需要的效果。

3.利用已有的UI控件(RelativeLayout,LinearLayout,FrameLayout....),繼承改造或者組合使用等。

接下來就以上的方法,一個(gè)一個(gè)實(shí)踐來練習(xí)吧!

自定義UI(利用View)

?利用View實(shí)現(xiàn)自定義主要是繼承View并利用OnDraw(Canvas canvas)方法繪制自己需要的UI,利用canvas主要可以繪制矩形(包括圓角矩形)、圓、點(diǎn)、線、扇形等,同時(shí)還可以根據(jù)類Path設(shè)置需要的路徑,利用Canvas將Path繪制出來。具體的使用通過實(shí)踐學(xué)習(xí)吧。這里我們還要關(guān)心View中的OnMeasure()方法,這個(gè)方法主要是設(shè)定我們當(dāng)前這個(gè)View的大小。關(guān)于View中的這些方法的分析可以看看這篇文章,分析的比較詳細(xì)。好了,還是實(shí)戰(zhàn)吧(在實(shí)戰(zhàn)中遇到問題不斷的解決,自然對很多東西就了解了,總是看理論的東西還是理解的不透徹哦),今天利用View實(shí)現(xiàn)如下的效果(gif 效果不是很好0_0,這里我們只分析第二個(gè)效果圖,其他的讀者可以自己擴(kuò)展實(shí)現(xiàn)):


效果圖

分解效果圖

?任何復(fù)雜的事情都要學(xué)會(huì)分解成多個(gè)簡單的事情去處理。動(dòng)畫效果的某個(gè)瞬間的靜態(tài)UI如下所示:


運(yùn)動(dòng)的某個(gè)瞬間

通過這個(gè)靜態(tài)的UI,可以看出它的組成很簡單:一個(gè)大圓,一個(gè)實(shí)心的小圓————這個(gè)小圓的中心點(diǎn)是在大圓的圓環(huán)上。這樣就把這個(gè)靜態(tài)的UI分解為:一個(gè)大圓和一個(gè)小圓。

接下來想想怎么讓實(shí)心小圓動(dòng)起來呢?前面說了,小圓的中心在大圓的圓環(huán)上,如果這個(gè)中心不停的沿著大圓的圓環(huán)上走,不就動(dòng)起來的。怎么沿著走呢,看看下面的圖!


坐標(biāo)圖

上圖我們繪制了小球(實(shí)心小圓)的中心位置,這里我們選取的順時(shí)針方向?yàn)檎较?#xff0c;并且0度角為X軸正方向。這里選取了45度角的一個(gè)靜態(tài)分析,假設(shè)定義一個(gè)變量為angle,當(dāng)這個(gè)angle不斷的從0到360變化時(shí),小球就是沿著大圓跑了。根據(jù)上面的圖和前面的分析,應(yīng)該比較清晰的知道原理了吧^_^!

實(shí)現(xiàn)分解效果圖

?這里將實(shí)現(xiàn)上面分解的結(jié)果啦,應(yīng)該很簡單的!

1.繪制圓環(huán)

?在onDraw(Canvas canvas)這個(gè)方法中利用canvas繪制,直接上代碼:

private void drawBigCircle(Canvas canvas){canvas.drawCircle(rectF.centerX(), rectF.centerY(), getBigCircleRadius(), mCirclePaint); }

(這里的rect變量主要是利用Rect累框定繪制圓的范圍)這里主要是利用了canvas的方法(當(dāng)然,繪制circle的方法還有其他幾個(gè)方法可以調(diào)用,根據(jù)自己的需求):

drawCircle(float cx, float cy, float radius, @NonNull Paint paint)

簡單介紹一下參數(shù),這里cx,cy表示的是圓心位置;radius表示圓半徑的大小,paint主要是畫筆,可以設(shè)置顏色等。這個(gè)應(yīng)該比較簡單吧+_+

2.繪制實(shí)心小圓——小球

?還是直接看代碼,然后分析^_^

double sweepAngle = Math.PI/180 * 45; //caculate the circle's center(x, y) float y = (float)Math.sin(sweepAngle)*(getBigCircleRadius()); float x = (float)Math.cos(sweepAngle)*(getBigCircleRadius()); int restoreCount = canvas.save(); //change aix center position canvas.translate(rectF.centerX(), rectF.centerY()); canvas.drawCircle(x, y, mAccBallRadius, mAccBallPaint); canvas.restoreToCount(restoreCount);

這里的第一步是計(jì)算角度,第二是計(jì)算實(shí)心小圓的中心位置,這兩步根據(jù)上面分解章節(jié)的數(shù)學(xué)計(jì)算應(yīng)該很好理解的。第三步是繪制實(shí)心小球,這里實(shí)現(xiàn)實(shí)心是通過Paint的方法setStyle(Paint.Style.FILL)設(shè)置充滿整個(gè)圓;

接下來就是繪制這個(gè)“小球”啦。首先移動(dòng)畫布(改變坐標(biāo)系的中心位置):在計(jì)算小球的中心位置(cx,cy)的時(shí)候,是根據(jù)大圓的半徑計(jì)算的,所以這里的(cx,cy)是到大圓中心點(diǎn)的距離。因此,Canvas的起始位置應(yīng)該移動(dòng)到大圓的中心位置。

這里首先要保存一下畫布,在繪制結(jié)束了還要恢復(fù)到原來的狀態(tài),為什么?因?yàn)樵诶L制之前我們需要對畫布進(jìn)行移動(dòng),當(dāng)繪制結(jié)束的時(shí)候如果不恢復(fù)到原來的狀態(tài),Canvas將一直保持在目前的狀態(tài),而后面的有可能是需要在沒有移動(dòng)的畫布上繪制其他圖案,這時(shí)候的中心位置改變了,就會(huì)存在問題。

3.讓小球動(dòng)起來

?上面的兩步我們已經(jīng)把靜態(tài)的狀態(tài)繪制完成了,但是還需要讓這個(gè)小球動(dòng)起來(順著大圓環(huán)跑Y(^_^)Y)。其實(shí)在繪制第二步繪制小球的時(shí)候我們是固定了一個(gè)45度角,如果我們讓這個(gè)角度變化(0-360),那么不就OK了。那么怎么才能做到呢?那就想啊..........,這里想到了利用ValueAimator來實(shí)現(xiàn),關(guān)于這個(gè)類的使用這里就不做介紹。大家可以另外尋找相應(yīng)的文章自行補(bǔ)腦!

AccTypeEvaluator accCore = new AccTypeEvaluator(); ValueAnimator animator = ValueAnimator.ofObject(accCore, 0.0f, 360.0f); animator.setDuration(mDuration); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {Float value = (Float) animation.getAnimatedValue();sweepAngle = value;invalidate();} }); animator.setRepeatCount(ValueAnimator.INFINITE); animator.start();

這里的AccTypeEvaluator定義如下:

public class AccTypeEvaluator implements TypeEvaluator<Float>{@Override public Float evaluate(float fraction, Float startValue, Float endValue) {Log.d("", " current fraction == " + fraction);return fraction * (endValue - startValue);} }

根據(jù)上面的代碼,我們就可以獲得0-360變化了,并且是隨著時(shí)間的變化。當(dāng)我們獲取到角度時(shí)通過調(diào)用invalidate()方法,觸發(fā)View重新繪制界面。這樣就可以達(dá)到我們需要的動(dòng)畫效果啦。

總結(jié)

??上面一步一步介紹了自定義UI的過程,現(xiàn)在應(yīng)該對這個(gè)過程有所了解了——其實(shí)主要還是一個(gè)模型的建立過程。這里簡單總結(jié)一下:

1.一點(diǎn)一點(diǎn)的分解UI,把復(fù)雜的界面分解成一個(gè)一個(gè)靜態(tài)、簡單的界面,并實(shí)現(xiàn)它們。

2.當(dāng)靜態(tài)界面繪制完了,需要?jiǎng)赢嫷摹^察需要改變哪些參數(shù),并且不斷的觸發(fā)View繪制,不就動(dòng)起來了^_^。

3.一些比較復(fù)雜的動(dòng)畫或者效果就需要一些物理、數(shù)學(xué)方面的知識來輔助了——塞貝爾曲線等,其實(shí)這些就需要花費(fèi)你一些時(shí)間去研究了(但是,還是那句話,從簡單到復(fù)雜)。

4.多多的練習(xí),只有練習(xí)你才能對自定義有更深的理解。

這里放一個(gè)簡單的自定義UI,讓大家自己實(shí)現(xiàn)吧(這里是靜態(tài)的,大家也可以讓它動(dòng)起來0_0)!


練習(xí)效果

附上這個(gè)自定義UI的源碼吧——github地址

如何利用ViewGroup自定義UI請閱讀實(shí)踐自定義UI-ViewGroup

如何利用RLF...(RelativeLayout、LinearLayout、FrameLayout...)自定義UI請閱讀實(shí)踐自定義UI—RLF...(RelativeLayout LinearLayout FrameLayout....)

希望在Android學(xué)習(xí)的路上,大家共同成長!

總結(jié)

以上是生活随笔為你收集整理的实践自定义UI—View的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。