Quando você precisa mostrar imagens estáticas no seu app, use a classe Drawable
e as subclasses dela para desenhar formas e
de imagens de contêiner. Um Drawable
é uma abstração geral para
algo que possa ser desenhado. As várias subclasses ajudam com funções específicas
e você pode estendê-los para definir seus próprios objetos drawable
que se comportam de maneiras únicas.
Há duas maneiras de definir e instanciar um Drawable
, além de usar os construtores da classe:
- Inflar um recurso de imagem (arquivo de bitmap) salvo no projeto.
- Inflar um recurso XML que define as propriedades do drawable.
Observação: Você pode preferir usar um drawable vetorial, que define uma imagem com um conjunto de pontos, linhas e curvas, junto com as informações de cor associadas. Isso permite drawables vetoriais ser dimensionados para diferentes tamanhos sem perder a qualidade. Para mais informações, consulte Vector Visão geral dos drawables.
Criar drawables a partir de imagens de recursos
É possível adicionar gráficos ao seu app referenciando um arquivo de imagem do seu recursos do projeto. Os tipos de arquivo aceitos são PNG (preferencial), JPG (aceitável), e GIF (não recomendado). Ícones, logotipos e outros elementos gráficos do app, como os usados em jogos, são ideais para essa técnica.
Para usar um recurso de imagem, adicione o arquivo ao res/drawable/
do seu projeto. No projeto, faça referência à imagem
recurso do seu código ou layout XML. De qualquer forma, ele é chamado de
ID do recurso, que é o nome do arquivo sem a extensão do tipo de arquivo. Para
por exemplo, consulte my_image.png
como my_image
.
Observação: recursos de imagem colocados na
O diretório res/drawable/
pode ser otimizado automaticamente com
compactação de imagem sem perdas pela ferramenta aapt
durante o build
de desenvolvimento de software. Por exemplo, um PNG de cores verdadeiras que não exige mais de 256 cores.
podem ser convertidos para um PNG de 8 bits com uma paleta de cores. Isso resulta em uma imagem
com a mesma qualidade, mas que requerem menos memória. Como resultado, os binários de imagem
colocados nesse diretório podem mudar no tempo de build. Se você planeja ler um
imagem como bitstream para convertê-la em um bitmap, coloque suas imagens no
res/raw/
, onde a ferramenta aapt
não
modificá-los.
O snippet de código abaixo demonstra como criar uma ImageView
que usa
uma imagem criada a partir de um recurso drawable e o adiciona ao layout:
Kotlin
private lateinit var constraintLayout: ConstraintLayout override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // Instantiate an ImageView and define its properties val i = ImageView(this).apply { setImageResource(R.drawable.my_image) contentDescription = resources.getString(R.string.my_image_desc) // set the ImageView bounds to match the Drawable's dimensions adjustViewBounds = true layoutParams = ViewGroup.LayoutParams( ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT) } // Create a ConstraintLayout in which to add the ImageView constraintLayout = ConstraintLayout(this).apply { // Add the ImageView to the layout. addView(i) } // Set the layout as the content view. setContentView(constraintLayout) }
Java
ConstraintLayout constraintLayout; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Create a ConstraintLayout in which to add the ImageView constraintLayout = new ConstraintLayout(this); // Instantiate an ImageView and define its properties ImageView i = new ImageView(this); i.setImageResource(R.drawable.my_image); i.setContentDescription(getResources().getString(R.string.my_image_desc)); // set the ImageView bounds to match the Drawable's dimensions i.setAdjustViewBounds(true); i.setLayoutParams(new ViewGroup.LayoutParams( ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); // Add the ImageView to the layout and set the layout as the content view. constraintLayout.addView(i); setContentView(constraintLayout); }
Em outros casos, processe seu recurso de imagem como um objeto Drawable
, conforme mostrado abaixo.
exemplo:
Kotlin
val myImage: Drawable = ResourcesCompat.getDrawable(context.resources, R.drawable.my_image, null)
Java
Resources res = context.getResources(); Drawable myImage = ResourcesCompat.getDrawable(res, R.drawable.my_image, null);
Aviso:cada recurso exclusivo do seu projeto
pode manter apenas um estado, não importa quantos objetos diferentes você
instanciar para ele. Por exemplo, se você instanciar dois objetos Drawable
do mesmo recurso de imagem e
alterar uma propriedade (como o alfa) de um objeto, isso também afetará
com o outro. Ao lidar com várias instâncias de um recurso de imagem, em vez
de transformar diretamente o objeto Drawable
, execute uma
pré-adolescente
animação.
O snippet de XML abaixo mostra como adicionar um recurso drawable a um ImageView
no layout XML:
<ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/my_image" android:contentDescription="@string/my_image_desc" />
Para mais informações sobre o uso de recursos do projeto, consulte Recursos.
Observação:ao usar recursos de imagem como a origem dos drawables, Certifique-se de que as imagens tenham o tamanho apropriado para várias densidades de pixel. Se o estiverem incorretas, elas serão dimensionadas para caber, o que pode causar artefatos nos seus drawables. Para mais informações, consulte Suporte a diferentes densidades de pixel
Criar drawables a partir de recursos XML
Se houver um Drawable
que você gostaria de criar, que não depende inicialmente de variáveis definidas pelo seu
ou interação do usuário, definir Drawable
em XML é uma boa opção. Uniforme
se você espera que o Drawable
mude as propriedades durante a interação do usuário.
com seu aplicativo, considere definir o objeto em XML, já que é possível modificar as propriedades depois
o objeto foi instanciado.
Depois de definir o Drawable
em XML, salve o arquivo na
res/drawable/
do seu projeto. O exemplo a seguir mostra o XML que
define um
TransitionDrawable
recurso herdado de Drawable
:
<!-- res/drawable/expand_collapse.xml --> <transition xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/image_expand"/> <item android:drawable="@drawable/image_collapse"/> </transition>
Em seguida, recupere e instancie o objeto chamando
Resources#getDrawable()
e passando o ID do recurso do seu arquivo XML. Qualquer um
Subclasse Drawable
com suporte ao método inflate()
pode ser definido em XML e instanciado
pelo seu app.
Cada classe de drawable que oferece suporte à inflação de XML utiliza atributos XML específicos
que ajudam a definir as propriedades do objeto. O código a seguir instancia
TransitionDrawable
e o define como o conteúdo de um
Objeto ImageView
:
Kotlin
val transition= ResourcesCompat.getDrawable( context.resources, R.drawable.expand_collapse, null ) as TransitionDrawable val image: ImageView = findViewById(R.id.toggle_image) image.setImageDrawable(transition) // Description of the initial state that the drawable represents. image.contentDescription = resources.getString(R.string.collapsed) // Then you can call the TransitionDrawable object's methods. transition.startTransition(1000) // After the transition is complete, change the image's content description // to reflect the new state.
Java
Resources res = context.getResources(); TransitionDrawable transition = (TransitionDrawable) ResourcesCompat.getDrawable(res, R.drawable.expand_collapse, null); ImageView image = (ImageView) findViewById(R.id.toggle_image); image.setImageDrawable(transition); // Description of the initial state that the drawable represents. image.setContentDescription(getResources().getString(R.string.collapsed)); // Then you can call the TransitionDrawable object's methods. transition.startTransition(1000); // After the transition is complete, change the image's content description // to reflect the new state.
Para mais informações sobre os atributos XML compatíveis, consulte as classes listados acima.
Drawables de formato
Um objeto ShapeDrawable
pode ser uma boa opção
quando você quer desenhar dinamicamente um gráfico bidimensional. Você pode
desenhar formas primitivas de forma programática em um objeto ShapeDrawable
;
e aplicar os estilos que o app precisa.
ShapeDrawable
é uma subclasse de Drawable
. Por isso, você pode usar uma
ShapeDrawable
em que um Drawable
é esperado. Para
Por exemplo, é possível usar um objeto ShapeDrawable
para definir o plano de fundo
de uma visualização transmitindo-a para o método setBackgroundDrawable()
dela. Você também pode desenhar sua forma
visualização personalizada e adicioná-la a um layout no seu app.
Como ShapeDrawable
tem o próprio método draw()
, é possível criar um
subclasse de View
que desenha a ShapeDrawable
objeto durante o evento onDraw()
, conforme mostrado no
este exemplo de código:
Kotlin
class CustomDrawableView(context: Context) : View(context) { private val drawable: ShapeDrawable = run { val x = 10 val y = 10 val width = 300 val height = 50 contentDescription = context.resources.getString(R.string.my_view_desc) ShapeDrawable(OvalShape()).apply { // If the color isn't set, the shape uses black as the default. paint.color = 0xff74AC23.toInt() // If the bounds aren't set, the shape can't be drawn. setBounds(x, y, x + width, y + height) } } override fun onDraw(canvas: Canvas) { drawable.draw(canvas) } }
Java
public class CustomDrawableView extends View { private ShapeDrawable drawable; public CustomDrawableView(Context context) { super(context); int x = 10; int y = 10; int width = 300; int height = 50; setContentDescription(context.getResources().getString( R.string.my_view_desc)); drawable = new ShapeDrawable(new OvalShape()); // If the color isn't set, the shape uses black as the default. drawable.getPaint().setColor(0xff74AC23); // If the bounds aren't set, the shape can't be drawn. drawable.setBounds(x, y, x + width, y + height); } protected void onDraw(Canvas canvas) { drawable.draw(canvas); } }
Use a classe CustomDrawableView
no exemplo de código
acima, como você usaria qualquer outra visualização personalizada. Por exemplo, é possível
adicioná-lo de forma programática a uma atividade no app, como mostrado abaixo
exemplo:
Kotlin
private lateinit var customDrawableView: CustomDrawableView override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) customDrawableView = CustomDrawableView(this) setContentView(customDrawableView) }
Java
CustomDrawableView customDrawableView; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); customDrawableView = new CustomDrawableView(this); setContentView(customDrawableView); }
Se você preferir usar a visualização personalizada no layout XML, o
A classe CustomDrawableView
precisa substituir o construtor View(Context, AttributeSet)
, que é chamado quando a classe é
inflada a partir de XML. O exemplo a seguir mostra como declarar
CustomDrawableView
no layout XML:
<com.example.shapedrawable.CustomDrawableView android:layout_width="fill_parent" android:layout_height="wrap_content" />
A classe ShapeDrawable
, assim como muitas outras
de drawable no pacote android.graphics.drawable
, permite
definir várias propriedades do objeto usando métodos públicos. Alguns exemplos
propriedades que talvez você queira ajustar incluem transparência alfa, filtro de cor,
pontilhamento, opacidade e cor.
Também é possível definir formas básicas de drawable por meio de recursos XML. Para mais informações, consulte Drawable de formato em Tipos de recursos drawable.
Drawables NinePatch
Um gráfico NinePatchDrawable
é
de bitmap esticável que pode ser usada como plano de fundo de uma visualização. Android
redimensiona automaticamente o gráfico para acomodar o conteúdo da visualização. Um
exemplo de uso de uma imagem NinePatch é o plano de fundo usado pelo sistema
botões: os botões devem esticar para acomodar strings de vários comprimentos. Um
O gráfico NinePatch é uma imagem PNG padrão que inclui uma borda extra de 1 pixel.
Ele precisa ser salvo com a extensão 9.png
no
res/drawable/
do seu projeto.
Use a borda para definir as áreas esticáveis e estáticas da imagem. Você indica uma seção esticável desenhando uma ou mais imagens com 1 pixel de largura linha(s) preta(s) na parte esquerda e superior da borda (os outros pixels da borda deve ser totalmente transparente ou branco). É possível ter quantas seções esticáveis como quiser. O tamanho relativo das seções esticáveis permanece o mesmo, então a maior seção é sempre a maior.
Também é possível definir uma seção de drawable opcional da imagem (efetivamente,
as linhas de preenchimento) desenhando uma linha à direita e outra na parte inferior. Se um
O objeto View
define o gráfico NinePatch como segundo plano.
e, em seguida, especifica o texto da visualização, ele se estica para que todo o texto
ocupa somente a área designada pelas linhas à direita e inferior (se incluídas).
Se as linhas de padding não estiverem incluídas, o Android usará as linhas esquerda e superior para
definem a área do desenhável.
Para esclarecer a diferença entre as linhas, as linhas esquerda e superior definem quais pixels da imagem podem ser replicados a fim de esticar a imagem. As linhas inferior e direita definem a área relativa dentro da imagem que que o conteúdo da visualização possa ocupar.
A Figura 1 mostra um exemplo de gráfico NinePatch usado para definir um botão:
Este gráfico NinePatch define uma área esticável com as partes esquerda e superior e a área do drawable com as linhas inferior e direita. Na imagem de cima, as linhas cinza pontilhadas identificam as regiões da imagem que são replicadas para esticar a imagem. O retângulo rosa na imagem de baixo identifica a região em que o conteúdo da visualização é permitido. Se o conteúdo não cabem nessa região, a imagem é esticada para ajustá-las.
A ferramenta Draw 9-patch oferece uma É uma forma muito prática de criar suas imagens NinePatch usando gráficos WYSIWYG. editor. Avisos serão gerados até mesmo se a região que você definiu para o área corre o risco de produzir artefatos de desenho como resultado da aplicação de forma consistente.
O XML de layout de exemplo a seguir demonstra como adicionar um gráfico NinePatch
alguns botões. A imagem NinePatch é salva
res/drawable/my_button_background.9.png
:
<Button android:id="@+id/tiny" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_centerInParent="true" android:text="Tiny" android:textSize="8sp" android:background="@drawable/my_button_background"/> <Button android:id="@+id/big" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_centerInParent="true" android:text="Biiiiiiig text!" android:textSize="30sp" android:background="@drawable/my_button_background"/>
layout_width
e layout_height
atributos sejam definidos como wrap_content
para que o botão se encaixe perfeitamente.
ao redor do texto.
A Figura 2 mostra os dois botões renderizados da imagem XML e NinePatch como mostrado acima. Observe como a largura e a altura do botão variam de acordo com o texto, e a imagem de plano de fundo se estica para acomodá-la.
Drawables personalizados
Quando você quiser criar alguns desenhos personalizados, estenda a classe Drawable
(ou qualquer uma das subclasses relacionadas).
O método mais importante a ser implementado é draw(Canvas)
porque isso fornece o objeto Canvas
que você precisa usar para fornecer
suas instruções de desenho.
O código a seguir mostra uma subclasse simples de Drawable
.
que desenha um círculo:
Kotlin
class MyDrawable : Drawable() { private val redPaint: Paint = Paint().apply { setARGB(255, 255, 0, 0) } override fun draw(canvas: Canvas) { // Get the drawable's bounds val width: Int = bounds.width() val height: Int = bounds.height() val radius: Float = Math.min(width, height).toFloat() / 2f // Draw a red circle in the center canvas.drawCircle((width / 2).toFloat(), (height / 2).toFloat(), radius, redPaint) } override fun setAlpha(alpha: Int) { // This method is required } override fun setColorFilter(colorFilter: ColorFilter?) { // This method is required } override fun getOpacity(): Int = // Must be PixelFormat.UNKNOWN, TRANSLUCENT, TRANSPARENT, or OPAQUE PixelFormat.OPAQUE }
Java
public class MyDrawable extends Drawable { private final Paint redPaint; public MyDrawable() { // Set up color and text size redPaint = new Paint(); redPaint.setARGB(255, 255, 0, 0); } @Override public void draw(Canvas canvas) { // Get the drawable's bounds int width = getBounds().width(); int height = getBounds().height(); float radius = Math.min(width, height) / 2; // Draw a red circle in the center canvas.drawCircle(width/2, height/2, radius, redPaint); } @Override public void setAlpha(int alpha) { // This method is required } @Override public void setColorFilter(ColorFilter colorFilter) { // This method is required } @Override public int getOpacity() { // Must be PixelFormat.UNKNOWN, TRANSLUCENT, TRANSPARENT, or OPAQUE return PixelFormat.OPAQUE; } }
Depois, é possível adicionar o desenhável onde quiser, como em uma
ImageView
, como mostrado aqui:
Kotlin
val myDrawing = MyDrawable() val image: ImageView = findViewById(R.id.imageView) image.setImageDrawable(myDrawing) image.contentDescription = resources.getString(R.string.my_image_desc)
Java
MyDrawable mydrawing = new MyDrawable(); ImageView image = findViewById(R.id.imageView); image.setImageDrawable(mydrawing); image.setContentDescription(getResources().getString(R.string.my_image_desc));
No Android 7.0 (nível 24 da API) e versões mais recentes, também é possível definir instâncias do com XML das seguintes maneiras:
- Use o nome de classe totalmente qualificado como o nome do elemento XML. Para essa abordagem, o modelo
A classe drawable precisa ser pública de nível superior:
<com.myapp.MyDrawable xmlns:android="http://schemas.android.com/apk/res/android" android:color="#ffff0000" />
- Usar
drawable
como o nome da tag XML e especificar a classe totalmente qualificada name do atributo de classe. Essa abordagem pode ser usada para classes públicas de nível superior e classes internas estáticas públicas:<drawable xmlns:android="http://schemas.android.com/apk/res/android" class="com.myapp.MyTopLevelClass$MyDrawable" android:color="#ffff0000" />
Adicionar tonalidade a drawables
Com o Android 5.0 (API de nível 21) e posteriores, é possível colorir bitmaps e 9-patches definidos como
máscaras alfa. É possível colori-los com recursos de cor ou atributos de tema que determinam a cor
recursos, como ?android:attr/colorPrimary
. Normalmente, você cria esses recursos
apenas uma vez e colore-as automaticamente para combinar com seu tema.
Você pode aplicar uma tonalidade a BitmapDrawable
, NinePatchDrawable
ou VectorDrawable
com o método setTint()
. Você pode
definir a cor e o modo da tonalidade nos seus layouts com android:tint
e
android:tintMode
.
Extrair cores em destaque de uma imagem
A Biblioteca de Suporte do Android inclui a classe Palette
, que permite extrair as cores em destaque de uma imagem.
Carregue seus drawables como um Bitmap
e transmita-o para Palette
para acessar as cores dele.
Para mais informações, leia Seleção de cores com
a API Palette.