2016-10-24 59 views
2

這是我在Stackoverflow上的第一個問題,所以對我來說很簡單。我試圖圍繞一個點繪製徑向布盧姆效果,並找到了RadialGradient以及GradientDrawable。然而,這兩者都不能完全解決。如何設置一個RadialGradient的大小,位置和顏色,或在GradientDrawable上設置XferMode

這裏是我正在做的圖紙現在:

//global 
PorterDuffXfermode xferMode = new PorterDuffXfermode(PorterDuff.Mode.ADD); 
Paint mainP = new Paint(); 
Paint whiteP = new Paint(); 
whiteP.setColor(Color.WHITE); 
RadialGradient gradient; 

// in a drawing method with a canvas 
gradient = new RadialGradient((int) x, (int) y, tempRadius, mainP.getColor(), 
    0x00000000, Shader.TileMode.CL 
mainP.setShader(gradient); 
mainP.setXfermode(xferMode); 

canvas.drawCircle((int) x, (int) y, tempRadius, mainP); 

gradient = new RadialGradient((int) x, (int) y, tempRadius/2, whiteP.getColor(), 
     0x00000000, Shader.TileMode.CLAMP); 
whiteP.setXfermode(xferMode); 
whiteP.setShader(gradient); 

canvas.drawCircle((int) x, (int) y, tempRadius/2, whiteP);  

這將使預期的結果:

Screenshot

但是新的RadialGradient在內存中每每幀積聚點。顯然以後會成爲問題。該類中唯一的公共事物是構造函數,因此您可以使用RadialGradient完成的每一次都需要創建一個新的大小,位置或顏色。我想這樣做的原因是因爲您將漸變分配給將要繪製的Paint對象,這允許您使用它的setXferMode()。

另一種方式,使用GradientDrawable,可以讓你創建自己的一個實例,所以你可以改變大小,位置和顏色,但是它用來繪製自己的Paint對象是私人的,所以你可以不要在其上設置XferMode。這是必要的,所以如果你有多個點,他們不只是彼此畫。它有一個colorfilter,但它看起來不像colorfilter對目的地的擔心,只有指定的顏色和來源。

由於我是新的,我只能發佈兩個環節,而不是僅僅張貼兩張圖片,我會鏈接到同一個問題,我在Reddit上寫了擁有所有背景圖片。 (沒有解答,這就是爲什麼我來到這裏,哈哈)

https://www.reddit.com/r/learnandroid/comments/590uce/having_a_shader_issue_using_radialgradient_and/

那麼,如何來完成的,我知道我需要一個類或其他。從我所知道的情況來看,如果我不需要在每次需要不同的尺寸,位置或顏色時都創建新的RadialGradient,那麼RadialGradient就是完美的。 GradientDrawable會同樣好,因爲你可以只有一個實例,但我需要能夠在它使用的paint上設置XferMode。還有另一個班,還是我錯過了其中的兩個?

謝謝!

回答

0

所以,雖然我找到了解決方案,但它仍然導致更多的問題。我找到的解決方案部分是here。它唯一缺少的是能夠改變預分配的RadialGradient位圖的顏色。所以,我想出了這個:

// Global 
int tempRadius; 
Paint p = new Paint(); 
RadialGradient gradient;  
Bitmap circleBitmap = Bitmap.createBitmap((int) (tempRadius * 2.0f), (int) (tempRadius * 2.0f), 
Bitmap.Config.ARGB_8888); 
Canvas tempCanvas = new Canvas(circleBitmap); 
Rect gradBMPRect = new Rect(0,0,200,200); 
Rect destRect = new Rect(); 
int[] hsv = {0,1,1}; 
PorterDuffColorFilter[] myColors = new PorterDuffColorFilter[360]; 
PorterDuffXfermode xferMode = new PorterDuffXfermode(PorterDuff.Mode.ADD); 


// Initialize 
gradient = new RadialGradient(tempRadius, tempRadius, tempRadius, Color.WHITE, 0x00000000, Shader.TileMode.CLAMP); 
circleBitmap = Bitmap.createBitmap((int) (100 * 2.0f), (int) (100 * 2.0f), 
Bitmap.Config.ARGB_8888); 
tempCanvas = new Canvas(circleBitmap); 
for(int i = 0; i < 360; i++){ 
    hsv[0] = i; 
    myColors[i] = new PorterDuffColorFilter(Color.HSVtoColor(hsv), PorterDuff.Mode.MULTIPLY) 
} 

// update/draw 
p.setDither(true); 
p.setShader(gradient); 
tempCanvas.drawCircle(100, 100, 100, p); 
p.setXfermode(xferMode); 


if(p.getColor() != mainP.getColor()) { 
p.setColorFilter(myColors[hue]); 
p.setColor(mainP.getColor()); 

destRect.set((int)x-tempRadius,(int)y-tempRadius,(int)x+tempRadius,(int)y+tempRadius); 
canvas.drawBitmap(circleBitmap,gradBMPRect,destRect,p); 

p.setColorFilter(null); 
destRect.set((int)x-(tempRadius/2),(int)y-(tempRadius/2),(int)x+(tempRadius/2),(int)y+(tempRadius/2)); 
canvas.drawBitmap(circleBitmap,gradBMPRect,destRect,p); 

與此有關的RadialGradient用於創建一個greyscaled位圖,然後360個PorterDuffColorFilters一個調色板使用HSVtoColor而成。所有360都將其模式設置爲相乘。繪製這些用於繪製位圖的繪圖時,使用由其色調指定的ColorFilter。 colorfilter將灰度位圖遮蔽爲濾鏡的顏色。並沒有更多的內存泄漏:)

這花了較長的時間來呈現RadialGradient與使用RadialGradient呈現圓的位圖。有30個圈子,我的銀河S5每幀畫15-20ms,而位圖花了大約30-35ms。它可能可以得到解決,但多一點工作和調整。

相關問題