Oft gefragt, nie beantwortet (zumindest nicht reproduzierbar).
Ich habe eine Bildansicht mit einem Bild, das kleiner als die Ansicht ist. Ich möchte das Bild auf die Breite des Bildschirms skalieren und die Höhe der Bildansicht anpassen, um die proportional korrekte Höhe des Bildes wiederzugeben.
<ImageView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
Dies führt dazu, dass das Bild in seiner ursprünglichen Größe (kleiner als die Bildschirmbreite) mit seitlichen Rändern zentriert wird. Nicht gut.
Also habe ich hinzugefügt
android:adjustViewBounds="true"
Gleicher Effekt, nicht gut. Ich fügte hinzu
android:scaleType="centerInside"
Gleicher Effekt, nicht gut. Ich wechselte centerInside
zu fitCenter
. Gleicher Effekt, nicht gut. Ich wechselte centerInside
zu centerCrop
.
android:scaleType="centerCrop"
Jetzt wird das Bild endlich auf die Breite des Bildschirms skaliert - aber oben und unten beschnitten ! Also wechselte ich centerCrop
zu fitXY
.
android:scaleType="fitXY"
Jetzt wird das Bild auf die Breite des Bildschirms skaliert, jedoch nicht auf der y-Achse, was zu einem verzerrten Bild führt.
Das Entfernen android:adjustViewBounds="true"
hat keine Auswirkung. Das Hinzufügen von android:layout_gravity
, wie an anderer Stelle vorgeschlagen, hat wiederum keine Auswirkung.
Ich habe andere Kombinationen ausprobiert - ohne Erfolg. Also, bitte weiß jemand:
Wie richten Sie das XML einer ImageView so ein, dass es die Breite des Bildschirms ausfüllt, skalieren Sie ein kleineres Bild, um die gesamte Ansicht auszufüllen, und zeigen Sie das Bild mit seinem Seitenverhältnis ohne Verzerrung oder Zuschneiden an?
EDIT: Ich habe auch versucht, eine beliebige numerische Höhe einzustellen. Dies wirkt sich nur auf die centerCrop
Einstellung aus. Das Bild wird entsprechend der Ansichtshöhe vertikal verzerrt.
quelle
android:scaleType="fitCenter"
?Antworten:
Ich habe dies gelöst, indem ich eine Java-Klasse erstellt habe, die Sie in Ihre Layout-Datei aufnehmen:
public class DynamicImageView extends ImageView { public DynamicImageView(final Context context, final AttributeSet attrs) { super(context, attrs); } @Override protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { final Drawable d = this.getDrawable(); if (d != null) { // ceil not round - avoid thin vertical gaps along the left/right edges final int width = MeasureSpec.getSize(widthMeasureSpec); final int height = (int) Math.ceil(width * (float) d.getIntrinsicHeight() / d.getIntrinsicWidth()); this.setMeasuredDimension(width, height); } else { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } } }
Jetzt verwenden Sie dies, indem Sie Ihre Klasse zu Ihrer Layout-Datei hinzufügen:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" > <my.package.name.DynamicImageView android:layout_width="fill_parent" android:layout_height="wrap_content" android:scaleType="centerCrop" android:src="@drawable/about_image" /> </RelativeLayout>
quelle
Ich hatte das gleiche Problem wie deins. Nachdem ich 30 Minuten lang verschiedene Variationen ausprobiert hatte, löste ich das Problem auf diese Weise. Sie erhalten die flexible Höhe und Breite, die an die übergeordnete Breite angepasst sind
<ImageView android:id="@+id/imageview_company_logo" android:layout_width="fill_parent" android:layout_height="fill_parent" android:adjustViewBounds="true" android:scaleType="fitCenter" android:src="@drawable/appicon" />
quelle
Innerhalb des XML-Layoutstandards gibt es keine praktikable Lösung.
Die einzige zuverlässige Möglichkeit, auf eine dynamische Bildgröße zu reagieren, ist die Verwendung
LayoutParams
in Code.Enttäuschend.
quelle
android:scaleType="fitCenter"
Berechnen Sie eine Skala, die das ursprüngliche src-Seitenverhältnis beibehält, aber auch sicherstellt, dass src vollständig in dst passt. Mindestens eine Achse (X oder Y) passt genau. Das Ergebnis ist innerhalb von dst zentriert.
bearbeiten:
Das Problem hierbei ist,
layout_height="wrap_content"
dass das Bild nicht "erweitert" werden kann. Für diese Änderung müssen Sie eine Größe festlegenandroid:layout_height="wrap_content"
zu
android:layout_height="100dp" // or whatever size you want it to be
edit2:
funktioniert gut:
<ImageView android:id="@+id/imageView1" android:layout_width="match_parent" android:layout_height="300dp" android:scaleType="fitCenter" android:src="@drawable/img715945m" />
quelle
Dies ist eine kleine Ergänzung zu Mark Martinssons hervorragender Lösung.
Wenn die Breite Ihres Bildes größer als die Höhe ist, lässt Marks Lösung oben und unten auf dem Bildschirm Platz.
Im Folgenden wird dies behoben, indem zuerst Breite und Höhe verglichen werden: Wenn die Bildbreite> = Höhe ist, wird die Höhe an die Bildschirmhöhe angepasst und anschließend die Breite skaliert, um das Seitenverhältnis beizubehalten. Wenn die Bildhöhe> Breite ist, wird die Breite entsprechend der Bildschirmbreite skaliert und anschließend die Höhe skaliert, um das Seitenverhältnis beizubehalten.
Mit anderen Worten, es erfüllt die Definition von
scaleType="centerCrop"
:http://developer.android.com/reference/android/widget/ImageView.ScaleType.html
package com.mypackage; import android.content.Context; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.widget.ImageView; public class FixedCenterCrop extends ImageView { public FixedCenterCrop(final Context context, final AttributeSet attrs) { super(context, attrs); } @Override protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { final Drawable d = this.getDrawable(); if(d != null) { int height = MeasureSpec.getSize(heightMeasureSpec); int width = MeasureSpec.getSize(widthMeasureSpec); if(width >= height) height = (int) Math.ceil(width * (float) d.getIntrinsicHeight() / d.getIntrinsicWidth()); else width = (int) Math.ceil(height * (float) d.getIntrinsicWidth() / d.getIntrinsicHeight()); this.setMeasuredDimension(width, height); } else { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } } }
Diese Lösung funktioniert automatisch im Hoch- oder Querformat. Sie verweisen in Ihrem Layout genauso wie in Marks Lösung. Z.B:
<com.mypackage.FixedCenterCrop android:id="@+id/imgLoginBackground" android:src="@drawable/mybackground" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:scaleType="centerCrop" />
quelle
Ich bin auf dasselbe Problem gestoßen, aber mit einer festen Höhe und einer skalierten Breite, die das ursprüngliche Seitenverhältnis des Bildes beibehält. Ich habe es über ein gewichtetes lineares Layout gelöst. Sie können es hoffentlich an Ihre Bedürfnisse anpassen.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal"> <ImageView android:id="@+id/image" android:layout_width="0px" android:layout_height="180dip" android:layout_weight="1.0" android:adjustViewBounds="true" android:scaleType="fitStart" /> </LinearLayout>
quelle
Kotlin-Version von Mark Martinssons Antwort :
class DynamicImageView(context: Context, attrs: AttributeSet) : AppCompatImageView(context, attrs) { override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { val drawable = this.drawable if (drawable != null) { //Ceil not round - avoid thin vertical gaps along the left/right edges val width = View.MeasureSpec.getSize(widthMeasureSpec) val height = Math.ceil((width * drawable.intrinsicHeight.toFloat() / drawable.intrinsicWidth).toDouble()).toInt() this.setMeasuredDimension(width, height) } else { super.onMeasure(widthMeasureSpec, heightMeasureSpec) } }
quelle
Eine weitere Ergänzung zu Mark Matinssons Lösung. Ich stellte fest, dass einige meiner Bilder überskaliert waren als andere. Deshalb habe ich die Klasse so geändert, dass das Bild um einen maximalen Faktor skaliert wird. Wenn das Bild zu klein ist, um mit maximaler Breite skaliert zu werden, ohne unscharf zu werden, wird die Skalierung über die maximale Grenze hinaus gestoppt.
public class DynamicImageView extends ImageView { final int MAX_SCALE_FACTOR = 2; public DynamicImageView(final Context context) { super(context); } @Override protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { final Drawable d = this.getDrawable(); if (d != null) { // ceil not round - avoid thin vertical gaps along the left/right edges int width = View.MeasureSpec.getSize(widthMeasureSpec); if (width > (d.getIntrinsicWidth()*MAX_SCALE_FACTOR)) width = d.getIntrinsicWidth()*MAX_SCALE_FACTOR; final int height = (int) Math.ceil(width * (float) d.getIntrinsicHeight() / d.getIntrinsicWidth()); this.setMeasuredDimension(width, height); } else { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } } }
quelle