एंड्रॉइड में प्रदर्शित किए बिना बिटमैप पर एक दृश्य परिवर्तित करना?


133

मैं समझाने की कोशिश करूँगा कि मुझे वास्तव में क्या करने की आवश्यकता है।

मेरे पास 3 अलग स्क्रीन हैं A, B, C। होमस्क्रीन को कहते हैं कि एक और स्क्रीन है जहां सभी 3 स्क्रीन बिटमैप को गैलरी दृश्य में प्रदर्शित किया जाना चाहिए और उपयोगकर्ता यह चुन सकता है कि वह किस दृश्य में जाना चाहता है।

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

तो, क्या मैं होमस्क्रीन से एक और गतिविधि को कॉल कर सकता हूं और इसे प्रदर्शित नहीं कर सकता और बस उस स्क्रीन का बिटमैप प्राप्त कर सकता हूं। उदाहरण के लिए, मैं केवल होमस्क्रीन को कॉल करता हूं और यह ए, बी, सी और एक्टिविटी में से कोई भी ए, बी, सी को प्रदर्शित करता है। यह सिर्फ getDrawingCache () द्वारा उस स्क्रीन का बिटमैप देता है। और फिर हम होमस्क्रीन में गैलरी दृश्य में उन बिटमैप को प्रदर्शित कर सकते हैं।

मुझे आशा है कि मैंने समस्या को बहुत स्पष्ट रूप से समझाया है।

कृपया मुझे बताएं कि क्या यह वास्तव में संभव है।


1
मुझे पूरा यकीन नहीं है, लेकिन मुझे लगता है कि आप ऐसा नहीं कर पाएंगे। समस्या यह है कि गतिविधियाँ उपयोगकर्ता को प्रदर्शित करने के लिए होती हैं। आप गतिविधि शुरू कर सकते हैं और फिर तुरंत इसे छिपा सकते हैं, लेकिन गतिविधि अभी भी विभाजित-सेकंड के लिए उपयोगकर्ता को दिखाई देगी। यह लंबे समय से पर्याप्त दिखाई देता है इसलिए स्क्रीन पर कई बार झिलमिलाहट होने से ऐप अप्रमाणिक दिखाई देता है। हालाँकि, यह संभव हो सकता है कि बिना प्रदर्शित किए किसी गतिविधि को शुरू करने की आज्ञा हो; मैं सिर्फ एक का पता नहीं है अगर यह मौजूद है।
स्टीव हेली

5
दरअसल, मैं ऐसा करने में सक्षम था।
सुनील

ओह, आप उस गतिविधि को कैसे कह सकते हैं, लेकिन इसे दिखाने के लिए नहीं? क्या मैं वर्तमान गतिविधि के लेआउट को बिटमैप को उत्पन्न करने के लिए टेम्पलेट के रूप में ले सकता हूं, जबकि इसे विभिन्न सामग्री खिला सकते हैं?
जियोनी

इस पोस्ट में उत्तर की जांच करें, मुझे कुछ प्रकार का समाधान मिला: stackoverflow.com/questions/36424381/…
Wackaloon

जवाबों:


213

ऐसा करने का एक तरीका है। आपको एक बिटमैप और एक कैनवस बनाना होगा और व्यू.ड्राइव (कैनवास) को कॉल करना होगा;

यहाँ कोड है:

public static Bitmap loadBitmapFromView(View v) {
    Bitmap b = Bitmap.createBitmap( v.getLayoutParams().width, v.getLayoutParams().height, Bitmap.Config.ARGB_8888);                
    Canvas c = new Canvas(b);
    v.layout(v.getLeft(), v.getTop(), v.getRight(), v.getBottom());
    v.draw(c);
    return b;
}

यदि यह आकार शून्य होने से पहले दृश्य प्रदर्शित नहीं किया गया था। इसे इस तरह मापना संभव है:

if (v.getMeasuredHeight() <= 0) {
    v.measure(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
    Bitmap b = Bitmap.createBitmap(v.getMeasuredWidth(), v.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
    Canvas c = new Canvas(b);
    v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
    v.draw(c);
    return b;
}

संपादित करें: इस पोस्ट के अनुसार , किसी भी अच्छा करने के लिए मान के रूप में पासिंगWRAP_CONTENTmakeMeasureSpec() (हालांकि कुछ दृश्य वर्गों के लिए यह काम करता है), और अनुशंसित विधि है:

// Either this
int specWidth = MeasureSpec.makeMeasureSpec(parentWidth, MeasureSpec.AT_MOST);
// Or this
int specWidth = MeasureSpec.makeMeasureSpec(0 /* any */, MeasureSpec.UNSPECIFIED);
view.measure(specWidth, specWidth);
int questionWidth = view.getMeasuredWidth();

1
मैंने यह कोशिश की, लेकिन मुझे लगता है कि एक अर्ध पारदर्शी ब्लैक बॉक्स है। क्या मुझे बिटमैप ड्राइंग के लिए तैयार होने के लिए दृश्य पर कुछ करने की आवश्यकता है?
बॉबबेक 4

4
मुझे वास्तव में इसे v.layout(v.getLeft(), v.getTop(), v.getRight(), v.getBottom());सही तरीके से काम करने के लिए बदलने के लिए बदलना पड़ा , लेकिन कोड के लिए धन्यवाद :)
triad

3
मुझे v.getLayoutParams () के बजाय v.getWidth () का उपयोग करना था। ऊँचाई के लिए चौड़ाई और समान। अन्यथा, अब काम कर रहा है।
डेविड मैनपेल

1
मैंने इस्तेमाल किया v.measure(0, 0); v.getMeasuredWidth(); v.getMeasuredHeight();
ब्रिस गाबिन

7
Bitmap b = Bitmap.createBitmap(v.getWidth(), v.getHeight(), Bitmap.Config.ARGB_8888);बेहतर काम करता है
पियरे

29

यहाँ मेरा समाधान है:

public static Bitmap getBitmapFromView(View view) {
    Bitmap returnedBitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(),Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(returnedBitmap);
    Drawable bgDrawable =view.getBackground();
    if (bgDrawable!=null) 
        bgDrawable.draw(canvas);
    else 
        canvas.drawColor(Color.WHITE);
    view.draw(canvas);
    return returnedBitmap;
}

का आनंद लें :)


धन्यवाद। कुछ उपकरणों पर मुझे समस्या आ रही थी यदि ऊंचाई एक निश्चित मूल्य से परे थी। मैंने पूरी तरह से परीक्षण नहीं किया है लेकिन इसका समाधान होता है।
बीएमएफ

22

इसे इस्तेमाल करे,

/**
 * Draw the view into a bitmap.
 */
public static Bitmap getViewBitmap(View v) {
    v.clearFocus();
    v.setPressed(false);

    boolean willNotCache = v.willNotCacheDrawing();
    v.setWillNotCacheDrawing(false);

    // Reset the drawing cache background color to fully transparent
    // for the duration of this operation
    int color = v.getDrawingCacheBackgroundColor();
    v.setDrawingCacheBackgroundColor(0);

    if (color != 0) {
        v.destroyDrawingCache();
    }
    v.buildDrawingCache();
    Bitmap cacheBitmap = v.getDrawingCache();
    if (cacheBitmap == null) {
        Log.e(TAG, "failed getViewBitmap(" + v + ")", new RuntimeException());
        return null;
    }

    Bitmap bitmap = Bitmap.createBitmap(cacheBitmap);

    // Restore the view
    v.destroyDrawingCache();
    v.setWillNotCacheDrawing(willNotCache);
    v.setDrawingCacheBackgroundColor(color);

    return bitmap;
}

मैं अपने मुख्य गतिविधि वर्ग से इसका उपयोग कैसे करूँ?
Si8

यह पदावनत है
Ch Vas

20

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

यहाँ वह विधि है जो मेरे मामले के लिए काम कर रही है। हालांकि, एक कैवेट के साथ। कॉल करने से पहले getViewBitmap(View)मैंने अपना दृष्टिकोण फुलाया और इसे ज्ञात आयामों के साथ लेआउट करने के लिए कहा। इसकी आवश्यकता तब से थी, जब तक कि मेरे दृश्य लेआउट को शून्य ऊँचाई / चौड़ाई नहीं देगा, जब तक कि सामग्री अंदर नहीं रखी जाती।

View view = LayoutInflater.from(context).inflate(layoutID, null);
//Do some stuff to the view, like add an ImageView, etc.
view.layout(0, 0, width, height);

Bitmap getViewBitmap(View view)
{
    //Get the dimensions of the view so we can re-layout the view at its current size
    //and create a bitmap of the same size 
    int width = view.getWidth();
    int height = view.getHeight();

    int measuredWidth = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY);
    int measuredHeight = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY);

    //Cause the view to re-layout
    view.measure(measuredWidth, measuredHeight);
    view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());

    //Create a bitmap backed Canvas to draw the view into
    Bitmap b = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
    Canvas c = new Canvas(b);

    //Now that the view is laid out and we have a canvas, ask the view to draw itself into the canvas
    view.draw(c);

    return b;
}

मेरे लिए "मैजिक सॉस" यहां पाया गया: https://groups.google.com/forum/# ​​.topic / android-developers / BxIBAOeTA1Q

चीयर्स,

लेवि


चीयर्स! ऐसा लगता है कि किसी को उनके द्वारा लेआउट में किसी भी परिवर्तन के बाद माप और अनुरोध को कॉल करना होगा
TheIT

1
इस समाधान के लिए धन्यवाद! मुझे भी यही समस्या थी। मैं उपयोग कर रहा था measure()और layout()इससे पहले कि मैं अपने दृष्टिकोण को आबाद करता, इसलिए मेरे अजीब परिणाम थे। इन कॉलों को नीचे ले जाना, ऊपर createBitmap()मेरे लिए तय!
स्वेन जैकब्स

6

एंड्रॉइड केटीएक्स में एक महान कोटलिन एक्सटेंशन फ़ंक्शन है: View.drawToBitmap(Bitmap.Config)


3
यदि लेआउट में दृश्य प्रस्तुत नहीं किया गया है तो यह काम नहीं करेगा। त्रुटि: "IllegalStateException: View को drawToBitmap () कॉल करने से पहले रखी जाने की आवश्यकता है"
Val

2

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

View view="some view instance";        
view.setDrawingCacheEnabled(true);
Bitmap bitmap=view.getDrawingCache();
view.setDrawingCacheEnabled(false);

अद्यतन
getDrawingCache() विधि एपीआई स्तर 28 में पदावनत है। इसलिए एपीआई स्तर> 28 के लिए अन्य विकल्प की तलाश करें।


1
getDrawingCacheवर्तमान में पदावनत है।
डेविड मिगुएल

1

बिटमैप के लिए लेआउट या दृश्य:

 private Bitmap createBitmapFromLayout(View tv) {      
    int spec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
    tv.measure(spec, spec);
    tv.layout(0, 0, tv.getMeasuredWidth(), tv.getMeasuredHeight());
    Bitmap b = Bitmap.createBitmap(tv.getMeasuredWidth(), tv.getMeasuredWidth(),
            Bitmap.Config.ARGB_8888);
    Canvas c = new Canvas(b);
    c.translate((-tv.getScrollX()), (-tv.getScrollY()));
    tv.draw(c);
    return b;
}

कॉलिंग विधि:

Bitmap src = createBitmapFromLayout(View.inflate(this, R.layout.sample, null)/* or pass your view object*/);

0

मुझे लगता है कि यह थोड़ा बेहतर है:

/**
 * draws the view's content to a bitmap. code initially based on :
 * http://nadavfima.com/android-snippet-inflate-a-layout-draw-to-a-bitmap/
 */
@Nullable
public static Bitmap drawToBitmap(final View viewToDrawFrom, int width, int height) {
    boolean wasDrawingCacheEnabled = viewToDrawFrom.isDrawingCacheEnabled();
    if (!wasDrawingCacheEnabled)
        viewToDrawFrom.setDrawingCacheEnabled(true);
    if (width <= 0 || height <= 0) {
        if (viewToDrawFrom.getWidth() <= 0 || viewToDrawFrom.getHeight() <= 0) {
            viewToDrawFrom.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
            width = viewToDrawFrom.getMeasuredWidth();
            height = viewToDrawFrom.getMeasuredHeight();
        }
        if (width <= 0 || height <= 0) {
            final Bitmap bmp = viewToDrawFrom.getDrawingCache();
            final Bitmap result = bmp == null ? null : Bitmap.createBitmap(bmp);
            if (!wasDrawingCacheEnabled)
                viewToDrawFrom.setDrawingCacheEnabled(false);
            return result;
        }
        viewToDrawFrom.layout(0, 0, width, height);
    } else {
        viewToDrawFrom.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
        viewToDrawFrom.layout(0, 0, viewToDrawFrom.getMeasuredWidth(), viewToDrawFrom.getMeasuredHeight());
    }
    final Bitmap drawingCache = viewToDrawFrom.getDrawingCache();
    final Bitmap bmp = ThumbnailUtils.extractThumbnail(drawingCache, width, height);
    final Bitmap result = bmp == null || bmp != drawingCache ? bmp : Bitmap.createBitmap(bmp);
    if (!wasDrawingCacheEnabled)
        viewToDrawFrom.setDrawingCacheEnabled(false);
    return result;
}

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

इसके अलावा, यदि आप विशेष दृश्य (सरफेस व्यू, सरफेस या विंडो, उदाहरण के लिए) को बिटमैप में परिवर्तित करना चाहते हैं, तो आपको इसके बजाय PixelCopy वर्ग का उपयोग करने पर विचार करना चाहिए । इसके लिए एपीआई 24 और उसके बाद के संस्करण की आवश्यकता है। मुझे नहीं पता कि यह पहले कैसे करना है।


कोई भी विचार, बिटमैप में कोई TextView नहीं जोड़ा गया है। केवल ImageView जोड़े जाते हैं।
खेमराज

@ खेमराज मुझे सवाल समझ नहीं आ रहा है।
Android डेवलपर

यह मेरी गलती थी मेरा टेक्स्ट व्यू बिटमैप में नहीं था। क्योंकि मैंने हल्के रंग का थीम लगाया था, उत्तर के लिए धन्यवाद।
खेमराज

1
@Khemraj क्षमा करें, लेकिन मुझे अभी भी समझ में नहीं आया है। अब सब ठीक है?
एंड्रॉयड डेवलपर

हाँ भाई, मुझे नहीं पता कि तुम मुझसे क्यों नहीं मिल रहे :)। मेरे पास लेआउट में एक TextView था जिसे मैं बिटमैप में परिवर्तित करना चाहता था। लेआउट में एक ImageView और एक TextView था। ImageView बिटमैप में परिवर्तित हो रहा था। लेकिन टेक्स्टमैप बिटमैप में दिखाई नहीं दे रहा था। वह समस्या थी। उसके बाद मुझे एहसास हुआ कि मेरे पास एक थीम थी जो कि टेक्स्टव्यू टेक्स्ट का रंग सफेद बना रही थी। मैंने ठीक कर दिया। और अब सब ठीक है। धन्यवाद।
खेमराज

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