2011-07-05 13 views
16

Encontré cómo change the opacity of a View, pero realmente necesito oscurecer un View. Mi mejor idea es colocar un rectángulo negro transparente sobre él y luego aumentar lentamente la opacidad del rectángulo.oscurecer programáticamente a Ver android

¿Conoces una manera más agradable de hacerlo?

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

El código anterior no está haciendo lo que esperaba. Page07AnimationView se agrega a un FrameLayout sobre la vista que necesito oscurecer. R.drawable.black_background apunta a una imagen png negra de 787px x 492px.

He añadido overlay.setWillNotDraw(false); pero no sirvió. Cambié el primer setAlpha(0) a setAlpha(255) pero eso no ayudó. Quité las llamadas setAlpha() por completo, pero no sirvió de nada.

Esta técnica básica de agregar un PageNNAnimationView ha estado trabajando para dibujar Bitmaps, pero no para dibujar ImageView overlay. (Yo utilizo Bitmaps, pero no parecen tener un componente alfa.)

Edit2: este es el padre de la clase anterior:

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

He confirmado que draw_bitmaps y update_bitmaps están siendo llamados en repetidas ocasiones. –

Respuesta

10

prefiero hacerlo de manera opuesta - Pon un rectángulo oscuro detrás de la vista y establece la opacidad de la vista. Esto ahorra pintar el rectángulo cuando la vista es 100% opaca.

+0

¡esta es una buena idea! Sin embargo, creo que estoy obligado a hacer algo "sobre" la Vista, en virtud de cómo tengo mis diseños establecidos. Pero tener un diseño de animación * detrás de ellos podría resolver otro problema; ¡Gracias! –

+0

Al ejecutar una animación detrás de una vista translúcida, puede desencadenar el repintado de toda la pantalla. Habilite "Mostrar actualizaciones de pantalla" en DevTools en el simulador y vea qué se repinta. – JBM

1

se podría tratar de usar la animación Alfa como esto (tal vez en el rectángulo):

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

Eso haría que el rectángulo para convertirse poco a poco opaca más de 350 segundos ...

+2

Creo que cuando dijo * mejor * quiso decir "más apropiado", no "más lindo" – JBM

0

Debe comprobar iPaulPro de respuesta en this question. Tendrá que extender ImageView y anular el método onDraw().

Dependiendo de lo que se va a hacer, la respuesta de Alexandru Cristescu también es válida pero debe llamada setFillAter(true) para la animación a persistir después de terminado.

2

Así es como terminé haciéndolo. La clave era usar una pintura con su conjunto alfa para lo que quisiera.

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

En caso de una ImageView, aquí es una manera de lograrlo:

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

usa más o menos recursos y luego establece '.setAlpha ((float) 1.0)' (para sdk 11 y arriba) o '. setAlpha (100) '(para sdk 11 y menos). La razón por la que pregunto es porque estoy configurando la opacidad para lograr esto, y si puedo llamarlo y si es más compatible, sería genial. –

+0

@ AaronRussell, creo que si usas setAlpha, es mejor, ya que podría estar optimizado para GPU. por supuesto, podría estar equivocado en esto. Lo mejor debería ser usar siempre las funciones API más nuevas. –

6

me gustaría hacer algo como esto:

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

Uso de color negro con un poco de alfa como 0x7f000000 de un oscurecimiento típico.

Es más conciso y también puede oscurecer el View con un evento de animación o desplazamiento, por ejemplo. Simplemente configure Color.argb(alpha, 0, 0, 0) como el color y anime alpha, o cámbielo según el desplazamiento de desplazamiento.

2

adición a la respuesta del desarrollador android:

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

se puede setColorFilter en cualquier caso como éste:

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); 
Cuestiones relacionadas