ImageView चौड़ाई भरने और पहलू अनुपात रखने के लिए स्केल छवि


198

मेरे पास ए GridView। का डेटा GridViewसर्वर से अनुरोध है।

यहाँ आइटम लेआउट इस प्रकार है GridView:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/analysis_micon_bg"
    android:gravity="center_horizontal"
    android:orientation="vertical"
    android:paddingBottom="@dimen/half_activity_vertical_margin"
    android:paddingLeft="@dimen/half_activity_horizontal_margin"
    android:paddingRight="@dimen/half_activity_horizontal_margin"
    android:paddingTop="@dimen/half_activity_vertical_margin" >

    <ImageView
        android:id="@+id/ranking_prod_pic"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:adjustViewBounds="true"
        android:contentDescription="@string/app_name"
        android:scaleType="centerCrop" />

    <TextView
        android:id="@+id/ranking_rank_num"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/ranking_prod_num"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/ranking_prod_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</LinearLayout>

मैं सर्वर से डेटा का अनुरोध करता हूं, छवि यूआरएल और लोड छवि प्राप्त करता हूं Bitmap

public static Bitmap loadBitmapFromInputStream(InputStream is) {
    return BitmapFactory.decodeStream(is);
}

public static Bitmap loadBitmapFromHttpUrl(String url) {
    try {
        return loadBitmapFromInputStream((InputStream) (new URL(url).getContent()));
    } catch (Exception e) {
        Log.e(TAG, e.getMessage());
        return null;
    }
}

और getView(int position, View convertView, ViewGroup parent)एडॉप्टर में विधि का कोड है

Bitmap bitmap = BitmapUtil.loadBitmapFromHttpUrl(product.getHttpUrl());
prodImg.setImageBitmap(bitmap);

छवि का आकार है 210*210। मैं अपने नेक्सस 4 पर अपना एप्लिकेशन चलाता हूं। छवि ImageViewचौड़ाई को भरती है , लेकिन ImageViewऊंचाई पैमाने पर नहीं होती है। ImageViewपूरी छवि नहीं दिखाता है।

मैं इस समस्या का समाधान कैसे कर सकता हूं।

जवाबों:


545

किसी भी कस्टम वर्ग या लाइब्रेरी का उपयोग किए बिना:

<ImageView
    android:id="@id/img"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:adjustViewBounds="true"
    android:scaleType="fitCenter" />

scaleType="fitCenter" (चूक होने पर डिफ़ॉल्ट)

  • माता-पिता की अनुमति देता है और पहलू अनुपात रखने के रूप में ऊपर / नीचे पैमाने के रूप में इसे व्यापक बना देगा।

scaleType="centerInside"

  • यदि आंतरिक चौड़ाई srcमाता-पिता की चौड़ाई से छोटी है, तो
    छवि क्षैतिज रूप से केंद्र में होगी
  • यदि आंतरिक चौड़ाई srcमाता-पिता की चौड़ाई से बड़ी है,
    तो यह माता-पिता की अनुमति और डाउन-स्केल कीपिंग आस्पेक्ट रेश्यो के रूप में व्यापक हो जाएगी।

इससे कोई फर्क नहीं पड़ता कि आप उपयोग करते हैं android:srcया ImageView.setImage*विधियाँ और कुंजी शायद है adjustViewBounds


5
एंड्रॉइड: लेआउट_हाइट = "रैप_ कॉन्टेंट" एंड्रॉइड: एडजस्ट व्यूबाउंड्स = "सच" एंड्रॉइड: स्केलटाइप = "फिटकेंटर" चाल करता है
जेम्स टैन

@JamesTan fill_parentचौड़ाई के लिए सिर्फ एक अच्छा अभ्यास है, एक निश्चित आकार भी काम करता है।
ट्वीस्ट्रीमोब

@TWiStErRob मुझे एहसास है कि इसे एंड्रॉइड की आवश्यकता है: इसके साथ एडजस्टेबलबाउंड्स = "सच", अन्यथा यह ऊंचाई के अनुसार फिट नहीं होता है। और हां, माता-पिता को फिट करने की चौड़ाई पूर्ण संस्करण है
जेम्स टैन

9
एपीआई 19+ पर आकर्षण की तरह काम करता है, लेकिन एपीआई 16 (परीक्षण) पर नहीं। एलेक्स सेमेनिउक का कस्टम दृश्य एपीआई 16 पर भी काम करता है।
अश्क सरलाक

1
@ F.Mysir व्हाट्स wh, हां, इससे कोई फर्क नहीं पड़ता कि कौन सा मुद्दा है, लेकिन अच्छी प्रैक्टिस फैलाने के लिए, मैं पूरी तरह से सहमत हूं।
ट्वीस्ट्रीम

42

मुझे arnefm का उत्तर पसंद है लेकिन उसने एक छोटी सी गलती की (टिप्पणी देखें) जिसे मैं सही करने की कोशिश करूंगा:

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.ImageView;

/**
 * ImageView that keeps aspect ratio when scaled
 */
public class ScaleImageView extends ImageView {

  public ScaleImageView(Context context) {
    super(context);
  }

  public ScaleImageView(Context context, AttributeSet attrs) {
    super(context, attrs);
  }

  public ScaleImageView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
  }

  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    try {
      Drawable drawable = getDrawable();
      if (drawable == null) {
        setMeasuredDimension(0, 0);
      } else {
        int measuredWidth = MeasureSpec.getSize(widthMeasureSpec);
        int measuredHeight = MeasureSpec.getSize(heightMeasureSpec);
        if (measuredHeight == 0 && measuredWidth == 0) { //Height and width set to wrap_content
          setMeasuredDimension(measuredWidth, measuredHeight);
        } else if (measuredHeight == 0) { //Height set to wrap_content
          int width = measuredWidth;
          int height = width *  drawable.getIntrinsicHeight() / drawable.getIntrinsicWidth();
          setMeasuredDimension(width, height);
        } else if (measuredWidth == 0){ //Width set to wrap_content
          int height = measuredHeight;
          int width = height * drawable.getIntrinsicWidth() / drawable.getIntrinsicHeight();
          setMeasuredDimension(width, height);
        } else { //Width and height are explicitly set (either to match_parent or to exact value)
          setMeasuredDimension(measuredWidth, measuredHeight);
        }
      }
    } catch (Exception e) {
      super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
  }

}

इस प्रकार आपकी ImageViewत्वचा को ठीक से तराशा जाएगा और कोई आयाम समस्या नहीं होगी यदि (उदाहरण के लिए) अंदर रखी गई होScrollView


thx, मुझे इसका हल मिल गया है, जो arnefm के उत्तर के ठीक नीचे है, पहली टिप्पणी जो मैंने जोड़ी है। कि thereएक कड़ी है
जो

36

मुझे एक बार इसी तरह की समस्या हुई थी। मैंने एक कस्टम ImageView बनाकर इसे हल किया।

public class CustomImageView extends ImageView

फिर इमेजव्यू के ऑनमोर मेथड को ओवरराइड करें। मैंने कुछ ऐसा किया है, मुझे विश्वास है:

    @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    try {
        Drawable drawable = getDrawable();

        if (drawable == null) {
            setMeasuredDimension(0, 0);
        } else {
            float imageSideRatio = (float)drawable.getIntrinsicWidth() / (float)drawable.getIntrinsicHeight();
            float viewSideRatio = (float)MeasureSpec.getSize(widthMeasureSpec) / (float)MeasureSpec.getSize(heightMeasureSpec);
            if (imageSideRatio >= viewSideRatio) {
                // Image is wider than the display (ratio)
                int width = MeasureSpec.getSize(widthMeasureSpec);
                int height = (int)(width / imageSideRatio);
                setMeasuredDimension(width, height);
            } else {
                // Image is taller than the display (ratio)
                int height = MeasureSpec.getSize(heightMeasureSpec);
                int width = (int)(height * imageSideRatio);
                setMeasuredDimension(width, height);
            }
        }
    } catch (Exception e) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

यह पहलू अनुपात को बनाए रखते हुए स्क्रीन को फिट करने के लिए छवि को बढ़ाएगा।


1
वहाँ देखें । पहला उत्तर
जो

खैर, यह जवाब सटीक नहीं है। उस स्थिति पर विचार करें जहां आपने सेट किया था android:layout_height="wrap_content"। इस मामले में MeasureSpec.getSize(heightMeasureSpec)हो जाएगा 0और अपने viewSideRatioमें परिणाम होगा Infinity(आश्चर्य करने की कोई जरूरत, जावा नाव इस तरह के मूल्यों की अनुमति देता है।) इस मामले में दोनों अपने heightऔर widthहो जाएगा 0
एलेक्स सेमिनेक

1
मेरे लिए भरण कार्य करने के लिए मुझे स्वैप करने की आवश्यकता है (imageSideRatio> = viewSideRatio) से (imageSideRatio <viewSideRatio) .. अन्यथा एक अच्छा उत्तर
मारेक हेल्मो

23

का उपयोग करें android:scaleType="centerCrop"


ठीक वैसा नहीं, जैसा सवाल पूछ रहा था, लेकिन वास्तव में मुझे क्या चाहिए!
निकम्मा

क्या आप @Jameson को विस्तृत कर सकते हैं? क्या आपका मतलब है Android वर्जन?
मिक

अगर मैं सेंटरक्रॉप का उपयोग करता हूं, तो छवि थोड़ा ऊपर और नीचे कट जाती है।
श्रीकांत करुमनघाट

9

मैंने उपरोक्त के समान कुछ किया और फिर कुछ घंटों के लिए दीवार के खिलाफ अपना सिर पीट लिया क्योंकि यह अंदर काम नहीं करता था RelativeLayout। मैं निम्नलिखित कोड के साथ समाप्त हुआ:

package com.example;

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.ImageView;

public class ScaledImageView extends ImageView {
    public ScaledImageView(final Context context, final AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
        final Drawable d = getDrawable();

        if (d != null) {
            int width;
            int height;
            if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY) {
                height = MeasureSpec.getSize(heightMeasureSpec);
                width = (int) Math.ceil(height * (float) d.getIntrinsicWidth() / d.getIntrinsicHeight());
            } else {
                width = MeasureSpec.getSize(widthMeasureSpec);
                height = (int) Math.ceil(width * (float) d.getIntrinsicHeight() / d.getIntrinsicWidth());
            }
            setMeasuredDimension(width, height);
        } else {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    }
}

और फिर RelativeLayoutमापा आयाम की अनदेखी करने से रोकने के लिए मैंने ऐसा किया:

    <FrameLayout
        android:id="@+id/image_frame"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_below="@+id/something">

        <com.example.ScaledImageView
            android:id="@+id/image"
            android:layout_width="wrap_content"
            android:layout_height="150dp"/>
    </FrameLayout>

5

पहलू अनुपात रखने के लिए ImageView में इन गुणों का उपयोग करें:

android:adjustViewBounds="true"
android:scaleType="fitXY"

9
fitXY पहलू अनुपात नहीं रखता है। यह लेआउट की चौड़ाई और ऊंचाई को बिल्कुल फिट करने के लिए छवि को फैलाता है।
कार्ट

5

यह लागू नहीं होगा यदि आप ImageView में पृष्ठभूमि के रूप में चित्र सेट करते हैं, तो src (android: src) पर सेट करना होगा।

धन्यवाद।


5

चौड़ाई के साथ एक छवि बनाने के लिए स्क्रीन की चौड़ाई के बराबर होती है, और पहलू अनुपात के अनुसार आनुपातिक रूप से सेट की जाती है, निम्नलिखित करें।

Glide.with(context).load(url).asBitmap().into(new SimpleTarget<Bitmap>() {
                    @Override
                    public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {

                        // creating the image that maintain aspect ratio with width of image is set to screenwidth.
                        int width = imageView.getMeasuredWidth();
                        int diw = resource.getWidth();
                        if (diw > 0) {
                            int height = 0;
                            height = width * resource.getHeight() / diw;
                            resource = Bitmap.createScaledBitmap(resource, width, height, false);
                        }
                                              imageView.setImageBitmap(resource);
                    }
                });

उम्मीद है की यह मदद करेगा।


यह सबसे अच्छा जवाब है जो मैंने पाया, मैं 2 दिनों के लिए खोज कर रहा हूं, धन्यवाद फातिमा
कार्तिक रामनाथन


4

यो को किसी जावा कोड की आवश्यकता नहीं है। बस तुम्हें यह करना होगा :

<ImageView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:adjustViewBounds="true"
    android:scaleType="centerCrop" />

कुंजी चौड़ाई और ऊंचाई के लिए मैच पैरेंट में है


CenterCrop वास्तव में छवि के कुछ हिस्से को काट देता है।
श्रीकांत करुमनघाट

2

इस सरल रेखा के साथ प्रयास करें ... इस लाइन को अपने xml कोड में छवि दृश्य टैग में किसी भी निर्भरता एंड्रॉइड को जोड़ने के साथ जोड़ें: scaleType = "fitXY"


fitXY पहलू अनुपात को बनाए नहीं रखता है, इसलिए छवि की संभावना बढ़ जाएगी
ProjectDelta

2

android का उपयोग करें: ScaleType = "fitXY" im ImageView xml


fitXY पहलू अनुपात को बनाए नहीं रखता है, इसलिए छवि की संभावना बढ़ जाएगी
ProjectDelta

1

आप छवियों को मैन्युअल रूप से लोड करके क्या कर रहे हैं यह करने की कोशिश कर सकते हैं, लेकिन मैं बहुत दृढ़ता से यूनिवर्सल इमेज लोडर पर एक नज़र डालने की सलाह दूंगा

मैंने हाल ही में इसे अपनी परियोजना में एकीकृत किया है और मुझे इसका शानदार कहना है। क्या चीजें आपके लिए अतुल्यकालिक, आकार बदलने, कैशिंग छवियों को बनाने के बारे में चिंता करती हैं। इसे एकीकृत करना और स्थापित करना वास्तव में आसान है। 5 मिनट के भीतर आप शायद वही कर पाएं जो आप चाहते हैं।

उदाहरण कोड:

//ImageLoader config
DisplayImageOptions displayimageOptions = new DisplayImageOptions.Builder().showStubImage(R.drawable.downloadplaceholder).cacheInMemory().cacheOnDisc().showImageOnFail(R.drawable.loading).build();

    ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getApplicationContext()).
            defaultDisplayImageOptions(displayimageOptions).memoryCache(new WeakMemoryCache()).discCache(new UnlimitedDiscCache(cacheDir)).build();

    if (ImageLoader.getInstance().isInited()) {
        ImageLoader.getInstance().destroy();
    }
    ImageLoader.getInstance().init(config);

    imageLoadingListener = new ImageLoadingListener() {
        @Override
        public void onLoadingStarted(String s, View view) {

        }

        @Override
        public void onLoadingFailed(String s, View view, FailReason failReason) {
            ImageView imageView = (ImageView) view;
            imageView.setImageResource(R.drawable.android);
            Log.i("Failed to Load " + s, failReason.toString());
        }

        @Override
        public void onLoadingComplete(String s, View view, Bitmap bitmap) {

        }

        @Override
        public void onLoadingCancelled(String s, View view) {

        }
    };

//Imageloader usage
ImageView imageView = new ImageView(getApplicationContext());
    if (orientation == 1) {
        imageView.setLayoutParams(new LinearLayout.LayoutParams(width / 6, width / 6));
    } else {
        imageView.setLayoutParams(new LinearLayout.LayoutParams(height / 6, height / 6));
    }
    imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
    imageLoader.displayImage(SERVER_HOSTNAME + "demos" + demo.getPathRoot() + demo.getRootName() + ".png", imageView, imageLoadingListener);

यह छवियों को आलसी कर सकता है, उन्हें लोड करते समय प्लेसहोल्डर छवि दिखाते हुए imageView के आकार में सही ढंग से फिट कर देता है, और संसाधनों को लोड करने और विफल होने पर डिफ़ॉल्ट आइकन दिखा रहा है।

- मुझे यह भी जोड़ना चाहिए कि यह वर्तमान कॉन्फ़िगरेशन छवि पहलू अनुपात रखता है, इसलिए आपके मूल प्रश्न पर लागू होता है


0

बस UniversalImageLoader और सेट का उपयोग करें

DisplayImageOptions.Builder()
    .imageScaleType(ImageScaleType.EXACTLY_STRETCHED)
    .build();

और ImageView पर कोई स्केल सेटिंग्स नहीं


0

मेरे पास एक समान मुद्दा था, मुझे इसका कारण मिला क्योंकि आपको गणना की आवश्यकता है dpImageViewजब आप इसे लोड करते हैं , तो एंड्रॉइड स्टूडियो गणना कर रहा होता है drawable, लेकिन जब आप किसी अन्य विधि का उपयोग कर रहे होते हैं, जैसे कि बिटमैप से लोड करना , dpइसका कोई हिसाब नहीं है,

यहाँ मेरा xml है

<ImageView
  android:id="@+id/imageViewer"
  android:layout_width="match_parent"
  android:layout_height="match_parent"//dp is not automaticly updated, when loading from a other source
  android:scaleType="fitCenter"
  tools:srcCompat="@drawable/a8" />

मैं Kotlin का उपयोग कर रहा हूं, और एक एसेट फाइल से ड्रॉइंग लोड कर रहा हूं, यहां बताया गया है कि मैं इसकी गणना कैसे करता हूं

val d = Drawable.createFromStream(assets.open("imageData/${imageName}.png"), null)
bitHeight = d.minimumHeight//get the image height
imageViewer.layoutParams.height = (bitHeight * resources.displayMetrics.density).toInt()//set the height
imageViewer.setImageDrawable(d)//set the image from the drawable
imageViewer.requestLayout()//here I apply it to the layout

-1

पिकासो का उपयोग करें जो उपयोग करना आसान है ।।

अपने एडॉप्टर में ..

@Override
public void getView(int position, View convertView, ViewGroup parent) {

 ImageView view = (ImageView) convertView.findViewById(R.id.ranking_prod_pic);

 Picasso.with(context).load(url).into(view); //url is image url

 //you can resize image if you want

 /* Picasso.with(context) .load(url) .resize(50, 50) .centerCrop() .into(view) */

}

http://square.github.io/picasso/ यहां छवि विवरण दर्ज करें

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.