Como implementar um andróide: fundo que não estica?

100

Eu encontrei este ótimo tópico que descreve como "comer o bolo e ter também", ou seja, usar a imagem para um em Buttonvez de ImageButton(que não permite SetText(), redimensionamento, etc.).

Isso é feito usando o atributo Exibir:

android:background="@drawable/bgimage"

O único problema com isso é que estica a imagem para caber no tamanho do botão.

Com exceção de codificar um tamanho de botão fixo (em pixels!), Há uma maneira de dizer ao Android para não esticar a imagem de fundo e cortá-la ou preenchê-la?

ef2011
fonte

Respostas:

29

Você deve usar ImageView se não quiser esticar. As imagens de fundo sempre se esticarão para caber na visualização. Você precisa defini-lo como um Drawable para forçar o aspecto da imagem para o objeto.

Caso contrário, se você está mantendo a ideia do botão, você precisará forçar a escala no botão para evitar que a imagem se estique.

Código:

onCreate(Bundle bundle) {
  // Set content layout, etc up here

  // Now adjust button sizes
  Button b = (Button) findViewById(R.id.somebutton);
  int someDimension = 50; //50pixels
  b.setWidth(someDimension);
  b.setHeight(someDimension);
}
Dr.J
fonte
1
Obrigado + 1. ImageViewparece interessante. Notei que tem um atributo que não está em Button: android:cropToPadding. Não me importo de usar um ImageView em vez disso, contanto que tenha setOnClickListener()- o que é verdade. O que vou perder ao mudar de Buttonpara ImageView?
ef2011
1
BTW, a 2ª solução que você sugeriu ainda estica a imagem.
ef2011
Acabei usando o tamanho do botão fixo (em pixels!), Mas estou aceitando sua resposta porque a 1ª sugestão parece uma solução alternativa funcional.
ef2011
1
@ ef2011 Para ImageView, não a defina como uma imagem de fundo, você deve defini-la como um setDrawableResourcee, em seguida, certifique-se de que setAdjustViewBoundsestá definido como verdadeiro
Dr.J
9
Votos negados para uma solução coxo. Solução correta aqui: stackoverflow.com/a/9362168/145046
Aleks N.
260

Você pode criar um bitmap xml e usá-lo como plano de fundo para a visualização. Para evitar alongamento, você pode especificar o android:gravityatributo.

por exemplo:

<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
    android:src="@drawable/dvdr"
    android:tileMode="disabled" android:gravity="top" >
</bitmap>

Existem muitas opções que você pode usar para personalizar a renderização da imagem

http://developer.android.com/guide/topics/resources/drawable-resource.html#Bitmap

Santosh
fonte
Ótima resposta, amigo!
Carnal de
3
Usar ImageViews é uma solução alternativa que nem sempre é uma opção possível - acredito que esta seja a solução adequada :)
JakeP
3
Estou definindo o plano de fundo em tempo de execução. Existe alguma solução para criar bitmap em tempo de execução?
Vivek Kumar Srivastava
1
Para mim, esta foi a melhor solução, mas remover o atributo "gravidade", que o faz corresponder ao seu valor padrão "preencher". Isso permitirá que o redimensionamento da imagem caiba na tela. Estude o link @Santosh para mais informações. Obrigado!
Hugo
12
Vejo apenas um problema com essa abordagem. Se a fonte drawable já for maior do que o contêiner, isso irá cortar a imagem (com base na gravidade) em vez de redimensioná-la, mantendo a proporção, para caber no contêiner.
Shashwat Black
25

Simplesmente usar em ImageButtonvez de Buttonresolve o problema.

<ImageButton android:layout_width="30dp"
             android:layout_height="30dp"
             android:src="@drawable/bgimage" />

e você pode definir

android:background="@null"

para remover o fundo do botão, se desejar.

Conserto rápido !! :-)

Adil Malik
fonte
1
E então defina a imagem com o método setImageResource () ... que funcionou para mim.
arlomedia
Eu queria a imagem e a cor do plano de fundo em um botão ... funcionou
perfeitamente
Funciona com mais precisão para mim (quero dizer - "layout_centerVertical", por exemplo).
Maxim Firsoff de
11

Estou usando um ImageView em um RelativeLayout que se sobrepõe ao meu layout normal. Nenhum código necessário. Ele dimensiona a imagem para a altura total da tela (ou qualquer outro layout que você usa) e, em seguida, recorta a imagem à esquerda e à direita para caber na largura. No meu caso, se o usuário virar a tela, a imagem pode ficar um pouco pequena demais. Portanto, eu uso match_parent, o que fará com que a largura da imagem seja muito pequena.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/main_backgroundImage"
        android:layout_width="match_parent"
        //comment: Stretches picture in the width if too small. Use "wrap_content" does not stretch, but leaves space

        android:layout_height="match_parent"
        //in my case I always want the height filled

        android:layout_alignParentTop="true"
        android:scaleType="centerCrop"
        //will crop picture left and right, so it fits in height and keeps aspect ratio

        android:contentDescription="@string/image"
        android:src="@drawable/your_image" />

    <LinearLayout
        android:id="@+id/main_root"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >
    </LinearLayout>

</RelativeLayout>
Gunnar Bernstein
fonte
Esta na verdade é uma solução muito mais fácil para um problema que não deveria existir
Ákos Nikházy
6

Eu tive o mesmo problema: você só deve usar uma imagem de 9 patch (.9.png) em vez da sua imagem original.

Sarja

Serge Bollaerts
fonte
5

Use draw9patch ... incluído nas ferramentas SDK do Android Studio. Você pode definir as áreas extensíveis de sua imagem. Partes importantes são restringidas e a imagem não parece toda distorcida. Uma boa demonstração do dra9patch está AQUI

Use draw9patch para alterar seu splash.png existente para new_splash.9.png, arraste new_splash.9.png para a pasta do projeto drawable-hdpi e certifique-se de que AndroidManifest e styles.xml sejam adequados conforme abaixo:

AndroidManifest.xml:

<application
...
        android:theme="@style/splashScreenStyle"
>

styles.xml:

<style name="splashScreenStyle" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="android:windowBackground">@drawable/new_splash</item>
</style>
WM1
fonte
3

Eu tinha uma imagem de fundo, não grande em tamanho, mas com dimensões estranhas - daí o alongamento e o mau desempenho. Fiz um método com os parâmetros Context, uma View e um drawable ID (int) que vai corresponder ao tamanho da tela do dispositivo. Use isso, por exemplo, em um Fragments onCreateView para definir o plano de fundo.

public void setBackground(Context context, View view, int drawableId){
    Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(),drawableId);

    bitmap = Bitmap.createScaledBitmap(bitmap, Resources.getSystem().
             getDisplayMetrics().widthPixels,
             Resources.getSystem().getDisplayMetrics().heightPixels,
             true);

    BitmapDrawable bitmapDrawable = new BitmapDrawable(context.getResources(), 
                                    bitmap);

    view.setBackground(bitmapDrawable);
}
ZooMagic
fonte
1

Esta é uma versão da resposta de Santosh para botões criados programaticamente, sem a necessidade de uma configuração XML separada:

Button button = new Button(getContext());
Bitmap backgroundBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.my_button);
BitmapDrawable backgroundDrawable = new BitmapDrawable(getResources(), backgroundBitmap);
backgroundDrawable.setGravity(Gravity.CENTER); // also LEFT, CENTER_VERTICAL, etc.
backgroundDrawable.setColorFilter(new PorterDuffColorFilter(Color.RED, PorterDuff.Mode.SRC_ATOP));
button.setBackground(backgroundDrawable);

Incluí a linha ColorFilter, pois funciona um pouco diferente dos botões com uma imagem de fundo normal.

arlomédia
fonte
1

Você pode usar um FrameLayoutcom um ImageViewcomo o primeiro filho e, em seguida, seu layout normal como o segundo filho:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

  <ImageView
        android:id="@+id/background_image_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop"
        android:src="@drawable/your_drawable"/>

  <LinearLayout
        android:id="@+id/your_actual_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

  </LinearLayout>

</FrameLayout>
Adam Johns
fonte
0

A chave é definir o drawable como a imagem do botão, não como um plano de fundo. Como isso:

rb.setButtonDrawable(R.drawable.whatever_drawable);
Jose L Ugia
fonte
Este é um método de CompoundButton, mas não de Button.
arlomedia
0

Pode-se usar um ImageView simples em seu xml e torná-lo clicável (android: clickable = "true")? Você só precisa usar como src uma imagem que tenha o formato de um botão, ou seja, cantos arredondados.

Grigoreas P.
fonte