पिकासो के साथ पूर्ण चौड़ाई और चर ऊंचाई के लिए छवि का आकार बदलें


84

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

मैंने इस प्रश्न की जाँच की है: पिकासो के साथ पूर्ण चौड़ाई और निश्चित ऊँचाई पर छवि का आकार बदलें

fit()काम करता है, लेकिन मैं तस्वीर का पहलू अनुपात रखने के लिए कुछ भी नहीं है नहीं मिली है।

यह कोड आंशिक रूप से काम करता है अगर मैंने एडेप्टर के लेआउट में ऊंचाई तय की है:

Picasso.with(this.context).load(message_pic_url)
.placeholder(R.drawable.profile_wall_picture)
.fit().centerInside()
.into(holder.message_picture);

लेकिन यह सूची दृश्य के चित्रों के बीच रिक्त स्थान उत्पन्न करता है क्योंकि चित्र ऐसा हो सकता है कि उसमें ऊँचाई न हो।

अग्रिम में धन्यवाद।

जवाबों:


89

पिकासो 2.4.0 के रूप में, यह ऑपरेशन अब सीधे समर्थित है । बस एक .resize()आयाम के साथ एक अनुरोध जोड़ें 0। उदाहरण के लिए, एक चर चौड़ाई होने के लिए, आपका कॉल बन जाएगा:

Picasso.with(this.context)
       .load(message_pic_url)
       .placeholder(R.drawable.profile_wall_picture)
       .resize(0, holder.message_picture.getHeight()),
       .into(holder.message_picture);

ध्यान दें कि यह कॉल उपयोग करता है .getHeight()और इसलिए मानता है message_pictureकि पहले से ही मापा जा चुका है। यदि ऐसा नहीं है, जैसे कि जब आपने एक नया दृश्य इनकाउंटर किया है ListAdapter, तो आप इस कॉल को देरी OnGlobalLayoutListenerसे देखने के बाद जोड़कर माप कर सकते हैं:

holder.message_picture.getViewTreeObserver()
      .addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            // Wait until layout to call Picasso
            @Override
            public void onGlobalLayout() {
                // Ensure we call this only once
                imageView.getViewTreeObserver()
                         .removeOnGlobalLayoutListener(this);


                Picasso.with(this.context)
                       .load(message_pic_url)
                       .placeholder(R.drawable.profile_wall_picture)
                       .resize(0, holder.message_picture.getHeight())
                       .into(holder.message_picture);
            }
        });

8
इस समाधान से मुझे java.lang.IllegalArgumentException: At least one dimension has to be positive number.रोटेशन पर त्रुटि प्राप्त होती है, यह टुकड़े में है, किसी भी विचार के साथ कि ऐसा क्यों हो सकता है?
लुकाज़ 'सेवेरियन' ग्रीला

1
हम, अगर मैं इस जांच को जोड़
दूं

2
@ Lukasz'Severiaan'Grela मुझे भी यही समस्या थी। मूल प्रश्न से मेल खाने के लिए इस उदाहरण को ठीक करने के लिए आपको दलीलें .resize(holder.message_picture.getWidth(), 0)
क्रिश्चियन

4
आपने मुझे आइडिया दिया। धन्यवाद। उन लोगों के लिए जो चर ऊंचाई के साथ पूरी चौड़ाई की छवि चाहते हैं, का उपयोग करें: Display display = getWindowManager().getDefaultDisplay(); Point size = new Point(); display.getSize(size); int width = size.x; .resize(width, 0)
fahrulazmi

1
मैंने इस पद्धति का उपयोग किया, जब आप ऐप को पृष्ठभूमि में ले जाते हैं और वापस आते हैं, तो onGlobalLayout()इसे नहीं बुलाया जाता है और छवि दिखाई नहीं देगी।
गोखान अरीक

82

मैं एक ही मुद्दे पर आया था और मुझे एक समाधान को ट्रैक करने में थोड़ा समय लगा लेकिन मैं आखिरकार मेरे लिए काम कर रहा था।

सबसे पहले मैंने पिकासो कॉल को बदल दिया

Picasso.with(this.context).load(message_pic_url)
.placeholder(R.drawable.profile_wall_picture)
.into(holder.message_picture);

fitऔर हटाना centerInside। आगे आपको अपने XML में निम्नलिखित पंक्तियों को ImageView में जोड़ना होगा

android:scaleType="fitStart"
android:adjustViewBounds="true"

उम्मीद है कि यह आपके लिए भी काम करेगा।


2
धन्यवाद, लेकिन यह मेरे लिए काम नहीं करता है। मैं तस्वीरों को नहीं देख सकता, बिटमैप के आकार के बारे में लॉगकैट चेतावनी (क्लासिक संदेश: 2048x2048 अधिकतम आकार है)।
वेंडीगो

4
ऐसा सुनने के लिए क्षमा करें। यह इस पद्धति की खामी होगी। छवि को आकार देने के लिए इसे पिकासो नहीं मिल रहा है, बस इसे पूर्ण आकार में लोड करें। स्मृति समस्याओं का कारण बन सकता है।
drspaceboo

आपका बहुत बहुत धन्यवाद। यह एक आकर्षण की तरह काम करता है, जल्दी और आसानी से;)
फू

@drspaceboo आपकी layout_widthऔर layout_heightImageView पर क्या है ? मैं के साथ match_parentऔर wrap_contentक्रमशः कोशिश कर रहा हूँ, लेकिन यह काम नहीं करता है :(
विक्की चिजवानी

स्मृति से @VickyChijwani मुझे लगता है कि मैं था 0dpऔर match_parentके भार के साथ 1नहीं बल्कि 100% यकीन है कि और मुझे नहीं लगता कि हम किसी भी अधिक हमारे आवेदन में यह है।
drspaceboo

60

अंत में मैंने इसे पिकासो के एक परिवर्तन को हल किया, यहाँ स्निपेट है:

    Transformation transformation = new Transformation() {

        @Override
        public Bitmap transform(Bitmap source) {
            int targetWidth = holder.message_picture.getWidth();

            double aspectRatio = (double) source.getHeight() / (double) source.getWidth();
            int targetHeight = (int) (targetWidth * aspectRatio);
            Bitmap result = Bitmap.createScaledBitmap(source, targetWidth, targetHeight, false);
            if (result != source) {
                // Same bitmap is returned if sizes are the same
                source.recycle();
            }
            return result;
        }

        @Override
        public String key() {
            return "transformation" + " desiredWidth";
        }
    };

    mMessage_pic_url = message_pic_url;

    Picasso.with(this.context)
        .load(message_pic_url)
        .error(android.R.drawable.stat_notify_error)
        .transform(transformation)
        .into(holder.message_picture, new Callback() {
            @Override
            public void onSuccess() {
                holder.progressBar_picture.setVisibility(View.GONE);
            }

            @Override
            public void onError() {
                Log.e(LOGTAG, "error");
                holder.progressBar_picture.setVisibility(View.GONE);
            }
    });

यह पंक्ति आपकी इच्छित चौड़ाई के साथ अनुकूलित करने के लिए है:

int targetWidth = holder.message_picture.getWidth();

इसके अतिरिक्त इस स्निप में छिपाई हुई अंतर्निहित पिकासो को लोड करने की त्रुटि और त्रुटि के लिए कॉलबैक शामिल है।

यदि आपको किसी त्रुटि को डीबग करने के लिए अधिक जानकारी की आवश्यकता है, तो आपको कस्टम श्रोता (पिकासो बिल्डर) को लागू करना होगा क्योंकि onError Callbackजानकारी "शून्य" है। आप केवल यह जानते हैं कि UI व्यवहार के लिए कोई त्रुटि है।

मुझे उम्मीद है कि यह किसी को कई घंटे बचाने में मदद करता है।


ऐसा लगता है कि आप केवल स्रोत को पुन: चक्रित कर रहे हैं यदि यह परिणाम के समान है। क्या आप इसकी परवाह किए बिना इसे रीसायकल करना चाहेंगे और परिणाम को वापस करेंगे?
वेंगर

यदि आप ऐसा करते हैं, तो दूत, नहीं, पिकासो शिकायत करते हैं।
जॉर्ज हिलियार्ड

महान!! वास्तव में महान
एलओजकर 16

हां, यह काम किया। लेकिन mycase में मुझे match_parent, या एक विशिष्ट चौड़ाई के लिए ImageView चौड़ाई सेट करनी थी। "wra_content" परिवर्तन में 0 (शून्य) देता है, और एक अपवाद उठाता है।
क्रोधितगीत

स्क्रॉल करते समय, कभी-कभी holder.message_picture.getWidth()0 लौटता है और यह एक त्रुटि का कारण बनता है width and height must be > 0। किसी भी विचार कैसे इस त्रुटि को ठीक करने के लिए?
शैडल उल हसन

9

हो सकता है कि स्वीकृत उत्तर सभी के लिए उपयोगी हो, लेकिन यदि आप एक से अधिक के ViewHolderलिए कई बाइंडिंग कर रहे हैं, Viewsतो आप परिवर्तन के लिए क्लास क्रिएट करके और ImageView से पास करके अपने कोड को कम कर सकते हैं ViewHolder

/**
 * Created by Pratik Butani
 */
public class ImageTransformation {

    public static Transformation getTransformation(final ImageView imageView) {
        return new Transformation() {

            @Override
            public Bitmap transform(Bitmap source) {
                int targetWidth = imageView.getWidth();

                double aspectRatio = (double) source.getHeight() / (double) source.getWidth();
                int targetHeight = (int) (targetWidth * aspectRatio);
                Bitmap result = Bitmap.createScaledBitmap(source, targetWidth, targetHeight, false);
                if (result != source) {
                    // Same bitmap is returned if sizes are the same
                    source.recycle();
                }
                return result;
            }

            @Override
            public String key() {
                return "transformation" + " desiredWidth";
            }
        };
    }
}

से कॉलिंग ViewHolder:

Picasso.with(context).load(baseUrlForImage)
                     .transform(ImageTransformation.getTransformation(holder.ImageView1))
                     .error(R.drawable.ic_place_holder_circle)
                     .placeholder(R.drawable.ic_place_holder_circle)
                     .into(holder.mMainPhotoImageView1);

आशा है इससे आपकी मदद होगी।


धन्यवाद, ImageView के लिए महान समाधान, एक सवाल: क्या हम VideoView आकार के लिए ऐसा कर सकते हैं जैसा कि ImageView पैरामीटर में पारित हुआ है?
व्रजेश

@Pratik मैं recyclerview है और जब तेजी से स्क्रॉल किया जाता है, तो मुझे अपवाद मिला: परिवर्तन परिवर्तन वांछित वांछित अपवाद के साथ दुर्घटनाग्रस्त हो गया। इसके कारण: java.lang.IllegalArgumentException: चौड़ाई और ऊंचाई> 0
व्रजेश

स्क्रॉल करते समय, कभी-कभी imageView.getWidth()0 लौटता है और यह एक त्रुटि का कारण बनता है width and height must be > 0। किसी भी विचार कैसे इस त्रुटि को ठीक करने के लिए?
शैडल उल हसन

उस स्थिति में, आपकी छवि url शून्य हो सकती है, इसलिए इसे पहले जांचें कि अशक्त है या नहीं।
प्रतिका बुटानी

3
    Picasso.with(this).load(url).resize(1800, 1800).centerInside().into(secondImageView)

    <ImageView
        android:id="@+id/SecondImage"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:layout_alignParentLeft="true"
        android:adjustViewBounds="true"
        android:layout_margin="10dp"
        android:visibility="gone"/>

यह आपको सभी उपकरणों के लिए छवियों की चर ऊंचाई के साथ मदद करेगा


0

मैंने सरल सहायक लिखा है जो लेआउट पूर्ण श्रोता को जोड़ने और लेआउट प्रक्रिया पूरी होने पर (छवि दृश्य) में कॉल करने के बारे में ध्यान रखता है।

public class PicassoDelegate {

private RequestCreator mRequestCreator;

public PicassoDelegate(ImageView target, RequestCreator requestCreator) {
    if (target.getWidth() > 0 && target.getHeight() > 0) {
        complete(target, requestCreator);
    } else {
        mRequestCreator = requestCreator;
        target.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
            @Override
            public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
                v.removeOnLayoutChangeListener(this);
                complete((ImageView) v, mRequestCreator);
            }
        });

    }

}

private void complete(ImageView target, RequestCreator requestCreator) {
    if (target.getWidth() > 0 && target.getHeight() > 0) {
        requestCreator.resize(target.getWidth(), target.getHeight());
    }

    requestCreator.into(target);
}

}

तो आप आसानी से इसे इस तरह से उपयोग कर सकते हैं उदाहरण के लिए अंश में onViewCreated ()

new PicassoDelegate(customerPhoto, Picasso.with(getActivity()).load(user.getPhotoUrl()).centerCrop());

0
imageView.post(new Runnable() {
      @Override public void run() {
        Picasso.with(context)
            .resize(0, imageView.getHeight())
            .onlyScaleDown()
            .into(imageView, new ImageCallback(callback, null));
      }
    });

0
public class CropSquareTransformation implements Transformation {

  private int mWidth;
  private int mHeight;

  @Override public Bitmap transform(Bitmap source) {
    int size = Math.min(source.getWidth(), source.getHeight());

    mWidth = (source.getWidth() - size) / 2;
    mHeight = (source.getHeight() - size) / 2;

    Bitmap bitmap = Bitmap.createBitmap(source, mWidth, mHeight, size, size);
    if (bitmap != source) {
      source.recycle();
    }

    return bitmap;
  }

  @Override public String key() {
    return "CropSquareTransformation(width=" + mWidth + ", height=" + mHeight + ")";
  }

अधिक रूपांतरण: https://github.com/wasabeef/picasso-transformations


क्या होना चाहिए layout_widthऔर layout_heightका ImageViewइस मामले में?
शैडल उल हसन

0

ImageView का विस्तार करें, फिर निम्न की तरह ऑनमार्ट विधि को ओवरराइड करें

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

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

0

वास्तव में मैं CustomImageView में छवि लोड करते समय मिल रहा था जिसमें ज़ूम करने योग्य कार्यक्षमता थी

त्रुटि थी

java.lang.RuntimeException: Transformation transformation desiredWidth crashed with exception.

मैंने इसे स्वीकार किए गए उत्तर से दिए गए संपादन कोड द्वारा हल किया है मुझे अपने प्रदर्शन की अधिकतम चौड़ाई मिली जैसे कि मेरी छवि की चौड़ाई पहले से ही match_parent थी।

अगर (imgUrl.equals ("") {

        DisplayMetrics displayMetrics = new DisplayMetrics();
        ((Activity) context).getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
        int height = displayMetrics.heightPixels;
        int width = displayMetrics.widthPixels;

        Picasso.with(context).load(imgUrl)
                .transform(getTransformation(width, imageView))
                .into(imageView, new Callback() {
                    @Override
                    public void onSuccess() {
                        if (progressBar != null) {
                            progressBar.setVisibility(View.GONE);
                        }
                    }

                    @Override
                    public void onError() {
                        if (progressBar != null) {
                            progressBar.setVisibility(View.GONE);
                        }
                    }
                });
    }

    public static Transformation getTransformation(final int width, final ImageView imageView) {
        return new Transformation() {
            @Override
            public Bitmap transform(Bitmap source) {
                int targetWidth = width;
                double aspectRatio = (double) source.getHeight() / (double) source.getWidth();
                int targetHeight = (int) (targetWidth * aspectRatio);
                Bitmap result = Bitmap.createScaledBitmap(source, targetWidth, targetHeight, false);
                if (result != source) {
                    // Same bitmap is returned if sizes are the same
                    source.recycle();
                }
                return result;
            }

            @Override
            public String key() {
                return "transformation" + " desiredWidth";
            }
        };
    }

0
Picasso.get()
.load(message_pic_url)
.fit()
.centerCrop()
.placeholder(R.drawable.profile_wall_picture)
.into(holder.message_picture);

इस कोड को आज़माएं, मेरे लिए काम किया।


0
@Override
    protected void onResume() {
        super.onResume();

        imageView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                loadImageIfReady();
            }
        });

    }

    private void loadImageIfReady() {
        if (imageView.getMeasuredWidth() <= 0 || mPayload == null)
            this.finish();    // if not ready GTFO

        Picasso.with(this)
                    .load(mPayload)
                    .resize(imageView.getMeasuredWidth(), imageView.getMeasuredWidth())
                    .centerInside()
                    .into(imageView);


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