2016-11-25 5 views
0

Comme vous le savez peut-être, il n'est pas possible de dessiner un dégradé radial ovale à l'aide de l'API Android habituelle.Gradient ovale lourd de mémoire

C'est ce que je veux atteindre:

Expected effect

Je mis en œuvre cette solution: tirer un dégradé radial régulier sur une image bitmap carré puis ce bitmap sera pas étirée par la vue elle-même (idée trouvé ici: https://stackoverflow.com/a/3543899/649910)

Cela fonctionne très bien, mais cette solution prend beaucoup de mémoire, en raison de l'utilisation de BitmapDrawable (voir les détails de mise en œuvre ci-dessous).

Toutes les idées sur la façon d'éviter l'utilisation d'un tel bitmap sont les bienvenues!

Ce mon code:

public class OvalGradientView extends ImageView { 

    private Drawable defaultBackgroundDrawable; 

    public OvalGradientView(Context context) { 
     super(context); 
     init(); 
    } 

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

    public OvalGradientView(Context context, AttributeSet attrs, int defStyleAttr, Paint paint) { 
     super(context, attrs, defStyleAttr); 
     init(); 
    } 

    private void init() { 
     setScaleType(ScaleType.FIT_XY); 
     defaultBackgroundDrawable = getResources().getDrawable(R.drawable.default_background); 
    } 

    @Override 
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 
     super.onLayout(changed, left, top, right, bottom); 
     int width = getWidth(); 
     int height = getHeight(); 
     Rect currentBounds = defaultBackgroundDrawable.getBounds(); 
     // check if we already have bitmap for these bounds 
     if (currentBounds.right == width && currentBounds.bottom == height) { 
      return; 
     } 
     // draw the drawable on square bitmap, it will be then stretched if needed to rectangular shape 
     // as the view gets more rectangular 
     defaultBackgroundDrawable.setBounds(0, 0, width, width); 
     Bitmap defaultBackgroundBitmap = Bitmap.createBitmap(width, width, Bitmap.Config.ARGB_8888); 
     Canvas canvas = new Canvas(defaultBackgroundBitmap); 
     defaultBackgroundDrawable.draw(canvas); 
     setImageBitmap(defaultBackgroundBitmap); 
    } 
} 

Et c'est le XML drawable - default_background

<shape xmlns:android="http://schemas.android.com/apk/res/android"> 
    <gradient 
     android:startColor="#ffffff" 
     android:endColor="#ff6600" 
     android:gradientRadius="50%p" 
     android:type="radial" /> 
</shape 

Répondre

0

J'ai fini avec cette mise en œuvre:

public class MyBackgroundView extends ImageView { 

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

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

    public MyBackgroundView(Context context, AttributeSet attrs, int defStyleAttr) { 
     super(context, attrs, defStyleAttr); 
    } 

    { 
     setBackgroundResource(R.drawable.my_background); 
     setScaleType(ScaleType.FIT_XY); 
    } 

    @Override 
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 
     super.onLayout(changed, left, top, right, bottom); 

     if (!changed) { 
      return; 
     } 

     int width = right - left; 
     int height = bottom - top; 
     float aspectRatio = (float) width/height; 
     if (aspectRatio > 1f) { 
      setScaleX(aspectRatio); 
     } else { 
      setScaleY(1/aspectRatio); 
     } 
    } 
} 

où my_background est :

<shape xmlns:android="http://schemas.android.com/apk/res/android"> 
    <gradient 
     android:startColor="@color/my_background_start_color" 
     android:endColor="@color/my_background_end_color" 
     android:gradientRadius="@fraction/my_background_gradient_radius_percent" 
     android:type="radial" /> 
</shape> 

La largeur et la hauteur de cette vue sont toutes les deux égales.

1

Je ne faire confiance à mon propre capacité à créer des bitmaps comme ça, surtout si elles sont en plein écran . Pourquoi ne pas appliquer la forme xml en tant qu'arrière-plan à la vue du conteneur en XML? Il étendra aux proportions de la vue si la largeur et la hauteur sont match_parent

public class OvalGradientView extends ImageView { 
    public OvalGradientView(Context context, AttributeSet attrs) { 
     super(context, attrs); 

     LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     inflater.inflate(R.layout.my_sexy_gradient, this, true); 
    } 
} 

my_sexy_gradient.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 
      android:layout_width="match_parent" 
      android:layout_height="match_parent" 
      android:background="@drawable/default_background"/>