2015-08-26 43 views
7

Renk # 1'den renk # 2'ye geçiş nasıl canlandırılır?Degrade nasıl animasyon yapılır?

enter image description here

benzer bir şey bunu googling iken (yeşil ile başlayan ve kırmızı ile biten böylece, bu finit edilecek animasyon)

cevap

22

birimi için sağlık-bar olarak kullanmayı planlıyorum, ben Android için yapmanın 2 yolu bulundu: use ShaderFactory veya new Shader(new LinearGradient()) kullanarak View genişler. Her iki cevap da aynı - new Shader() her View.onDraw(Canvas canvas) yönteminin çağrısını çağırır. Bu tür animasyonlu geçişlerin sayısı ~ 3'ten daha fazla ise, gerçekten pahalı.

Başka bir şekilde yaptım. Önceden ayarlanmış bir LinearGradient kullanarak her onDraw() numaralı telefonu arayarak kaçındım. Yani benziyor şekli de budur (gif, böylece animasyon çürümüş):

enter image description here

hüner View.getWidth() daha colorsCount kat daha büyük olan LinearGradient yaratmaktır. Bundan sonra, canvas.translate(), gradyanı çizerken, rengini değiştirmek için no'lu telefon numarasının onDraw() numarasından hiçbirini kullanamazsınız.

Degrade oluşturmak için geçerli genişliğe ve yüksekliğe ihtiyacınız vardır. onSizeChanged()'da yaptım. Ayrıca burada Shader'u da ayarlıyorum.

@Override 
protected void onSizeChanged(int w, int h, int oldw, int oldh) { 
    super.onSizeChanged(w, h, oldw, oldh); 

    width = getWidth(); 
    height = getHeight(); 

    LinearGradient gradient = new LinearGradient(
      0, height/2, width * colors.length - 1, height/2, 
      colors, null, Shader.TileMode.REPEAT); 
    fillPaint.setShader(gradient); 

    shapePath = getParallelogrammPath(width, height, sidesGap); 
    shapeBorderPath = getParallelogrammPath(width, height, sidesGap); 
} 

Yolları paralelkenar görünümleri nedeniyle kullanıyorum, istediğiniz her şeyi kullanabilirsiniz. çizim uygularken, 2 şeyleri fark olmalıdır:

@Override 
protected void onDraw(Canvas canvas) { 
    canvas.save(); 
    canvas.translate(-gradientOffset, 0); 
    shapePath.offset(gradientOffset, 0f, tempPath); 
    canvas.drawPath(tempPath, fillPaint); 
    canvas.restore(); 

    canvas.drawPath(shapeBorderPath, borderPaint); 

    super.onDraw(canvas); // my View is FrameLayout, so need to call it after 
} 

Ayrıca canvas.save() & canvas.restore() kullanmalıdır: Eğer ofset ve offset() sizin dolum şekli akım üzerinde translate() bütün canvas gerekir. Tuvalin iç matrisini biriktirecek ve buna karşılık olarak geri yükleyecektir.

Yapmanız gereken son şey, gradientOffset'u canlandırmaktır. ObjectAnimator (Property Animation) gibi istediğiniz her şeyi kullanabilirsiniz. TimeAnimator kullanıyorum, çünkü updateTick kontrolünü ve doğrudan ofsetini başlatmam gerekiyordu. İşte benim gerçekleşme (biraz zor ve sert) 'dir:

static public final int LIFETIME_DEAFULT = 2300; 
private long lifetime = LIFETIME_DEAFULT, updateTickMs = 25, timeElapsed = 0; 
private long accumulatorMs = 0; 
private float gradientOffset = 0f; 

public void startGradientAnimation() { 
    stopGradientAnimation(); 
    resolveTimeElapsed(); 

    final float gradientOffsetCoef = (float) (updateTickMs)/lifetime; 
    final int colorsCount = this.colors.length - 1; 
    gradientAnimation.setTimeListener(new TimeAnimator.TimeListener() { 
     @Override 
     public void onTimeUpdate(TimeAnimator animation, long totalTime, long deltaTime) { 
      final long gradientWidth = width * colorsCount; 
      if (totalTime > (lifetime - timeElapsed)) { 
       animation.cancel(); 
       gradientOffset = gradientWidth; 
       invalidate(); 
      } else { 
       accumulatorMs += deltaTime; 

       final long gradientOffsetsCount = accumulatorMs/updateTickMs; 
       gradientOffset += (gradientOffsetsCount * gradientWidth) * gradientOffsetCoef; 
       accumulatorMs %= updateTickMs; 

       boolean gradientOffsetChanged = (gradientOffsetsCount > 0) ? true : false; 
       if (gradientOffsetChanged) { 
        invalidate(); 
       } 
      } 
     } 
    }); 

    gradientAnimation.start(); 
} 

tam View kodu anlamıyorum here

+0

bulabilirsiniz ... Eğer soru soruldu ve aynı zamanda bunu yanıtladı aynı gün? Bu asla bir soru değildi. –

+4

@ Chris-Jr, Çok aradım ve istediğim bir cevap bulamadım. Bu yüzden bir çeşit araştırma yaptım ve sonunda anladım. Sonra düşündüm de "hm, belki başka birileri bunu gelecekte arayacak ve ben de onunla yapışacak mıyım?" - Ben de cevabı soruyla yarattım. Ayrıca, bunu yapmak için yerleşik bir özellik var. 'Soru Sor' seçeneğini tıklatmaya çalışın. Bir kontrol var 'Kendi sorunuzu cevaplayın - bilginizi paylaşın, Soru-Cevap tarzı ' – Nexen

+0

Ah, tamam, size zamanlama tarafından kafam karıştı. Bunun için teşekkürler ve çözümünüzü paylaştığınız için teşekkürler. –

İlgili konular