Comment implémenter un Android: un arrière-plan qui ne s'étire pas?

100

J'ai trouvé ce grand fil de discussion décrivant comment «manger le gâteau et l'avoir aussi», c'est-à-dire utiliser l'image pour un Buttonau lieu de ImageButton(ce qui ne permet pas SetText(), le redimensionnement, etc.).

Ceci est réalisé en utilisant l'attribut View:

android:background="@drawable/bgimage"

Le seul problème avec cela est que cela étire l'image pour l'adapter à la taille du bouton.

À moins de coder en dur une taille de bouton fixe (en pixels!), Existe-t-il un moyen de dire à Android de ne pas étirer du tout l'image d'arrière-plan et de la recadrer ou de la remplir?

ef2011
la source

Réponses:

29

Vous devez utiliser ImageView si vous ne souhaitez pas qu'il s'étire. Les images d'arrière-plan s'étireront toujours pour s'adapter à la vue. Vous devez le définir comme Drawable pour forcer l'aspect de l'image à l'objet.

Sinon, si vous vous en tenez à l'idée du bouton, vous devrez forcer la mise à l'échelle du bouton pour empêcher l'image de s'étirer.

Code:

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
la source
1
Merci + 1. ImageViewsemble intéressant. Je l' ai remarqué a un attribut qui est pas Button: android:cropToPadding. Cela ne me dérange pas d'utiliser un ImageView à la place, tant qu'il en a setOnClickListener(), ce qu'il fait. Que vais-je perdre en passant de Buttonà ImageView?
ef2011
1
BTW, la 2ème solution que vous avez suggérée étire toujours l'image.
ef2011
J'ai fini par utiliser une taille de bouton fixe (en pixels!) Mais j'accepte votre réponse car la 1ère suggestion ressemble à une solution alternative fonctionnelle.
ef2011
1
@ ef2011 Pour ImageView, ne le définissez pas comme image d'arrière-plan, vous devez le définir comme un setDrawableResource, puis assurez-vous qu'il setAdjustViewBoundsest défini sur true
Dr.J
9
Évalué pour une solution boiteuse. Solution correcte ici: stackoverflow.com/a/9362168/145046
Aleks N.
260

Vous pouvez créer un bitmap xml et l'utiliser comme arrière-plan de la vue. Pour éviter l'étirement, vous pouvez spécifier un android:gravityattribut.

par exemple:

<?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>

Il existe de nombreuses options que vous pouvez utiliser pour personnaliser le rendu de l'image

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

Santosh
la source
3
Utiliser ImageViews est une solution de contournement qui n'est pas toujours une option possible - je pense que c'est la bonne solution :)
JakeP
3
Je mets l'arrière-plan au moment de l'exécution. Existe-t-il une solution pour créer un bitmap au moment de l'exécution?
Vivek Kumar Srivastava
1
pour moi c'était la meilleure solution mais en supprimant l'attribut "gravity", qui le fait correspondre à sa valeur par défaut "fill". Cela permettra de redimensionner l'image pour s'adapter à l'écran. Étudiez le lien @Santosh pour plus d'informations. Merci!
Hugo
12
Je ne vois qu'un seul problème avec cette approche. Si la source dessinable est déjà plus grande que le conteneur, cela découpera l'image (en fonction de la gravité) plutôt que de la redimensionner, en conservant le rapport hauteur / largeur, pour l'adapter au conteneur.
Shashwat Black
1
Semble un peu daté maintenant. Cela ne fonctionne que pour les bitmaps et ne fonctionne pas pour les dessins vectoriels.
The_Sympathizer
25

Utiliser simplement ImageButtonau lieu de Buttonrésout le problème.

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

et vous pouvez définir

android:background="@null"

pour supprimer l'arrière-plan du bouton si vous le souhaitez.

Solution rapide !! :-)

Adil Malik
la source
1
Et puis définissez l'image avec la méthode setImageResource () ... qui a fonctionné pour moi.
arlomedia
je voulais à la fois l'image et la couleur d'arrière-plan dans un bouton ... cela a fonctionné comme un charme
Abhishek Chauhan
Cela fonctionne plus précisément pour moi (je veux dire - "layout_centerVertical", par exemple).
Maxim Firsoff
11

J'utilise un ImageView dans un RelativeLayout qui se superpose à ma mise en page normale. Aucun code requis. Il redimensionne l'image à la hauteur totale de l'écran (ou de toute autre disposition que vous utilisez), puis recadre l'image à gauche et à droite pour l'adapter à la largeur. Dans mon cas, si l'utilisateur tourne l'écran, l'image peut être un tout petit peu trop petite. Par conséquent, j'utilise match_parent, ce qui rendra l'image étirée en largeur si elle est trop petite.

<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
la source
C'est en fait une solution beaucoup plus simple pour un problème qui ne devrait pas exister
Ákos Nikházy
6

J'ai eu le même problème: vous ne devriez utiliser qu'une image à 9 patchs (.9.png) au lieu de votre image d'origine.

Serge

Serge Bollaerts
la source
5

Utilisez draw9patch ... inclus dans les outils SDK d'Android Studio. Vous pouvez définir les zones extensibles de votre image. Les parties importantes sont contraintes et l'image n'a pas l'air déformée. Une bonne démo sur dra9patch est ICI

Utilisez draw9patch pour changer votre splash.png existant en new_splash.9.png, faites glisser new_splash.9.png dans le dossier du projet drawable-hdpi assurez-vous que AndroidManifest et styles.xml sont corrects comme ci-dessous:

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
la source
3

J'avais une image de fond, pas de grande taille, mais avec des dimensions étranges - donc l'étirement et les mauvaises performances. J'ai fait une méthode avec des paramètres Contexte, une vue et un ID dessinable (int) qui correspondra à la taille de l'écran de l'appareil. Utilisez ceci par exemple dans un Fragments onCreateView pour définir l'arrière-plan.

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
la source
1

Voici une version de la réponse de Santosh pour les boutons créés par programme, sans avoir besoin d'une configuration XML distincte:

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

J'ai inclus la ligne ColorFilter car cela fonctionne un peu différemment des boutons avec une image d'arrière-plan normale.

arlomedia
la source
1

Vous pouvez utiliser a FrameLayoutavec un ImageViewcomme premier enfant, puis votre disposition normale comme deuxième enfant:

<?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
la source
0

La clé est de définir le dessinable comme image du bouton, pas comme arrière-plan. Comme ça:

rb.setButtonDrawable(R.drawable.whatever_drawable);
Jose L Ugia
la source
Il s'agit d'une méthode de CompoundButton mais pas de Button.
arlomedia
0

On peut utiliser un simple ImageView dans son xml et le rendre cliquable (android: clickable = "true")? Vous n'avez qu'à utiliser comme src une image qui a été formée comme un bouton c'est à dire des coins arrondis.

Grigoreas P.
la source