2016-10-24 12 views
2

これは私の最初のStackoverflowに関する質問です。私はある点の周りに放射状の花の効果を描こうとしていて、RadialGradientとGradientDrawableを見つけました。しかしどちらも完全に解決策を提示していません。1つのRadialGradientのサイズ、位置、色を設定する方法、GradientDrawableでXferModeを設定する方法

Screenshot

新しいRadialGradientは、メモリのすべてのフレームごとに蓄積しかし:

//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);  

これは期待どおりの結果が得られます:ここでは

は、私は今、図面をやっている方法ですドット。後で明らかに問題になるのは誰か。そのクラスの唯一のパブリックなものはコンストラクタです。したがって、RadialGradientでできることは、新しいサイズ、位置、または色が必要になるたびに新しいものを作成することです。このようにしたいのは、ペイントオブジェクトに描画する描画オブジェクトにグラデーションを割り当てるためです。このオブジェクトを使用すると、setXferMode()を使用できます。

GradientDrawableを使用する別の方法では、サイズ、位置、および色を変更できるように、自分自身のインスタンスを1つだけ作成できますが、ペイントするために使用するPaintオブジェクトは非公開です。その上にXferModeを設定しないでください。あなたが1つ以上のドットを持っているならば、それらはお互いに塗りつぶすのではないので、必要です。それはカラーフィルタを持っていますが、カラーフィルタのように見えません。

私は新しいので、2つのリンクを投稿するだけで、2つの写真を投稿するのではなく、私がredditに書いたのと同じ質問にリンクします。 (と私はハハ、ここに来た理由はまだありません答え、)これが行われる必要がありますどのように

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

、私は一つのクラスや他の必要な知っています。 RadialGradientは、異なるサイズ、位置、または色が必要なときに新しいものを作成する必要がなければ、完璧です。 GradientDrawableは1つのインスタンスしか持つことができないので同様に優れていますが、使用するペイントにXferModeを設定できる必要があります。別の授業はありますか、あるいは私はこれらの2つの間に何かを見逃していますか?

ありがとうございます!

答えて

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を使用して設定されます。カラーフィルタはグレースケールビットマップをフィルタの色に合わせてシェーディングします。それ以上のメモリリークはありません。

RadialGradientのビットマップをレンダリングするとRadialGradientを使用して円を描画するのに時間がかかりました。 30サークルでは、ギャラクシーS5はフレームドローあたり15〜20ミリ秒、ビットマップは約30〜35ミリ秒かかる。それはもう少し仕事と調整をしてもうまくいくはずです。

関連する問題