2011-07-05 17 views
16

Znalazłem, jak change the opacity of a View, ale muszę faktycznie przyciemnić View. Moim najlepszym pomysłem jest umieszczenie na nim przezroczystego czarnego prostokąta, a następnie powolne zwiększanie krycia prostokąta.Programowo ciemnieje widok Android

Czy znasz lepszy sposób na zrobienie tego?

public class Page07AnimationView extends ParentPageAnimationView { 
    private final String TAG = this.getClass().getSimpleName(); 
    private ImageView overlay; 
    private int mAlpha = 0; 

    public Page07AnimationView(Context context) { 
     super(context); 
    } 

    public Page07AnimationView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 

    protected void init() 
    { 
     overlay = new ImageView(mContext); 
     overlay.setImageResource(R.drawable.black_background); 
     overlay.setAlpha(0); 
     overlay.setWillNotDraw(false); 
     // make the PageAniSurfaceView focusable so it can handle events 
     setFocusable(true); 
    } 

    protected void draw_bitmaps(Canvas canvas) 
    { 
     overlay.draw(canvas); 
     update_bitmaps(); 
     invalidate(); 
    } 

    public void update_bitmaps() 
    { 
     if(mAlpha < 250) 
     { 
      mAlpha += 10; 
      overlay.setAlpha(mAlpha); 
     } 
    } 
} 

Powyższy kod nie spełnia moich oczekiwań. Page07AnimationView został dodany do FrameLayout nad widokiem, który muszę przyciemnić. R.drawable.black_background wskazuje na czarny obraz png o wymiarach 787 pikseli x 492 pikseli.

Dodałem overlay.setWillNotDraw(false);, ale to nie pomogło. Zmieniłem pierwszą setAlpha(0) na setAlpha(255), ale to nie pomogło. Usunąłem wszystkie połączenia setAlpha(), ale to nie pomogło.

Ta podstawowa technika dodawania obiektu PageNNAnimationView służy do rysowania Bitmaps, ale nie do rysowania ImageView overlay. (Użyłbym Bitmaps, ale nie wydaje się, że składnik alfa.)

Edit2: jest to dominująca w klasie powyżej:

public class ParentPageAnimationView extends View { 
    private final String TAG = this.getClass().getSimpleName(); 
    protected Context mContext; 

    public ParentPageAnimationView(Context context) { 
     super(context); 
     mContext = context; 
     init(); 
    } 

    public ParentPageAnimationView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     mContext = context; 
     init(); 
    } 

    protected void init() 
    { 
    } 

    protected void draw_bitmaps(Canvas canvas) 
    { 
     // will be overridden by child classes 
    } 

    @Override 
    protected void onDraw(Canvas canvas) { 
     if(this.getVisibility() == View.VISIBLE) 
     { 
      if(canvas != null) 
      { 
       draw_bitmaps(canvas); 
      } 
     } 
    } 

    public void update_bitmaps() 
    { 
     // will be overridden by child classes 
    } 

    public void elementStarted(PageElement _pageElement) { 
     // Nothing in parent class 
    } 

    public void elementFinished(PageElement mElement) { 
     // Nothing in parent class 
    } 
} 
+0

Ustaliliśmy, że draw_bitmaps i update_bitmaps są nazywane wielokrotnie. –

Odpowiedz

10

wolałbym zrobić to w odwrotnym kierunku - umieść ciemny prostokąt za widokiem i ustaw nieprzezroczystość widoku. Spowoduje to zapisanie obrazu w prostokącie, gdy widok jest w 100% nieprzejrzysty.

+0

to jest fajny pomysł! Sądzę, że jestem zmuszony robić coś "ponad" Widzeniem, z racji tego, jak mam układane moje układy. Ale posiadanie układu animacji * za * nimi może rozwiązać inny problem; dzięki! –

+0

Po uruchomieniu animacji za półprzezroczystym widokiem może zająć odświeżenie całego ekranu. Włącz "Pokazuj aktualizacje ekranu" w DevTools w symulatorze i zobacz, co zostało przemalowane. – JBM

1

można spróbować użyć animacji Alpha jak to (być może na prostokącie):

Animation animation = new AlphaAnimation(0.0f, 1.0f); 
    animation.setDuration(350); 

To spowodowałoby prostokąt stopniowo stają się nieprzezroczyste ponad 350 sekund ...

+2

Myślę, że kiedy powiedział * ładniej * miał na myśli "właściwsze", a nie "przytłaczające" – JBM

0

Należy sprawdzić iPaulPro użytkownika odpowiedź w this question. Będziesz musiał rozszerzyć ImageView i zastąpić metodę onDraw().

W zależności od tego, co zamierzasz zrobić, odpowiedź Alexandru Cristescu jest również ważna, ale powinieneś wykonać zadzwonić pod numer setFillAter(true), aby animacja pozostała po zakończeniu.

2

Tak właśnie to zrobiłem. Kluczem było użycie farby z zestawem alfa do tego, co chciałem.

public class Page07AnimationView extends ParentPageAnimationView { 
    private final String TAG = this.getClass().getSimpleName(); 
    private Bitmap bitmap; 
    private BitmapDrawable drawable; 
    private ImageView overlay; 
    private int which = -1; 
    private long last_time; 
    private Page07State state; 
    private int mAlpha; 
    private int maxAlpha; 
    private Paint mPaint; 
    private int _alpha_step; 
    private int minAlpha; 

    public enum Page07State { 
     WAITING, DARKENING, DARKENED 
    } 

    public Page07AnimationView(Context context) { 
     super(context); 
    } 

    public Page07AnimationView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 

    protected void init() 
    { 
     minAlpha = 0; 
     mAlpha = minAlpha; 
     _alpha_step = 5; 
     maxAlpha = 255; 
     mPaint = new Paint(); 
     mPaint.setAlpha(minAlpha); 
     state = Page07State.WAITING; 
     overlay = new ImageView(mContext); 
     overlay.setImageResource(R.drawable.black_background); 
     drawable = (BitmapDrawable) overlay.getDrawable(); 
     bitmap = drawable.getBitmap(); 
     last_time = 0; 
    } 

    protected void draw_bitmaps(Canvas canvas) 
    { 
     if(state != Page07State.WAITING) 
     { 
      DebugLog.d(TAG, "drawing " + Integer.toString(which)); 
      canvas.drawBitmap(bitmap, 0, 0, mPaint); 
     } 
     update_bitmaps(); 
     invalidate(); 
    } 

    public void update_bitmaps() 
    { 
     if(state == Page07State.DARKENING) 
     { 
      if(mAlpha < maxAlpha) 
      { 
       if(System.currentTimeMillis() > last_time + 12) 
       { 
        last_time = System.currentTimeMillis(); 
        mAlpha += _alpha_step; 
        mPaint.setAlpha(mAlpha); 
       } 
      } 
      else 
      { 
       state = Page07State.DARKENED; 
      } 
     } 
    } 

    public void runAnimation() 
    { 
     state = Page07State.DARKENING; 
    } 
} 
28

W przypadku ImageView, oto jeden sposób, aby to osiągnąć:

imageView.setColorFilter(Color.rgb(123, 123, 123), android.graphics.PorterDuff.Mode.MULTIPLY); 
+0

, czy używa to mniej lub więcej zasobów niż ustawienie '.setAlpha ((zmiennoprzecinkowe) 1.0)' (dla sdk 11 i wyżej) lub '. setAlpha (100) '(dla sdk 11 i poniżej). Powód, dla którego pytam, polega na tym, że ustawiam nieprzezroczystość, aby to osiągnąć, i czy mogę to tak nazwać, a jeśli jest bardziej kompatybilny, byłoby świetnie. –

+0

@AaronRussell Myślę, że jeśli używasz setAlpha, to lepiej, ponieważ może być zoptymalizowany GPU. oczywiście, mógłbym się mylić. Najlepiej jest zawsze korzystać z najnowszych funkcji API. –

6

chciałbym zrobić coś takiego:

view.getBackground().setColorFilter(color, PorterDuff.Mode.DARKEN); 

używać czarnego koloru z pewnym alfa jak 0x7f000000 dla typowe zaciemnienie.

Jest to bardziej zwięzłe i można również przyciemnić obiekt View z animacją lub wydarzeniem przewijania. Wystarczy ustawić Color.argb(alpha, 0, 0, 0) jako kolor i animować alpha lub zmienić go na podstawie przesunięcia przesunięcia.

2

Dodawanie do odpowiedzi android dewelopera:

imageView.setColorFilter(Color.rgb(123, 123, 123), android.graphics.PorterDuff.Mode.MULTIPLY); 

można setColorFilter w każdym razie tak:

GradientDrawable gd = (GradientDrawable) textView.getBackground(); 
gd.setColor(color); //you can also set BG color to a textview like this 
gd.setColorFilter(Color.rgb(123, 123, 123), android.graphics.PorterDuff.Mode.MULTIPLY);