क्रॉपिंग या विरूपण के बिना लचीली ऊंचाई के साथ चौड़ाई के लिए एंड्रॉइड इमेज व्यू स्केल की छोटी छवि


79

अक्सर पूछा, कभी जवाब नहीं दिया (कम से कम एक प्रतिलिपि प्रस्तुत करने योग्य तरीके से नहीं)।

मेरे पास एक छवि है जिसमें एक छवि है जो दृश्य से छोटी है। मैं छवि को स्क्रीन की चौड़ाई में स्केल करना चाहता हूं और छवि के आनुपातिक रूप से सही ऊंचाई को दर्शाने के लिए ImageView की ऊंचाई को समायोजित करना चाहता हूं।

<ImageView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
/>

इसके परिणामस्वरूप छवि अपने मूल आकार (तब स्क्रीन की चौड़ाई) के किनारे पर हाशिये पर केंद्रित होती है। अच्छा नहीं।

तो मैंने जोड़ा

android:adjustViewBounds="true" 

समान प्रभाव, अच्छा नहीं। मैंने कहा

android:scaleType="centerInside"

समान प्रभाव, अच्छा नहीं। मैं बदल centerInsideगया fitCenter। समान प्रभाव, अच्छा नहीं। मैं बदल centerInsideगया centerCrop

android:scaleType="centerCrop"

अब, अंत में, छवि को स्क्रीन की चौड़ाई तक बढ़ाया जाता है - लेकिन ऊपर और नीचे से काट दिया गया! इसलिए मैं बदल centerCropगया fitXY

android:scaleType="fitXY"

अब छवि को स्क्रीन की चौड़ाई पर स्केल किया गया है, लेकिन y- अक्ष पर स्केल नहीं किया गया है, जिसके परिणामस्वरूप विकृत छवि है।

हटाने android:adjustViewBounds="true"का कोई प्रभाव नहीं है। android:layout_gravityजैसा कि कहीं और सुझाव दिया गया है, जोड़ना फिर से कोई प्रभाव नहीं है।

मैंने अन्य संयोजनों की कोशिश की है - कोई फायदा नहीं हुआ। तो, कृपया किसी को पता है:

आप स्क्रीन की चौड़ाई को भरने के लिए एक इमेज व्यू के XML को कैसे सेट करते हैं, संपूर्ण दृश्य को भरने के लिए एक छोटी छवि को स्केल करते हैं, छवि को विरूपण या क्रॉपिंग के बिना इसके पहलू अनुपात के साथ प्रदर्शित करते हैं?

संपादित करें: मैंने एक मनमाना संख्यात्मक ऊंचाई सेट करने का भी प्रयास किया। यह केवल centerCropसेटिंग के साथ एक प्रभाव है । यह दृश्य ऊंचाई के अनुसार छवि को लंबवत रूप से विकृत करेगा।


क्या आपने कोशिश की है android:scaleType="fitCenter"?
माइकल सीली

1
@ BrainSlugs83 मेरे पास है और यह मेरे लिए काम करता है, फिर भी। साथ ही, यह पूछने के लिए प्रश्न पूछा गया था कि पूछने वाले ने क्या प्रयास किया था। Snarkiness की कोई आवश्यकता नहीं है, विशेष रूप से सात महीने बाद यह पोस्ट नहीं किया गया था।
माइकल सीली

यह काम नहीं करता। -- निचे देखो; इसके अलावा, मैंने इसकी कोशिश की है और यह सत्यापित कर सकता है कि यह काम नहीं करता है (यदि आपने इसे आज़माया है और अलग-अलग परिणाम देखें, तो कृपया नीचे चर्चा करें और हमें दिखाएं कि हम क्या गलत कर रहे हैं - केवल यही निष्कर्ष निकल सकता है कि आपने गलत समझा है सवाल, या यह कोशिश नहीं की है)।
ब्रेनस्ल्गस83

जवाबों:


110

मैंने इसे एक जावा-वर्ग बनाकर हल किया है जिसे आप अपने लेआउट-फाइल में शामिल करते हैं:

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

अब, आप इसे अपनी लेआउट-फ़ाइल में अपनी कक्षा को जोड़कर उपयोग करते हैं:

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

4
+1 महान समाधान, नेक्सस 7 के लिए भी पूरी तरह से काम करता है। और सबसे अच्छी बात यह है कि यह ग्रहण में लेआउट संपादक के भीतर भी सही ढंग से काम करता है।
Ridcully

गैलेक्सी एस 4 पर काम करता है। ऐसा क्यों नहीं होना चाहिए :) THx
Malachiasz

धन्यवाद। महान समाधान। ऊंचाई पर आधारित समान करने के लिए आसान पर्याप्त संशोधन।
स्पीडिनोमैड्स

1
हां, लेकिन नहीं ... यह समाधान छवियों को धुंधला करता है। अगर मैं निश्चित ऊंचाई के साथ ImageView और फिटकटर का उपयोग करता हूं, तो छवि को धुंधला नहीं किया जाता है (लेकिन निश्चित ऊंचाई मेरे लिए कोई समाधान नहीं है)। ब्लोइंग से कैसे बचें?
गेलट्रूड

मैं हफ्तों, कुडोस के लिए इस समाधान की तलाश कर रहा था! मैं एक छवि को अपकेंद्रित करना चाहता हूं, लेकिन यह सही काम करता है
सोको

36

मुझे भी वैसी ही समस्या थी, जैसी आपकी। भिन्न भिन्न रूपों की कोशिश करने के 30 मिनट के बाद मैंने इस तरह से समस्या को हल किया। यह आपको लचीली ऊंचाई देता है , और पैरेंट चौड़ाई को समायोजित करता है

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

4
यहाँ पर KeyViewBounds
user3690202

@ user3690202 आप सही हैं, इसने मेरी समस्या को भी हल कर दिया। धन्यवाद
पार्थ पटेल

22

XML लेआउट मानक के भीतर कोई व्यवहार्य समाधान नहीं है।

डायनामिक छवि आकार पर प्रतिक्रिया करने का एकमात्र विश्वसनीय तरीका LayoutParamsकोड में उपयोग करना है।

निराश करना।


8
  android:scaleType="fitCenter"

एक पैमाने की गणना करें जो मूल src पहलू अनुपात को बनाए रखेगा, लेकिन यह भी सुनिश्चित करेगा कि src पूरी तरह से dst के अंदर फिट बैठता है। कम से कम एक अक्ष (एक्स या वाई) बिल्कुल फिट होगा। परिणाम dst के अंदर केंद्रित है।

संपादित करें:

यहां समस्या यह है कि layout_height="wrap_content"छवि का विस्तार करने की "अनुमति" नहीं है। आपको उस परिवर्तन के लिए एक आकार सेट करना होगा

  android:layout_height="wrap_content"

सेवा

  android:layout_height="100dp"  // or whatever size you want it to be

edit2:

ठीक काम करता है:

<ImageView
    android:id="@+id/imageView1"
    android:layout_width="match_parent"
    android:layout_height="300dp"
    android:scaleType="fitCenter"
    android:src="@drawable/img715945m" />

2
यह छवि के पहले संस्करण में परिणामित होता है: केंद्रित, क्षैतिज रूप से विस्तारित नहीं, दोनों तरफ हाशिये के साथ। अच्छा नहीं।
मुंडी

2
यह काम नहीं करता। यह सटीक ऊंचाई के साथ एक छवि में परिणत होता है, लेकिन क्षैतिज रूप से विस्तारित नहीं होता है। अच्छा नहीं। प्रश्न में मेरा संपादन भी देखें।
मुंडी

1
nasa.gov/images/content/715945main__NOB0093_4x3_516-387.jpg महत्वपूर्ण हिस्सा यह है कि यह नेक्सस 7 की स्क्रीन से छोटा लगता है।
मुंडी

2
अच्छा नहीं। मुझे ऊंचाई का पता नहीं है - यह गतिशील है। यह अप्रत्याशित विकृतियों के परिणामस्वरूप होगा। मेरे प्रश्न में संपादित यह पहले से ही शामिल है। क्षमा करें - लेकिन आपके प्रयासों के लिए धन्यवाद! Google पर शर्म आनी चाहिए!
मुंडी

1
मुझे पता था कि यह एक विकल्प है, लेकिन मैं एक XML समाधान की तलाश में था । फिर भी, आपको इसे अपने उत्तर में संपादित करना चाहिए। धन्यवाद!
मुंडी

8

यह मार्क मार्टिंसन के उत्कृष्ट समाधान के लिए एक छोटा सा जोड़ है।

यदि आपकी छवि की चौड़ाई इसकी ऊंचाई से बड़ी है, तो मार्क का समाधान स्क्रीन के ऊपर और नीचे जगह छोड़ देगा।

नीचे पहले चौड़ाई और ऊंचाई की तुलना करके इसे ठीक करता है: यदि छवि चौड़ाई> = ऊंचाई है, तो यह स्क्रीन की ऊंचाई से मेल खाने के लिए ऊंचाई को स्केल करेगा, और फिर पहलू अनुपात को संरक्षित करने के लिए चौड़ाई को स्केल करेगा। इसी तरह, यदि छवि ऊंचाई> चौड़ाई है, तो यह स्क्रीन की चौड़ाई से मेल खाने के लिए चौड़ाई को मापेगा और फिर पहलू अनुपात को संरक्षित करने के लिए ऊंचाई को स्केल करेगा।

दूसरे शब्दों में, यह ठीक से संतुष्ट करता है 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);
        }
    }
}

यह समाधान स्वचालित रूप से पोर्ट्रेट या लैंडस्केप मोड में काम करता है। आप इसे अपने लेआउट में उसी तरह संदर्भित करते हैं जैसे आप मार्क के समाधान में करते हैं। जैसे:

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

3

मैं उसी समस्या में भाग गया, लेकिन एक निश्चित ऊंचाई के साथ, छवि के मूल पहलू अनुपात को ध्यान में रखते हुए स्केल की गई चौड़ाई। मैंने इसे एक भारित रैखिक लेआउट के माध्यम से हल किया। आप अपनी आवश्यकताओं के लिए इसे संशोधित कर सकते हैं।

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

इस समाधान ने मेरे लिए बहुत काम किया। इसने मुझे मेरा ImageView को एक विशिष्ट ऊंचाई देने की अनुमति दी और इसके पहलू अनुपात को बनाए रखने के लिए ImageView को गतिशील रूप से समायोजित करने के लिए इसकी चौड़ाई है।
ल्यूक

0

मार्क मार्टिंसन के जवाब का कोटलिन संस्करण :

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

0

मार्क मैटिंसन के समाधान के लिए एक और अतिरिक्त। मैंने पाया कि मेरी कुछ छवियां दूसरों की तुलना में कम हो गई थीं। इसलिए मैंने कक्षा को संशोधित किया ताकि छवि को अधिकतम कारक द्वारा बढ़ाया जाए। यदि छवि धुँधली हुए बिना अधिकतम चौड़ाई पर स्केल होने के लिए बहुत छोटी है, तो यह अधिकतम सीमा से परे स्केलिंग को रोकता है।

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