Android: एक चित्र या पृष्ठभूमि छवि स्केल करें?


134

एक लेआउट पर मैं पृष्ठ बनाया जाता है जब आवंटित की गई पृष्ठभूमि की छवि (इसके पहलू अनुपात को ध्यान में रखते हुए) को स्केल करना चाहता हूं। किसी को भी यह कैसे करना है एक विचार है?

मैं क्लिपिंग और फिलिंग के लिए उपयोग कर रहा हूं layout.setBackgroundDrawable()और BitmapDrawable()सेट कर रहा हूं gravity, लेकिन स्केलिंग के लिए कोई विकल्प नहीं देखता।


मेरे पास यह समस्या थी और एक्यू द्वारा सुझाए गए बदलाव के साथ ड्वेबो की सिफारिश का पालन किया: फिटकेंटर को फिटकैंटर में बदल दिया। अच्छा काम किए।

जवाबों:


90

पृष्ठभूमि छवि स्केलिंग को अनुकूलित करने के लिए इस तरह से एक संसाधन बनाएं:

<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
    android:gravity="center"
    android:src="@drawable/list_bkgnd" />

तब यह दृश्य में केंद्रित होगा यदि पृष्ठभूमि के रूप में उपयोग किया जाता है। अन्य झंडे भी हैं: http://developer.android.com/guide/topics/resource/drawable-resource.html


6
मैंने बिटमैप का उपयोग करने की कोशिश की, लेकिन छवि बस केंद्रित है, नहीं स्केल के रूप में सैम पूछ रहा है। जब मैं ImageView का उपयोग करता हूं, तो यह खूबसूरती से काम करता है, कोई मुस / फस नहीं। (नायब: मैं भी अपने मामले में स्क्रॉल नहीं कर रहा हूं।) छवि को स्केल करने के लिए मैं बिटमैप के साथ क्या वृद्धि करूंगा?
जो

7
संभावित मूल्य हैं: "शीर्ष" | "नीचे" | "छोड़ दिया" | "सही" | "center_vertical" | "fill_vertical" | "center_hor ट्रेलर" | "fill_horporary" | "केंद्र" | "भरें" | "clip_vertical" | "क्लिप_होर्टल"
एन।

30
इन मापदंडों में से कोई भी बिटमैप को स्केल नहीं करता है, यह पहलू राशन रखकर है, इसलिए उत्तर गलत है।
मलयासीज

7
प्रिय Malachiasz, 'केंद्र' पहलू अनुपात का सम्मान करता है। लेकिन यह इमेज को स्केल नहीं करेगा। जिसका मतलब है कि यह उपयोग करने के लिए कुछ हद तक खतरा है। लक्ष्य के रिज़ॉल्यूशन के आधार पर आप कभी नहीं जान पाएंगे कि बात कितनी सही है। Google द्वारा एक और आधा-समाधान।

2
स्केल टाइप विशेषता जोड़ने का एक तरीका है?
ademar111190

57

जैसा आप चाहते हैं वैसा करने की कोशिश नहीं की गई है, लेकिन आप एक ImageView पैमाने का उपयोग कर सकते हैं android:scaleType="fitXY"
और यह जिस भी आकार में आप ImageView देते हैं उसमें फिट होने के लिए आकार होगा।

तो आप अपने लेआउट के लिए एक फ्रेम-आउट बना सकते हैं, इसके अंदर ImageView डाल सकते हैं, और फिर फ़्रेमलैयआउट में आपको जो भी अन्य सामग्री की आवश्यकता होती है, वह w / पारदर्शी पृष्ठभूमि है।

<FrameLayout  
android:layout_width="fill_parent" android:layout_height="fill_parent">

  <ImageView 
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:src="@drawable/back" android:scaleType="fitXY" />

  <LinearLayout>your views</LinearLayout>
</FrameLayout>

1
क्या किसी सरफेस पर ऐसा करना संभव है। यदि नहीं, तो क्या मैं FrameLayout का उपयोग करके पूर्वावलोकन (एक रिकॉर्डर ऐप के लिए) दिखा सकता हूं?
नम्रता

1
@dweebo: क्या आपने यह कोशिश की है? यह मेरे लिए काम करने लगता नहीं है।
स्पीडप्लेन

3
एक के बजाय दो यूआई घटकों का उपयोग करने के बाद से डाउनवोट किया गया, विशेष रूप से लिस्टव्यू जैसे व्यस्त घटकों के लिए एक बुरा विचार है। सबसे अधिक संभावना है कि आपको स्क्रॉल करते समय परेशानी होगी। उचित समाधान: stackoverflow.com/a/9362168/145046
एलेक्स एन।

मैंने फिटकेंटर और सेंटरक्रॉप के पैमाने की कोशिश की (साथ ही विभिन्न घनत्वों के लिए ड्राबल / छवि के कुछ रूपों के साथ) और यह काम किया! मेरे लिए या तो स्केल टाइप समझदारी है - छवि के आधार पर व्यक्तिगत प्राथमिकता, मुझे संदेह है। ध्यान दें कि मैंने फ्रेमलैट के बजाय मर्ज का उपयोग किया है, और मेरे विशेष मामले में कोई स्क्रॉलिंग नहीं है।
जो

2
सेंटर इनसाइड उचित है, फिटएक्सवाई नहीं, क्योंकि फिटएक्सवाई छवि का पहलू अनुपात नहीं रखता है
मैलाकियास

35

ड्रॉबल से ऐसा करने का एक आसान तरीका है:

your_drawable.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >

    <item android:drawable="@color/bg_color"/>
    <item>
        <bitmap
            android:gravity="center|bottom|clip_vertical"
            android:src="@drawable/your_image" />
    </item>

</layer-list>

केवल नकारात्मक पक्ष यह है कि यदि पर्याप्त जगह नहीं है, तो आपकी छवि पूरी तरह से दिखाई नहीं देगी, लेकिन यह क्लिप किया जाएगा, मुझे सीधे एक ड्रॉबल से ऐसा करने का तरीका नहीं मिल सकता है। लेकिन परीक्षणों से मैंने यह बहुत अच्छी तरह से काम किया है, और यह छवि के उस हिस्से को क्लिप नहीं करता है। आप गुरुत्वाकर्षण विकल्पों के साथ अधिक खेल सकते हैं।

एक और तरीका सिर्फ एक लेआउट बनाना होगा, जहां आप एक का उपयोग करेंगे ImageViewऔर करने के scaleTypeलिए सेट करेंगेfitCenter


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

1
यह त्रुटि दिखाता है:error: <item> must have a 'name' attribute.
दिमित्री

thx @lonutNegru, +1 मेरे दिन को बचाने के लिए :)
रवि वानिया

18

पहलू अनुपात रखने के लिए आपको उपयोग करना है android:scaleType=fitCenterया fitStartआदि का उपयोग करना हैfitXY छवि के मूल पहलू अनुपात रखना नहीं होगा!

ध्यान दें कि यह केवल एक srcविशेषता वाली छवियों के लिए काम करता है , न कि पृष्ठभूमि छवि के लिए।


18

लेआउट के लिए पृष्ठभूमि के आकार के रूप में छवि का उपयोग करें:

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

    <ImageView
        android:id="@+id/imgPlaylistItemBg"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:adjustViewBounds="true"
        android:maxHeight="0dp"
        android:scaleType="fitXY"
        android:src="@drawable/img_dsh" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical" >


    </LinearLayout>

</FrameLayout>

धन्यवाद! भी android:scaleType="centerCrop"काम करता है।
कूलमाइंड

5

जब आप setBackgroundDrawableविधि का उपयोग करके किसी छवि दृश्य का चित्रण सेट करते हैं , तो छवि हमेशा स्केल की जाएगी। के रूप में adjustViewBoundsया अलग मापदंडों को ScaleTypesबस नजरअंदाज कर दिया जाएगा। पहलू अनुपात जो मैंने पाया, उसका एकमात्र उपाय यह है कि ImageViewआपके ड्रॉबल को लोड करने के बाद उसका आकार बदलें । यहाँ कोड स्निपेट का उपयोग किया गया है:

// bmp is your Bitmap object
int imgHeight = bmp.getHeight();
int imgWidth = bmp.getWidth();
int containerHeight = imageView.getHeight();
int containerWidth = imageView.getWidth();
boolean ch2cw = containerHeight > containerWidth;
float h2w = (float) imgHeight / (float) imgWidth;
float newContainerHeight, newContainerWidth;

if (h2w > 1) {
    // height is greater than width
    if (ch2cw) {
        newContainerWidth = (float) containerWidth;
        newContainerHeight = newContainerWidth * h2w;
    } else {
        newContainerHeight = (float) containerHeight;
        newContainerWidth = newContainerHeight / h2w;
    }
} else {
    // width is greater than height
    if (ch2cw) {
        newContainerWidth = (float) containerWidth;
        newContainerHeight = newContainerWidth / h2w; 
    } else {
        newContainerWidth = (float) containerHeight;
        newContainerHeight = newContainerWidth * h2w;       
    }
}
Bitmap copy = Bitmap.createScaledBitmap(bmp, (int) newContainerWidth, (int) newContainerHeight, false);
imageView.setBackgroundDrawable(new BitmapDrawable(copy));
LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
imageView.setLayoutParams(params);
imageView.setMaxHeight((int) newContainerHeight);
imageView.setMaxWidth((int) newContainerWidth);

कोड में ऊपर झलकी है bmp बिटमैप वस्तु दिखाया जा रहा है कि और imageView है ImageViewवस्तु

ध्यान देने वाली एक महत्वपूर्ण बात लेआउट मापदंडों का परिवर्तन है । यह आवश्यक है क्योंकि setMaxHeightऔर setMaxWidthकेवल तभी फर्क पड़ेगा जब सामग्री को लपेटने के लिए चौड़ाई और ऊंचाई को परिभाषित किया जाता है, न कि माता-पिता को भरने के लिए। दूसरी ओर माता-पिता को भरें शुरुआत में वांछित सेटिंग है, क्योंकि अन्यथा containerWidthऔर containerHeightदोनों में 0 के बराबर मान होंगे। इसलिए, आपके लेआउट फ़ाइल में आपके ImageView के लिए कुछ इस तरह होगा:

...
<ImageView android:id="@+id/my_image_view"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"/>
...

4

यह सबसे बेहतर समाधान नहीं है, लेकिन जैसा कि किसी ने पृष्ठभूमि के बजाय सुझाव दिया है कि आप फ्रेमलेयआउट या रिलेटिवलैट बना सकते हैं और ImageView को छद्म पृष्ठभूमि के रूप में उपयोग कर सकते हैं - अन्य तत्व इसके ठीक ऊपर की स्थिति में होंगे:

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

    <ImageView
        android:id="@+id/ivBackground"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:scaleType="fitStart"
        android:src="@drawable/menu_icon_exit" />

    <Button
        android:id="@+id/bSomeButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="61dp"
        android:layout_marginTop="122dp"
        android:text="Button" />

</RelativeLayout>

ImageView के साथ समस्या यह है कि केवल उपलब्ध पैमाने हैं: CENTER, CENTER_CROP, CENTER_INSIDE, FIT_CENTER, FIT_END, FIT_START, FIT_XY, MATRIX ( http://etcodehome.blogspot.de/2011/05/android-imcalview.scalview) )

और कुछ मामलों में, जब आप पूरी स्क्रीन (उदाहरण के लिए पृष्ठभूमि की छवि) और छवि का पहलू अनुपात छवि को भरने के लिए अलग-अलग चाहते हैं, तो "स्केल बैकग्राउंड इमेज (इसके पहलू अनुपात को ध्यान में रखते हुए) को स्केल करना आवश्यक है। TOP_CROP की, क्योंकि:

CENTER_CROP छवि के शीर्ष किनारे के शीर्ष किनारे को संरेखित करने के बजाय स्केल की गई छवि को केंद्र में रखता है और FIT_START स्क्रीन की ऊँचाई को फिट करता है और चौड़ाई को नहीं भरता है। और उपयोगकर्ता Anke के रूप में देखा FIT_XY पहलू अनुपात नहीं रखता है।

ख़ुशी की बात है कि किसी ने TOP_CROP का समर्थन करने के लिए ImageView को बढ़ाया है

public class ImageViewScaleTypeTopCrop extends ImageView {
    public ImageViewScaleTypeTopCrop(Context context) {
        super(context);
        setup();
    }

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

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

    private void setup() {
        setScaleType(ScaleType.MATRIX);
    }

    @Override
    protected boolean setFrame(int frameLeft, int frameTop, int frameRight, int frameBottom) {

        float frameWidth = frameRight - frameLeft;
        float frameHeight = frameBottom - frameTop;

        if (getDrawable() != null) {

            Matrix matrix = getImageMatrix();
            float scaleFactor, scaleFactorWidth, scaleFactorHeight;

            scaleFactorWidth = (float) frameWidth / (float) getDrawable().getIntrinsicWidth();
            scaleFactorHeight = (float) frameHeight / (float) getDrawable().getIntrinsicHeight();

            if (scaleFactorHeight > scaleFactorWidth) {
                scaleFactor = scaleFactorHeight;
            } else {
                scaleFactor = scaleFactorWidth;
            }

            matrix.setScale(scaleFactor, scaleFactor, 0, 0);
            setImageMatrix(matrix);
        }

        return super.setFrame(frameLeft, frameTop, frameRight, frameBottom);
    }

}

https://stackoverflow.com/a/14815588/2075875

अब IMHO सही होगा अगर किसी ने कस्टम ड्रॉबल लिखा है जो उस तरह की छवि को मापता है। तब इसे बैकग्राउंड पैरामीटर के रूप में इस्तेमाल किया जा सकता था।


Reflog का उपयोग करने से पहले drawable को निर्धारित करने का सुझाव देता है। यहाँ निर्देश है कि यह कैसे करना है: जावा (एंड्रॉइड): बिटमैप के बिना ड्रॉबल को कैसे स्केल किया जाए? हालांकि इसका नुकसान है, कि अपकेंद्रित ड्रॉबल / बिटमैप अधिक रैम का उपयोग करेगा, जबकि ImageView द्वारा उपयोग किए जाने वाले मक्खी पर स्केलिंग के लिए अधिक मेमोरी की आवश्यकता नहीं होती है। लाभ कम प्रोसेसर लोड हो सकता है।


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

4

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

int bwidth=bitMap1.getWidth();
int bheight=bitMap1.getHeight();
int swidth=imageView_location.getWidth();
int sheight=imageView_location.getHeight();
new_width=swidth;
new_height = (int) Math.floor((double) bheight *( (double) new_width / (double) bwidth));
Bitmap newbitMap = Bitmap.createScaledBitmap(bitMap1,new_width,new_height, true);
imageView_location.setImageBitmap(newbitMap)

2

क्या Dweebo प्रस्तावित काम करता है। लेकिन मेरी विनम्र राय में यह अनावश्यक है। एक बैकग्राउंड ड्रिबल स्कैल्स खुद से। दृश्य में निश्चित चौड़ाई और ऊंचाई होनी चाहिए, जैसे निम्नलिखित उदाहरण में:

 < RelativeLayout 
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@android:color/black">

    <LinearLayout
        android:layout_width="500dip"
        android:layout_height="450dip"
        android:layout_centerInParent="true"
        android:background="@drawable/my_drawable"
        android:orientation="vertical"
        android:padding="30dip"
        >
        ...
     </LinearLayout>
 < / RelativeLayout>

2
मेरी समझ यह है कि किसी दृश्य को भरने के लिए एक पृष्ठभूमि का विस्तार होगा, लेकिन सिकुड़ना नहीं।
एडवर्ड फॉक

1

कोशिश करने का एक विकल्प यह है कि छवि को drawable-nodpiफ़ोल्डर में रखा जाए और लेआउट के बैकग्राउंड को ड्रॉबल रिसोर्स आईडी में सेट किया जाए।

यह निश्चित रूप से स्केलिंग के साथ काम करता है, हालांकि मैंने स्केलिंग के साथ परीक्षण नहीं किया है।


0

Kotlin:

यदि आपको दृश्य में एक बिटमैप आकर्षित करने की आवश्यकता है, तो FIT में स्केल किया गया।

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

इमेजिस:

उदाहरण चित्र 1

उदाहरण चित्र 2

// binding.fragPhotoEditDrawCont is the RelativeLayout where is your view
// bm is the Bitmap
val ch = binding.fragPhotoEditDrawCont.height
val cw = binding.fragPhotoEditDrawCont.width
val bh = bm.height
val bw = bm.width
val rc = cw.toFloat() / ch.toFloat()
val rb = bw.toFloat() / bh.toFloat()

if (rb < rc) {
    // Bitmap Width to Height ratio is less than Container ratio
    // Means, bitmap should pin top and bottom, and have some space on sides.
    //              _____          ___
    // container = |_____|   bm = |___| 
    val bmHeight = ch - 4 //4 for container border
    val bmWidth = rb * bmHeight //new width is bm_ratio * bm_height
    binding.fragPhotoEditDraw.layoutParams = RelativeLayout.LayoutParams(bmWidth.toInt(), bmHeight)
}
else {
    val bmWidth = cw - 4 //4 for container border
    val bmHeight = 1f/rb * cw
    binding.fragPhotoEditDraw.layoutParams = RelativeLayout.LayoutParams(bmWidth, bmHeight.toInt())
}

-4

इससे पहले कि आप इसे पृष्ठभूमि के रूप में उपयोग कर सकें, आपको पहले से मापना होगा


क्या यह वास्तव में एकमात्र विकल्प है? क्या ImageView को रखने के लिए कोई प्रकार का कंटेनर नहीं है जिसमें प्रदर्शन आकार निर्दिष्ट कर सकते हैं?
GrkEngineer

मुझे सर्फेस व्यू
AZ_

3
IOS पर पहलू फिट, पहलू भरण, शीर्ष बाएँ, शीर्ष आदि जैसा कुछ नहीं है? वह बेकार है ..
Maciej Swic

जैसा @Aleksej ने कहा, एक असत्य उत्तर।
शिक्षार्थी

-5

आप निम्न में से किसी एक का उपयोग कर सकते हैं:

एंड्रॉयड: गुरुत्वाकर्षण = "fill_horizontal | clip_vertical"

या

एंड्रॉयड: गुरुत्वाकर्षण = "fill_vertical | clip_horizontal"

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