web-dev-qa-db-fra.com

Mise à l'échelle de ImageView à la largeur du périphérique

Dans mon application Android, j'ai une activité qui affiche des images dont la taille est la suivante: 244 x 330. Je veux montrer ces images dans la largeur totale de l'appareil.

Mon fichier de présentation ressemble à ceci:

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

J'ai essayé de définir le ScaleType de ImageView mais il n'y a pas de ScalingType qui redimensionne le proportionnel ImageView. Comment puis-je redimensionner l’image proportionnellement à l’ensemble de l’écran en mode paysage ET en mode portrait?

Ce que je veux fondamentalement, c’est quelque chose comme ScaleType.CENTER_CORP mais qui définit également la hauteur proportionnelle de l’image afin que je puisse tout voir et pas seulement une partie de l’image.

Modifier parce que je sais que je vous confonds avec ma quête "bizarre".

Je veux vous le montrer avec une image. C'est ce que je reçois pour le moment avec ma mise en page. Je souhaite remplir toute la zone grise en redimensionnant l'image aussi grande que nécessaire. Comment puis-je accomplir cela?

Lorsque je règle ScaleType sur CENTER_CROP, je reçois ce message.

mais ce n'est pas ce que je veux parce que vous ne voyez pas l'image entière simplement à partir du centre.

Et voici ce que je veux que ce soit:

J'espère que cela vous aide à comprendre ce que j'essaie d'accomplir. Quelqu'un sait comment faire ça?

Edit 2:

Cela peut sembler bizarre et peu déroutant que j'essaye d'afficher une image dont la hauteur est supérieure à la taille de l'écran, mais puisque j'utilise une variable ScrollView dans mon exemple, cela devrait être correct et l'utilisateur peut faire défiler s'il le souhaite. pour voir la zone non affichée.

J'espère que cela aide à comprendre ce que j'essaie de faire.

14
OemerA

J'ai vraiment essayé chaque ScaleType dans ma ImageView avec fill_parent et wrap_content mais aucun d'entre eux n'a fonctionné. J'ai également essayé tout ce que j'ai trouvé sur Google, mais rien ne fonctionnait pour moi non plus, alors j'ai trouvé quelque chose par moi-même.

Il était clair que ImageView ne redimensionnait pas mon image comme je le souhaitais et que je devais donc la redimensionner moi-même. Après la mise à l'échelle de l'image bitmap, je définirais la nouvelle image bitmap en tant que source d'image pour ImageView. Cela fonctionne très bien et semble très bien sur le G1 et le Motorola Milestone 2.

Et voici tous les morceaux de mon code

Disposition:

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

Activité

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

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

}

S'il existe un moyen meilleur ou plus précis de réaliser la même mise à l'échelle s'il vous plaît, faites-moi savoir parce que je ne peux pas croire qu’une chose aussi triviale soit si difficile à accomplir.

J'espère vraiment trouver un meilleur moyen de le faire.

Merci pour la lecture.

29
OemerA

le moyen le plus simple consiste à ajouter Android: adjustViewBounds = "true" à ImageView et à définir le type de balance sur "fitCenter".

19
Marian

Légèrement confus sur ce que vous recherchez, exactement. Si vous adaptez votre écran à l’écran, vous avez trois options, dont deux sont viables si vous conservez les proportions. Vous pouvez utiliser ScaleType fitCenter, qui ajustera l’image proportionnellement dans les limites, ou vous pouvez utiliser centerCrop (ce que vous avez dit avoir essayé), qui étendra le plus petit côté de l’image pour s’adapter au conteneur (ce qui signifie que certains seront tronqués). sur la plus longue dimension). Vous ne pouvez pas l'étirer pour s'adapter à la largeur ET à la hauteur sans recadrer ou étirer de manière disproportionnée.

EDIT: D'accord, je pense que je comprends maintenant. Premièrement, je définirais votre LinearLayout sur wrap_content pour la hauteur. Deuxièmement, dans le code, voici une façon de le faire à laquelle je peux penser. Il existe probablement une autre façon de procéder en obtenant d’abord les dimensions de l’écran, puis en utilisant createScaledBitmap avec les nouvelles dimensions, puis en définissant la ressource d’arrière-plan.

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);
        }
    }
}
3
kcoppock

J'ai cherché Google partout et je n'ai pas trouvé de solution. Voici ce que j'ai fait, cela a fonctionné pour moi et avec une vue de défilement.

Fichier 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>
3
vtlinh

Avez-vous essayé de le définir par programme via ImageView.setScaleType()?

setAdjustViewBounds( false ) pourrait également vous aider.

Edit: désolé, j'ai mal lu la question. Quoi qu'il en soit, setAdjustViewBounds() still pourrait aider. Jamais utilisé cependant.

2
Snailer

Je veux montrer ces images dans la largeur totale de l'appareil.

C'est simple Vous avez juste les mauvais paramètres de marge. Supprimez ces lignes et votre image apparaîtra dans la largeur totale du périphérique:

Android:layout_marginLeft="18dip"
Android:layout_marginRight="18dip" 
2
user432209

réussir à atteindre ce que je voulais, ce qui est, espérons-le, le même que votre objectif:

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

puis pour redimensionner le bitmap:

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;
}
1
Hitesh Tailor

Je ne vois plus les images et la question est ancienne, mais juste au cas où quelqu'un d'autre le trouverait et aurait le même problème. Ne feriez-vous pas mieux d’obtenir float screenWidth = getResources().getDisplayMetrics().widthPixels et de configurer par programme ImageView LayoutParamters pour redimensionner l’image en screenWidth. Juste une idée !!

1
Saad Farooq

Une des façons de le faire consiste à définir Android: adjustViewBounds = "true" dans ImageView et à définir le type d'échelle sur "fitCenter" dans le fichier xml. Cela devrait fonctionner comme prévu. Vous pouvez également le faire par programme en définissant ImageView.adjustViewBounds (true) et ImageView.setScaleType (ScaleType.FIT_CENTER).

0
Parag Agrawal