Wie implementiere ich einen Android: Hintergrund, der sich nicht dehnt?

100

Ich fand diesen großartigen Thread, der beschreibt, wie man "den Kuchen isst und ihn auch hat", dh ein Bild für ein Buttonanstelle von verwendet ImageButton(was nicht erlaubt SetText(), die Größe ändert usw.).

Dies wird mithilfe des View-Attributs erreicht:

android:background="@drawable/bgimage"

Das einzige Problem dabei ist, dass das Bild so gedehnt wird, dass es der Schaltflächengröße entspricht.

Gibt es eine Möglichkeit, Android anzuweisen, das Hintergrundbild überhaupt nicht zu strecken und es entweder zuzuschneiden oder aufzufüllen, ohne eine feste Tastengröße (in Pixel!) Fest zu codieren ?

ef2011
quelle

Antworten:

29

Sie sollten ImageView verwenden, wenn Sie nicht möchten, dass es sich dehnt. Hintergrundbilder werden immer gedehnt, um der Ansicht zu entsprechen. Sie müssen es als Drawable festlegen, um den Bildaspekt auf das Objekt zu erzwingen.

Wenn Sie an der Button-Idee festhalten, müssen Sie andernfalls die Skalierung in der Button erzwingen, um zu verhindern, dass sich das Bild dehnt.

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.
quelle
1
Danke + 1. ImageViewsieht interessant aus. Mir ist aufgefallen, dass es ein Attribut hat, das nicht in Button: android:cropToPadding. Es macht mir nichts aus, stattdessen ein ImageView zu verwenden, solange es vorhanden ist setOnClickListener()- was es auch tut. Was werde ich aus durch Umschalten zu verlieren sein Buttonzu ImageView?
ef2011
1
Übrigens, die zweite von Ihnen vorgeschlagene Lösung streckt das Bild immer noch.
ef2011
Am Ende habe ich eine feste Tastengröße (in Pixel!) Verwendet, aber ich akzeptiere Ihre Antwort, da der erste Vorschlag wie eine funktionierende alternative Lösung aussieht.
ef2011
1
@ ef2011 Für ImageView legen Sie es nicht als Hintergrundbild fest, Sie müssen es als ein festlegen setDrawableResourceund dann sicherstellen, dass setAdjustViewBoundses auf true gesetzt ist
Dr.J
9
Für eine lahme Lösung herabgestimmt. Richtige Lösung hier: stackoverflow.com/a/9362168/145046
Aleks N.
260

Sie können eine XML-Bitmap erstellen und als Hintergrund für die Ansicht verwenden. Um ein Dehnen zu verhindern, können Sie ein android:gravityAttribut angeben .

beispielsweise:

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

Es gibt viele Optionen, mit denen Sie das Rendern des Bildes anpassen können

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

Santosh
quelle
Super Antwort Kumpel!
Carnal
3
Die Verwendung von ImageViews ist eine Problemumgehung, die nicht immer möglich ist - ich glaube, dies ist die richtige Lösung :)
JakeP
3
Ich stelle den Hintergrund zur Laufzeit ein. Gibt es eine Lösung zum Erstellen einer Bitmap zur Laufzeit?
Vivek Kumar Srivastava
1
Für mich war dies die beste Lösung, aber das Attribut "Schwerkraft" wurde entfernt, wodurch es mit dem Standardwert "Füllen" übereinstimmt. Dadurch kann die Bildgröße an den Bildschirm angepasst werden. Studieren Sie den @ Santosh-Link für weitere Informationen. Vielen Dank!
Hugo
12
Ich sehe nur ein Problem mit diesem Ansatz. Wenn die zeichnbare Quelle bereits größer als der Container ist, wird das Bild (basierend auf der Schwerkraft) abgeschnitten, anstatt die Größe unter Beibehaltung des Seitenverhältnisses an den Container anzupassen.
Shashwat Black
25

Einfach zu verwenden ImageButtonstatt zu Buttonbeheben behebt das Problem.

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

und du kannst einstellen

android:background="@null"

um den Hintergrund der Schaltfläche zu entfernen, wenn Sie möchten.

Schnelle Lösung !! :-)

Adil Malik
quelle
1
Und dann setzen Sie das Bild mit der setImageResource () -Methode ... die für mich funktioniert hat.
Arlomedia
Ich wollte sowohl Bild als auch Hintergrundfarbe in einem Knopf ... das funktionierte wie ein Zauber
Abhishek Chauhan
Es funktioniert genauer für mich (ich meine - zum Beispiel "layout_centerVertical").
Maxim Firsoff
11

Ich verwende eine ImageView in einem RelativeLayout, das sich mit meinem normalen Layout überschneidet. Kein Code erforderlich. Das Bild wird auf die volle Höhe des Bildschirms (oder eines anderen verwendeten Layouts) angepasst und das Bild dann nach links und rechts zugeschnitten, um es an die Breite anzupassen. In meinem Fall ist das Bild möglicherweise etwas zu klein, wenn der Benutzer den Bildschirm dreht. Daher verwende ich match_parent, wodurch das Bild in der Breite gedehnt wird, wenn es zu klein ist.

<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
quelle
Dies ist eigentlich eine viel einfachere Lösung für ein Problem, das es nicht geben sollte
Ákos Nikházy
6

Ich hatte das gleiche Problem: Sie sollten nur ein 9-Patch-Bild (.9.png) anstelle Ihres Originalbildes verwenden.

Serge

Serge Bollaerts
quelle
5

Verwenden Sie draw9patch ..., das in den SDK-Tools von Android Studio enthalten ist. Sie können die dehnbaren Bereiche Ihres Bildes definieren. Wichtige Teile sind eingeschränkt und das Bild sieht nicht ganz verzerrt aus. Eine gute Demo zu dra9patch gibt es HIER

Verwenden Sie draw9patch, um Ihre vorhandene splash.png in new_splash.9.png zu ändern. Ziehen Sie new_splash.9.png in den Projektordner drawable-hdpi und stellen Sie sicher, dass AndroidManifest und styles.xml wie folgt korrekt sind:

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
quelle
3

Ich hatte ein Hintergrundbild, nicht groß, aber mit seltsamen Abmessungen - daher die Dehnung und die schlechte Leistung. Ich habe eine Methode mit den Parametern Context, einer Ansicht und einer zeichnbaren ID (int) erstellt, die der Bildschirmgröße des Geräts entspricht. Verwenden Sie dies beispielsweise in einem Fragment in onVreateView, um den Hintergrund festzulegen.

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
quelle
1

Hier ist eine Version von Santoshs Antwort für programmgesteuert erstellte Schaltflächen, ohne dass eine separate XML-Konfiguration erforderlich ist:

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

Ich habe die ColorFilter-Zeile eingefügt, da dies etwas anders funktioniert als Schaltflächen mit einem normalen Hintergrundbild.

Arlomedia
quelle
1

Sie können a FrameLayoutmit a ImageViewals erstes Kind und dann Ihr normales Layout als zweites Kind verwenden:

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

Der Schlüssel besteht darin, das Zeichenbare als Bild der Schaltfläche und nicht als Hintergrund festzulegen. So was:

rb.setButtonDrawable(R.drawable.whatever_drawable);
Jose L Ugia
quelle
Dies ist eine Methode von CompoundButton, jedoch nicht von Button.
Arlomedia
0

Man kann eine einfache ImageView in seiner XML verwenden und sie anklickbar machen (android: clickable = "true")? Sie müssen nur ein Bild als src verwenden, das wie eine Schaltfläche geformt wurde, dh runde Ecken.

Grigoreas P.
quelle