新聞中心
前言
創(chuàng)新互聯(lián)是一家專業(yè)提供貴港企業(yè)網(wǎng)站建設(shè),專注與成都網(wǎng)站制作、做網(wǎng)站、外貿(mào)營銷網(wǎng)站建設(shè)、H5場景定制、小程序制作等業(yè)務(wù)。10年已為貴港眾多企業(yè)、政府機(jī)構(gòu)等服務(wù)。創(chuàng)新互聯(lián)專業(yè)的建站公司優(yōu)惠進(jìn)行中。
說實(shí)話當(dāng)?shù)谝淮慰吹竭@個(gè)需求的時(shí)候,第一反應(yīng)就是Canvas只有drawLine方法,并沒有drawDashLine方法?。∵@咋整啊,難道要我自己做個(gè)遍歷不斷的drawLine?不到1秒,我就放棄這個(gè)想法了,因?yàn)樘珢盒牧?。方法肯定是有的,只不過我不知道而已。
繪制方法
最簡單的方法是利用ShapeDrawable,比如說你想用虛線要隔開兩個(gè)控件,就可以在這兩個(gè)控件中加個(gè)View,然后給它個(gè)虛線背景。
嗯,理論上就是這樣子的,實(shí)現(xiàn)上也很簡單。
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
寫完之后,從Android Studio的預(yù)覽功能上就可以看到效果了。
是不是很簡單呢?慢著,先別高興得太早了,真機(jī)上跑一下看看效果先。
這什么鬼,明明是虛線才對的啊,Studio上的預(yù)覽也可以看出代碼沒問題的。其實(shí),這是因?yàn)槲覀儸F(xiàn)在的手機(jī)默認(rèn)都是開啟了硬件加速的,而dashGap不支持硬件加速,我們只需要修改下View的參數(shù),把硬件加速關(guān)了就好了。
使用ShapeDrawable實(shí)現(xiàn)虛線的方式雖然簡單,但是簡單就意味著不靈活。比如說要求虛線是根據(jù)用戶操作來判斷要不要添加的,這種情況下就不如使用Canvas來實(shí)現(xiàn)方便了。
前面說了,Canvas只有drawLine方法,沒有drawDashLine方法。但是你要知道,畫什么雖然是Canvas決定的,但是怎么畫卻是由畫筆Paint決定的。接下來看看這神奇的畫筆怎么幫我們把直線畫成虛的吧。
Paint有setPathEffect(PathEffect effect)
這么一個(gè)方法,PathEffect一共有五個(gè)子類:ComposePathEffect, CornerPathEffect, DashPathEffect, DiscretePathEffect, PathDashPathEffect, SumPathEffect, 其中的DashPathEffect就是我們需要的虛線效果,其它的幾種效果大家可以自己試一試。
DashPathEffect的創(chuàng)建需要兩個(gè)參數(shù),一個(gè)float數(shù)組,代表實(shí)線與空白處的長度。比如說我給的參數(shù)是new float[] {10, 5}
,那么虛線的一個(gè)單位就是10像素的實(shí)線加上5像素的空白,然后以它為單位去不斷重復(fù)畫,從而形成一條虛線。而如果設(shè)定的參數(shù)是new float[] {10, 5,20, 10},那么虛線的一個(gè)單位就是由10像素實(shí)線,5像素空白,20像素實(shí)線,10像素空白組成的虛線段。
另一個(gè)參數(shù)代表偏移,一般我們設(shè)置為0即可,如果要實(shí)現(xiàn)虛線的動畫效果的話,可以不斷改變這個(gè)值,從而讓虛線動起來。
接著實(shí)現(xiàn)這個(gè)自定義View,并將它代替上面xml文件中的虛線(View)即可。
public class DashLineView extends View { private Paint mPaint; public DashLineView(Context context, AttributeSet attrs) { super(context, attrs); mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mPaint.setColor(getResources().getColor(R.color.dash_line)); mPaint.setStrokeWidth(3); mPaint.setPathEffect(new DashPathEffect(new float[] {5, 5}, 0)); } @Override protected void onDraw(Canvas canvas) { int centerY = getHeight() / 2; canvas.drawLine(0, centerY, getWidth(), centerY, mPaint); } }
代碼跑起來之后又發(fā)現(xiàn)虛線變成了直線,根本就沒有效果。有了上面使用ShapeDrawable的經(jīng)驗(yàn)之后,我們完全有理由猜測這是由于硬件加速引起的,到官方文檔硬件加速上可以看到確實(shí)是因?yàn)橛布铀賹?dǎo)致的。
(PS:其實(shí)真實(shí)情況是我先自定義View后才知道ShapeDrawable沒有虛線效果可能也是因?yàn)橛布铀僖鸬摹#?/p>
重新修改onDraw方法。重新運(yùn)行之后,虛線就正常出現(xiàn)了。
@Override protected void onDraw(Canvas canvas) { int centerY = getHeight() / 2; setLayerType(LAYER_TYPE_SOFTWARE, null); canvas.drawLine(0, centerY, getWidth(), centerY, mPaint); }
使用shapeDrawable和drawLine方法都能實(shí)現(xiàn)虛線的效果,但它們的缺點(diǎn)也很明顯,就是不支持硬件加速。上面的代碼因?yàn)楹唵?,所以不會引起卡頓的問題,但是如果你的自定義View很復(fù)雜,比如說用戶在畫矩形框的時(shí)候,如果用戶拉出來的圖形是一個(gè)正方形,那我們就畫一條對角虛線來提醒用戶。這種情況下不支持硬件加速的弊端可能就會顯現(xiàn)出來了。好在我們還有其它方法來實(shí)現(xiàn)虛線的繪制。setPathEffect方法只是不支持直線而已,那我們就找找有沒有另外的方式來畫直線,drawPath就可以繪制各種路徑,當(dāng)然也可以幫我們繪制直線,雖然說有點(diǎn)大材小用了。
重新來看看代碼怎么寫。
public class DashLineView extends View { private Paint mPaint; private Path mPath; public DashLineView(Context context, AttributeSet attrs) { super(context, attrs); mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mPaint.setColor(getResources().getColor(R.color.dash_line)); // 需要加上這句,否則畫不出東西 mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeWidth(3); mPaint.setPathEffect(new DashPathEffect(new float[] {15, 5}, 0)); mPath = new Path(); } @Override protected void onDraw(Canvas canvas) { int centerY = getHeight() / 2; mPath.reset(); mPath.moveTo(0, centerY); mPath.lineTo(getWidth(), centerY); canvas.drawPath(mPath, mPaint); } }
把setLayerType(LAYER_TYPE_SOFTWARE, null);
這一句代碼去掉之后也還能畫出虛線,證明是支持硬件加速的。
至此,我們已經(jīng)完美的實(shí)現(xiàn)了虛線的繪制,但本篇文章還沒完呢!我們繪制出來的虛線是一個(gè)實(shí)心矩形,那如果我們要求這條是由實(shí)心圓形組成的呢?又或者是其它圖形組成的呢?這時(shí)候我們就可以用PathDashPathEffect來實(shí)現(xiàn)了,看清楚點(diǎn),是PathDashPathEffect而不是DashPathEffect!PathDashPathEffect允許我們添加一個(gè)路徑來定義虛線的樣式。我們把setPathEffect()
改一下,看看效果。
Path path = new Path(); path.addCircle(0, 0, 3, Path.Direction.CW); mPaint.setPathEffect(new PathDashPathEffect(path, 15, 0, PathDashPathEffect.Style.ROTATE));
其實(shí)圓形組成的虛線也挺好看的嘛。繪制虛線至此就講完了,但如果要我們給這條虛線加一些效果呢?比如說虛線由中間是完全不透明的,而兩邊則會慢慢變透明。是不是想打人了,又不是不能用,那么多要求干嘛!沒辦法,硬著頭皮來吧。Paint還有另外一個(gè)方法,setShader(Shader shader)
,Shader我們可以理解為著色器,它有一個(gè)子類是LinearGradient,利用它可以幫助我們實(shí)現(xiàn)線性變色??纯创a先。
為了讓效果突出一點(diǎn),把虛線的顏色調(diào)為黑色。
// 其它方法還是不變 @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); // 前四個(gè)參數(shù)沒啥好講的,就是起點(diǎn)和終點(diǎn)而已。 // color數(shù)組的意思是從透明 -> 黑 -> 黑 -> 透明。 // float數(shù)組與color數(shù)組對應(yīng): // 0 -> 0.3 (透明 -> 黑) // 0.3 - 0.7 (黑 -> 黑,即不變色) // 0.7 -> 1 (黑 -> 透明) mPaint.setShader(new LinearGradient(0, 0, getWidth(), 0, new int[] {Color.TRANSPARENT, Color.BLACK, Color.BLACK, Color.TRANSPARENT}, new float[] {0, 0.3f, 0.7f, 1f}, Shader.TileMode.CLAMP)); }
效果還是可以的嘛,當(dāng)然不是應(yīng)用在圖片上的這種場景。好了,這次是真的講完了。雖然畫虛線不難,但還是有一些值得注意的地方的(硬件加速),然后再細(xì)細(xì)玩一玩,雖然簡單,還是可以玩出一些花樣來的。
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對各位Android開發(fā)者們能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對創(chuàng)新互聯(lián)的支持。
分享題目:Android自定義View實(shí)現(xiàn)繪制虛線的方法詳解
當(dāng)前路徑:http://www.dlmjj.cn/article/iighii.html