2011-02-02 23 views
14

En mi aplicación Android tengo una actividad que muestra imágenes que tienen el siguiente tamaño 244 x 330. Quiero mostrar esas imágenes en el ancho total del dispositivo.Escala ImageView al ancho del dispositivo

Mi archivo de diseño se parece a esto:

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

    <LinearLayout 
     android:layout_width="fill_parent" 
     android:layout_height="fill_parent" 
     android:orientation="vertical"> 

      <ImageView android:id="@+id/news_image" 
       android:layout_height="fill_parent" 
       android:layout_width="fill_parent" 
       android:layout_marginLeft="18dip" 
       android:layout_marginRight="18dip" 
       android:background="#aaaaaa" /> 


    </LinearLayout> 

</ScrollView> 

traté de establecer el ScaleType del ImageView pero no hay ScalingType que escala el ImageView proporcional. ¿Cómo puedo escalar la imagen proporcionalmente para que se ajuste a toda la pantalla en modo horizontal Y en modo vertical?

Básicamente lo que quiero es algo así como ScaleType.CENTER_CORP pero que también establece la altura proporcional de la imagen para que pueda ver todo y no solo una parte de la imagen.

Editar porque sé que te estoy confundiendo con mi búsqueda "rara".

Quiero mostrarle una imagen. Esto es lo que obtengo en este momento con mi diseño. Quiero llenar toda el área gris escalando la imagen tan grande como sea necesario. ¿Cómo puedo lograr eso?

Cuando me puse la ScaleType a CENTER_CROP recibí este

pero esto no es lo que quiero hacer que usted no está viendo la imagen completa sólo una parte del centro.

Y esto es lo que yo quiero que sea:

espero que esto le ayuda a comprender lo que estoy tratando de lograr. ¿Alguien sabe cómo hacer eso?

Edición 2:

Puede parecer raro y poco confuso que estoy tratando de mostrar una imagen que es más grande en la altura que el tamaño de la pantalla, pero ya que estoy usando un ScrollView en mi ejemplo diseño esto debería estar bien y el usuario podría desplazarse si quiere ver el área no mostrada.

Espero que esto ayude a entender lo que estoy tratando de hacer.

Respuesta

29

me trataron realmente cada ScaleType en mi ImageView con fill_parent y wrap_content pero ninguno de ellos trabajaron. También intenté todo lo que encontré en Google pero tampoco funcionó, así que se me ocurrió algo.

Estaba claro que ImageView no está escalando mi imagen como si quisiera escalarla, así que tuve que escalarla por mi cuenta. Después de escalar el mapa de bits, establecería el nuevo mapa de bits como fuente de la imagen en ImageView. Esto funciona bastante bien y se ve muy bien en el G1 y en el Motorola Milestone 2.

Y aquí es todas las piezas de mi código

Diseño:

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

    <LinearLayout 
     android:layout_width="fill_parent" 
     android:layout_height="fill_parent" 
     android:id="@+id/news_wrapper"> 

      <ImageView android:id="@+id/news_image" 
       android:layout_height="fill_parent" 
       android:layout_width="fill_parent" 
       android:layout_marginLeft="18dip" 
       android:layout_marginRight="18dip" 
       android:background="#aaaaaa" /> 

    </LinearLayout> 

</ScrollView> 

Actividad

public class ScalingImages extends Activity { 

    private ImageView imageView; 

    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.test_margin); 

     this.imageView = (ImageView)findViewById(R.id.news_image); 

     // The image is coming from resource folder but it could also 
     // load from the internet or whatever 
     Drawable drawable = getResources().getDrawable(R.drawable.img); 
     Bitmap bitmap = ((BitmapDrawable)drawable).getBitmap(); 

     // Get scaling factor to fit the max possible width of the ImageView 
     float scalingFactor = this.getBitmapScalingFactor(bitmap); 

     // Create a new bitmap with the scaling factor 
     Bitmap newBitmap = Util.ScaleBitmap(bitmap, scalingFactor); 

     // Set the bitmap as the ImageView source 
     this.imageView.setImageBitmap(newBitmap); 
    } 

    private float getBitmapScalingFactor(Bitmap bm) { 
     // Get display width from device 
     int displayWidth = getWindowManager().getDefaultDisplay().getWidth(); 

     // Get margin to use it for calculating to max width of the ImageView 
     LinearLayout.LayoutParams layoutParams = 
      (LinearLayout.LayoutParams)this.imageView.getLayoutParams(); 
     int leftMargin = layoutParams.leftMargin; 
     int rightMargin = layoutParams.rightMargin; 

     // Calculate the max width of the imageView 
     int imageViewWidth = displayWidth - (leftMargin + rightMargin); 

     // Calculate scaling factor and return it 
     return ((float) imageViewWidth/(float) bm.getWidth()); 
    } 
} 

Clase util

public class Util { 

    public static Bitmap ScaleBitmap(Bitmap bm, float scalingFactor) { 
     int scaleHeight = (int) (bm.getHeight() * scalingFactor); 
     int scaleWidth = (int) (bm.getWidth() * scalingFactor); 

     return Bitmap.createScaledBitmap(bm, scaleWidth, scaleHeight, true); 
    } 

} 

Si hay una manera mejor o más precisa de lograr la misma escala , por favor avíseme porque no puedo creer que una cosa tan trivial sea tan difícil de lograr.

Realmente espero ver una mejor manera de hacerlo.

Gracias por leer.

+2

Thnx para compartir. Debería haber un factor de escala para hacer esto. – binW

+1

Muchas gracias - ¡No puedo creer que no haya una manera más fácil de hacerlo! –

+1

También perdí mucho tiempo tratando de usar las configuraciones en el xml. Gracias por publicar su propia solución. – ggenglish

2

¿Ha intentado configurarlo programáticamente a través de ImageView.setScaleType()?

setAdjustViewBounds(false) puede ser de ayuda también.

Editar: lo siento, he leído mal la pregunta. De todos modos, setAdjustViewBounds()todavía podría ayudar. Nunca lo usé sin embargo.

+0

Acabo de probar 'setAdjustViewBounds', pero no sirvió. ¿Cualquier otra sugerencia? Tal vez mi edición está haciendo que mi objetivo sea mejor para entender. – OemerA

2

Quiero mostrar esas imágenes en su totalidad ancho del dispositivo.

Esto es simple.Simplemente tiene la configuración de margen incorrecta. Elimine estas líneas y su imagen se mostrará en el ancho total del dispositivo:

android:layout_marginLeft="18dip" 
android:layout_marginRight="18dip" 
+0

Esto parece extraño, pero en realidad me gustaría tener estos márgenes; de lo contrario, me gustaría "pegar" la pantalla. A menos que los 18 caigan a la izquierda y a la derecha, me gustaría utilizar todo el tamaño de la pantalla. – OemerA

3

Ligeramente confundido con lo que está buscando, exactamente. Si está escalando para ajustarse a la pantalla, tiene tres opciones, dos de las cuales son viables si mantiene las proporciones. Puede usar ScaleType fitCenter, que hará que la imagen se ajuste dentro de los límites proporcionalmente, o puede usar centerCrop (que dijo que había intentado), que estirará el lado más corto de la imagen para que se ajuste al contenedor (es decir, algunos se recortarán) en la dimensión más larga). No puede hacer que se estire para ajustar el ancho Y la altura sin recortar o estirar de manera desproporcionada.

EDIT: Bien, creo que entiendo su punto ahora. Primero, establecería LinearLayout en wrap_content para la altura. Segundo, en el código, aquí hay una manera en que puedes hacerlo que yo pueda pensar. Probablemente también haya otra manera de hacerlo, primero obteniendo las dimensiones de la pantalla, y luego haciendo createScaledBitmap con las nuevas dimensiones, y luego estableciendo el recurso de fondo.

final ImageView newsImage = (ImageView)findViewById(R.id.news_image); 

//get details on resolution from the display 
DisplayMetrics metrics = new DisplayMetrics(); 
getWindowManager().getDefaultDisplay().getMetrics(metrics); 

//going to set what happens as the layout happens 
newsImage.getViewTreeObserver().addOnGlobalLayoutListener(
    new ViewTreeObserver.OnGlobalLayoutListener() { 

     public void onGlobalLayout() { 
      int oldHeight, oldWidth, newHeight, newWidth; 

      //we want the new width to be as wide as the screen 
      newWidth = metrics.widthPixels; 

      oldHeight = newsImage.getDrawable().getIntrinsicHeight(); 
      oldWidth = newsImage.getDrawable().getIntrinsicWidth(); 

      //keeping the aspect ratio, the new height should be w1/h1 = w2/h2 
      newHeight = Math.floor((oldHeight * newWidth)/oldWidth); 
      LinearLayout.LayoutParams params = 
       (LinearLayout.LayoutParams)newsImage.getLayoutParams(); 
      params.height = newHeight; 
      params.width = newWidth; 
      newsImage.setLayoutParams(params); 
      newsImage.setScaleType(ScaleType.CENTER); 
      newsImage.invalidate(); 
      newsImage.getViewTreeObserver().removeGlobalOnLayoutListener(this); 
     } 
    } 
} 
+0

Lo intenté pero 'ScaleType.CENTER_CROP'did cortó la altura. ¿Puedes proporcionar una muestra? Lo intentaré de nuevo (tal vez cometí un error en algún lugar) y publicaré mis resultados. – OemerA

+0

Su ejemplo muestra la imagen que se extiende fuera del dispositivo físico ... – kcoppock

+0

TIENE que cortar la altura si desea que se ajuste al ancho. Para hacer lo que está buscando, usaría el tipo de escala fitXY, pero se escalará desproporcionadamente. No hay otra forma de hacer esto. – kcoppock

1

Ya no veo las imágenes y la pregunta es antigua, pero solo en caso de que alguien más encuentre esto y tenga el mismo problema. ¿No sería mejor obtener float screenWidth = getResources().getDisplayMetrics().widthPixels y configurar ImageView LayoutParamters programáticamente para escalar la imagen a screenWidth. Solo una idea !!

1

las arreglan para conseguir lo que quería, que se espera es la misma que su objetivo:

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.pgviewer); 

    ImageView PgContainer = (ImageView)findViewById(R.id.imageView1); 

    String Page = String.valueOf(getIntent().getExtras().getInt("Page")); 
    try { 
     PgContainer.setImageBitmap(getBitmapFromAsset(Page)); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

    PgContainer.setScaleType(ScaleType.FIT_CENTER); 
    PgContainer.scrollTo(0, 0); 
    PgContainer.setScrollBarStyle(0); 
} 

entonces para escalar el mapa de bits:

private Bitmap getBitmapFromAsset(String strName) throws IOException 
{ 
    AssetManager assetManager = getAssets(); 
    InputStream istr = assetManager.open(strName+".png"); 
    Bitmap bitmap = BitmapFactory.decodeStream(istr); 

    float screenWidth = getResources().getDisplayMetrics().widthPixels; 
    int ih=bitmap.getHeight(); 
    int iw=bitmap.getWidth(); 
    float scalefactor = screenWidth/iw; 
    //w = 480, h=~ 
    //int newh = bitmap.getHeight()/bitmap.getWidth(); 
    return android.graphics.Bitmap.createScaledBitmap(bitmap, (int)(iw*scalefactor), (int)(ih*scalefactor), true); 
    //return bitmap; 
} 
3

Busqué en Google en todas partes y no podía encontrar una solución. Esto es lo que hice, que funcionó para mí y con una vista de desplazamiento.

archivo XML:

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

    <ImageView 
     android:id="@+id/manga_page_image" 
     android:layout_width="match_parent" 
     android:layout_height="0dp" 
     android:adjustViewBounds="true" 
     android:scaleType="fitCenter" /> 
</ScrollView> 
+0

¡Confirmado! Funcionó para mí también y es mucho más fácil que escalar la imagen a través del código – chip

19

la forma más fácil es añadir androide: adjustViewBounds = "true" a la ImageView y establecer el tipo de escala para "fitCenter"

+0

Requisito simple con una solución simple, y funcionó bien para mí. (¡Esta debería ser la respuesta correcta!) –

+0

Esto también funciona en la API 20. – Manish

+0

¡La solución perfecta! –

0

lo que solía escalar ImageView con la resolución del dispositivo se establece las propiedades con respecto a padres. Así que a medida que el tamaño de los padres cambia, el tamaño de los elementos también se ampliará. He aquí un ejemplo de mi activity_main.xml

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:app="http://schemas.android.com/apk/res-auto" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    tools:context="com.example.csci567.singleimagerequest.MainActivity"> 

    <ImageView 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:id="@+id/image_display" 
     android:layout_marginBottom="100dp" 
     android:layout_marginLeft="15dp" 
     android:layout_marginRight="15dp" 
     android:layout_centerHorizontal="true" 
     /> 

    <Button 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:text="Upload Image" 
     android:id="@+id/upload_button" 
     android:layout_alignParentBottom="true" 
     android:layout_centerHorizontal="true" 
     android:layout_marginBottom="22dp" /> 

</RelativeLayout 

Se puede poner más elementos mediante el ajuste de los márgenes.

Cuestiones relacionadas