2011-01-18 38 views
9

Tôi cần vẽ nền của Canvas một màu với tô bóng/tô dốc, nhưng mỗi lần gọi trênDraw tôi muốn có khả năng thay đổi màu.Làm thế nào để vẽ một màu gradient trong Android trên Canvas với màu sắc thay đổi?

Tôi gặp sự cố khi thực hiện việc này mà không cần tạo đối tượng mới mỗi cuộc gọi onDraw. Ai có ý tưởng gì không? Nếu tôi sử dụng drawPaint() và thiết lập một shader mới() cho sơn của tôi, sau đó tôi đã tạo ra một đối tượng shader mới và nếu tôi tạo một GradientDrawable mới() tôi có là tốt. Tôi muốn tránh GC. Tôi nghĩ rằng tôi có thể tái sử dụng một đối tượng GradientDrawable() và gọi phương thức .setColor(), nhưng điều này chỉ đặt lại bất kỳ dữ liệu gradient nào liên quan đến nó và vẽ màu có thể drawable như màu đồng nhất đó.

Bất kỳ ai?

Trả lời

5

Thật không may là bạn phải tạo LinearGradient mới mọi lúc. Lưu ý rằng bạn không cần phải sử dụng một GradientDrawable, bạn có thể vẽ hình dạng cho mình với một Paint mà trên đó bạn thiết lập các shader.

+0

Cảm ơn Romain, bạn có thể chia sẻ kiến ​​thức chuyên môn của mình trong nhận xét của tôi về cắm trại dưới đây không? Tôi tự hỏi phương thức .draw() nào hiệu quả nhất sẽ là vẽ hai lớp cần thiết để tạo hiệu ứng này hoặc nếu LayerDrawable chính xác là cái tôi cần. – Greg

+0

@Romain Guy Tôi đã cố gắng sử dụng SweepGradient để đạt được hiệu ứng gradient hình nón.Nhưng có vẻ như nó chỉ hoạt động với hai màu. Nếu tôi sử dụng một mảng bốn màu thì ** SweepGradient ** dường như không hoạt động như mong đợi. Tôi đã thử kết hợp khác nhau của ** vị trí ** giá trị và cũng đã cố gắng cài đặt vị trí như ** NULL ** nhưng hầu hết tôi chỉ nhận được hai màu hoặc một gradient mà không phải là hình nón. Bất kì sự trợ giúp nào đều được đánh giá cao. –

0

Tôi nghĩ rằng những gì bạn muốn làm là điều này. Tạo một LayerDrawable và sau đó chèn hai Drawables vào nó. Bản vẽ đầu tiên bạn chèn phải có màu được đặt thành màu bạn muốn nền của bạn và màu thứ hai sẽ là một Gradient được thiết lập thành màu đen và chuyển từ alpha 0 sang alpha 255.

Để biết thêm thông tin, xem: http://developer.android.com/guide/topics/resources/drawable-resource.html#LayerList

+0

campnic - cảm ơn đây là loại của những gì tôi đã đi cho khi tôi nghĩ để gọi canvas.drawARGB() với alpha xFF và sau đó một sơn w/shader hoặc gradient với alpha thấp hơn trên đầu trang của nó. Tôi chỉ lo lắng về hiệu quả. Tôi muốn tránh vẽ toàn bộ khung hình bằng hai lớp và muốn biết liệu có xây dựng trong xây dựng để làm điều này trong một lần không. Liệu LayerDrawable đạt được điều này hay nó thực sự làm lớp vẽ tuần tự theo lớp? – Greg

+0

Tôi đã làm một chút đào, và những gì tôi thấy cho thấy rằng bạn sẽ kết thúc vẽ hai lớp đầy đủ trên toàn bộ màn hình. Mã cho LayerDrawable.draw chỉ lặp lại trên con Drawables theo thứ tự chỉ số giảm dần. Tôi nghĩ rằng hiệu suất của LayerDRawable có thể không phải là những gì bạn muốn sử dụng. Romain có nhiều kinh nghiệm hơn với công cụ này, vì vậy anh ấy có thể cung cấp cho bạn một ý tưởng tốt hơn :) –

+0

Tôi thực sự đánh giá cao bạn đang tìm kiếm điều này - đây là những gì tôi cũng tìm thấy và nghi ngờ khi xem qua tài liệu. Tôi sẽ phải suy nghĩ về một cái gì đó sáng tạo cho một nền tảng tìm kiếm năng động tốt đẹp nếu không có giải pháp tích hợp. – Greg

0

Câu hỏi này vẫn còn hiệu lực gần như vào giữa năm 2017. Tôi muốn tạo chuyển đổi suôn sẻ cho các thay đổi màu cho chế độ xem tùy chỉnh của mình. Tôi đã sử dụng shaders với LinearGradients.

Ý định của tôi là làm cho quá trình chuyển đổi suôn sẻ betweeen trạng thái vô hiệu hóa và bị tắt trong chế độ xem của tôi.

Trường hợp của tôi thậm chí còn phức tạp hơn do xây dựng và mục đích của chế độ xem. Đó là một thanh trượt. Vì vậy, quan điểm của tôi bao gồm gần 2 lớp giống hệt nhau được vẽ trên đầu trang của lớp thứ hai sử dụng canvas. Yếu tố thứ ba là một con trỏ.

Cả hai lớp đều sử dụng LinearGradients, con trỏ sử dụng một màu duy nhất.

Tổng hợp tất cả tôi phải làm một sự chuyển tiếp giữa 5 màu sắc cùng một lúc:

  • bắt đầu và màu cuối cho đáy lớp - một Gradient Linear,
  • bắt đầu và kết thúc màu cho lớp trên cùng - Gradient Linear thứ hai ,
  • màu con trỏ - màu bình thường;

Giải pháp cho điều này là có 5 Trình tạo giá trị riêng biệt. Điều quan trọng nhất là sử dụng ValueAnimator.ofArgb():

private ValueAnimator frontStartColorAnimator; 
private ValueAnimator frontEndColorAnimator; 
private ValueAnimator bottomStartColorAnimator; 
private ValueAnimator bottomEndColorAnimator; 
private ValueAnimator pointerColorAnimator; 
private AnimatorSet colorsAnimatorSet; 

... 

frontStartColorAnimator = ValueAnimator.ofArgb(frontLayerStartColor, frontLayerDisabledStartColor); 
frontStartColorAnimator.setDuration(animationDuration); 
frontStartColorAnimator.setInterpolator(new LinearInterpolator()); 
frontStartColorAnimator.addUpdateListener(animation 
      -> shaderFrontLayerStartColor = (int) animation.getAnimatedValue()); 

frontEndColorAnimator = ValueAnimator.ofArgb(frontLayerEndColor, frontLayerDisabledEndColor); 
frontEndColorAnimator.setDuration(animationDuration); 
frontEndColorAnimator.setInterpolator(new LinearInterpolator()); 
frontEndColorAnimator.addUpdateListener(animation -> { 
     shaderFrontLayerEndColor = (int) animation.getAnimatedValue(); 
     frontLayerPaint.setShader(new LinearGradient(0, 0, getWidth(), 0, shaderFrontLayerStartColor, 
       shaderFrontLayerEndColor, Shader.TileMode.CLAMP)); 
    }); 

bottomStartColorAnimator = ValueAnimator.ofArgb(bottomLayerStartColor, bottomLayerDisabledStartColor); 
bottomStartColorAnimator.setDuration(animationDuration); 
bottomStartColorAnimator.setInterpolator(new LinearInterpolator()); 
bottomStartColorAnimator.addUpdateListener(animation -> 
      shaderBottomLayerStartColor = (int) animation.getAnimatedValue()); 

bottomEndColorAnimator = ValueAnimator.ofArgb(bottomLayerEndColor, bottomLayerDisabledEndColor); 
bottomEndColorAnimator.setDuration(animationDuration); 
bottomEndColorAnimator.setInterpolator(new LinearInterpolator()); 
bottomEndColorAnimator.addUpdateListener(animation -> { 
     shaderBottomLayerEndColor = (int) animation.getAnimatedValue(); 
     backLayerPaint.setShader(new LinearGradient(0, 0, 0, getHeight(), shaderBottomLayerStartColor, 
       shaderBottomLayerEndColor, Shader.TileMode.CLAMP)); 
    }); 

pointerColorAnimator = ValueAnimator.ofArgb(pointerEnabledColor, pointerDisabledColor); 
pointerColorAnimator.setDuration(animationDuration); 
pointerColorAnimator.setInterpolator(new LinearInterpolator()); 
pointerColorAnimator.addUpdateListener(animation -> { 
     pointerColor = (int) animation.getAnimatedValue(); 
     pointerPaint.setColor(pointerColor); 
    }); 

colorsAnimatorSet = new AnimatorSet(); 
colorsAnimatorSet.playTogether(frontStartColorAnimator, frontEndColorAnimator, 
      bottomStartColorAnimator, bottomEndColorAnimator, pointerColorAnimator); 

... 

colorsAnimatorSet.start(); 

Tôi cũng lo ngại khi khởi về việc tạo một Gradient Linear mới trên mỗi lần cập nhật hình ảnh động nhưng sau đó tôi đưa ra GPU hồ sơ trên điện thoại với "Trên màn hình là thanh" . Mọi thứ đều ổn và chạy trong lề an toàn.

Các vấn đề liên quan