14

I have two main issues which are closely linked. I am looking at these problems from a programmatic point of view.

(1) - I wish to take a screenshot of the contents of a SPECIFIC layout, i.e. a ScrollView nested in a LinearLayout.

(2) - As the ScrollView has content that spills out of the screen (hence scrolling made possible), how can I ensure that the screenshot includes the elements that are not visible on the screen?

This is the current block of code I use. It does the job of taking a screenshot but only for the entire screen. This is even though R.id.boss is the ID of the ScrollView and not the main LinearLayout.

View view = findViewById(R.id.boss);
View v = view.getRootView();// this does not seem to make a difference
v.setDrawingCacheEnabled(true);                                                
v.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), 
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());    
v.buildDrawingCache(true);
Bitmap b = Bitmap.createBitmap(u.getDrawingCache());             
v.setDrawingCacheEnabled(false);

Thanks in advance.

EDIT:

I've made a few mistakes. I used R.id.boss which is the wrong resource. I am now able to take a screenshot of the scrollview alone, less the out-of-screen parts.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/boss"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="top"
android:orientation="vertical" >

    <TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="F"
    android:textAppearance="?android:attr/textAppearanceMedium" />

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="Analyze via image URL"
        android:textAppearance="?android:attr/textAppearanceSmall" />

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
             >

                        <EditText
                            android:id="@+id/mUrl"
                            android:layout_width="fill_parent"
                            android:layout_height="wrap_content"
                            android:layout_weight="0.7"
                            android:text="http://" >

                            <requestFocus />
                        </EditText>

                        <ImageView
                            android:id="@+id/call"
                            android:layout_width="75dp"
                            android:layout_height="50dp"
                            android:layout_weight="0.3"
                            android:text="ABC"
                            android:src="@drawable/run" />

        </LinearLayout>

     <TextView
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
         android:text="ABC"
         android:textAppearance="?android:attr/textAppearanceSmall" />

     <LinearLayout
         android:layout_width="fill_parent"
         android:layout_height="wrap_content" >

         <EditText
             android:id="@+id/filepath"
             android:layout_width="fill_parent"
             android:layout_height="wrap_content"
             android:layout_weight="0.55" />

         <ImageView
             android:id="@+id/cam"
             android:layout_width="75dp"
             android:layout_height="50dp"
             android:layout_weight="0.15"
             android:src="@drawable/cam" />

         <ImageView
             android:id="@+id/browse"
             android:layout_width="75dp"
             android:layout_height="50dp"
             android:layout_weight="0.15"
             android:src="@drawable/folder"
             android:text="B" />

         <ImageView
             android:id="@+id/upload"
             android:layout_width="75dp"
             android:layout_height="50dp"
             android:layout_weight="0.15"
             android:src="@drawable/run"
             android:text="A" />
     </LinearLayout>


     <LinearLayout
         android:id="@+id/baba"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
         android:orientation="vertical" >


         <ScrollView
             android:id="@+id/scroll"
             android:layout_width="fill_parent"
             android:layout_height="150dp"
             android:layout_weight="0.7" >

             <LinearLayout
                 android:layout_width="fill_parent"
                 android:layout_height="186dp"
                 android:orientation="vertical" >

                 <ImageView
                     android:id="@+id/pic"
                     android:layout_width="fill_parent"
                     android:layout_height="fill_parent"
                     android:layout_weight="1" />

                 <TextView
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
                     android:layout_weight="1"
                     android:text="Facial recognition"
                     android:textAppearance="?android:attr/textAppearanceMedium" />

                 <TextView
                     android:id="@+id/text3"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
                     android:layout_weight="1"
                     android:text="Small Text"
                     android:textAppearance="?android:attr/textAppearanceSmall" />

                 <TextView
                     android:id="@+id/avmarwe"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
                     android:layout_weight="1"
                     android:text="Gender and age"
                     android:textAppearance="?android:attr/textAppearanceMedium" />

                 <TextView
                     android:id="@+id/text1"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
                     android:layout_weight="1"
                     android:text="Small Text"
                     android:textAppearance="?android:attr/textAppearanceSmall" />

                 <TextView
                     android:id="@+id/skahasd"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
                     android:layout_weight="1"
                     android:text="Expression and mood"
                     android:textAppearance="?android:attr/textAppearanceMedium" />

                 <TextView
                     android:id="@+id/text2"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
                     android:layout_weight="1"
                     android:text="Small Text"
                     android:textAppearance="?android:attr/textAppearanceSmall" />

                 <TextView
                     android:id="@+id/dsfsfs"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
                     android:layout_weight="1"
                     android:text="Celebrity Facial Match"
                     android:textAppearance="?android:attr/textAppearanceMedium" />

                 <TextView
                     android:id="@+id/text4"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
                     android:layout_weight="1"
                     android:text="Small Text"
                     android:textAppearance="?android:attr/textAppearanceSmall" />
             </LinearLayout>
         </ScrollView>

     </LinearLayout>


    <LinearLayout
        android:id="@+id/linearLayout1"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom" >

        <Button
            android:id="@+id/c"
            android:layout_width="fill_parent"
            android:layout_height="50dp"
            android:layout_weight="0.7"
            android:text="" />

        <Button
            android:id="@+id/share"
            android:layout_width="70dp"
            android:layout_height="50dp"
            android:layout_weight="0.3"
            android:text="" />

    </LinearLayout>

</LinearLayout>
Reuben L.
  • 2,806
  • 2
  • 29
  • 45
  • Check these - http://stackoverflow.com/questions/4538429/capture-picture-from-webview - http://stackoverflow.com/questions/5604125/android-taking-screenshot-of-offscreen-page - http://stackoverflow.com/questions/9782595/how-to-take-screenshot-of-androidemulator-using-this-library-and-where-can-i-g – silwar May 18 '12 at 09:32
  • see my [question](http://stackoverflow.com/questions/5604125/android-taking-screenshot-of-offscreen-page) under **EDIT: final outcome**.. it is about taking screenshot of offscreen page.. But the same logic works anywhere.. – Krishnabhadra May 18 '12 at 09:38
  • hi silwar, thanks, i've looked at them. the link on 2 activities seems to be the closest to what I need but I do not wish to create a second activity. – Reuben L. May 18 '12 at 09:38
  • hi, because I do not want the entire LinearLayout to be saved. Just the contents of the ScrollView. – Reuben L. May 18 '12 at 09:42
  • Using LinearLayout just get ScreenShots of it, If it contains your all layout views even not visible views on screen also. Then go further. – user370305 May 18 '12 at 09:45
  • unfortunately it does not. it only saves what is visible on the screen. – Reuben L. May 18 '12 at 09:46
  • @Krishnabhadra is it possible for me to get Activity B as a clone of the current activity but only with the scrollview? – Reuben L. May 18 '12 at 09:48
  • 1
    Also I found some mistakes in your code, on u, v.. – user370305 May 18 '12 at 09:57
  • argh so many mistakes in my code!! another thing i realised is that `R.id.boss` is the wrong resource! It is actually the main LinearLayout. – Reuben L. May 18 '12 at 09:59
  • Can you post your layout file for which you want to take screenshot? – user370305 May 18 '12 at 10:02
  • 1
    Actually, I tried the code and it take a screenshot of all views from parent whether they are visible on screen or not.. You don't need to scroll. – user370305 May 18 '12 at 10:17
  • hmmm my scrollview is about 2 screens high and I am still only able to take a screenshot of the visible portions – Reuben L. May 18 '12 at 10:20
  • I tried with long scrollView with only half is visible with same code but In my image I got complete screen layout also invisible views.. – user370305 May 18 '12 at 10:26
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/11415/discussion-between-reuben-l-and-user370305) – Reuben L. May 18 '12 at 10:27
  • Also whats the structure of your layout? is Scrollview has only one child layout? – user370305 May 18 '12 at 10:27

6 Answers6

20

Thanks to you guys, I've finally found out what was wrong.

View v = view.getRootView(); should not be used because it will call the root view which I do not want. I mistakenly thought this did not make a difference because I had entered the wrong resource ID.

MeasureSpec somehow did not give a good account of the width and height. So I ended up using another method:

...
ScrollView z = (ScrollView) findViewById(R.id.scroll);
int totalHeight = z.getChildAt(0).getHeight();
int totalWidth = z.getChildAt(0).getWidth();
u.layout(0, 0, totalWidth, totalHeight);
...

As ScrollView's total height can be determined by the single child element that it has.

After making these changes, I am now able to take a screenshot of a nested ScrollView and all its contents, visible or not. For anyone interested, here is the block of code including the saving of the bitmap:

            View u = findViewById(R.id.scroll);
            u.setDrawingCacheEnabled(true);                                                
            ScrollView z = (ScrollView) findViewById(R.id.scroll);
            int totalHeight = z.getChildAt(0).getHeight();
            int totalWidth = z.getChildAt(0).getWidth();
            u.layout(0, 0, totalWidth, totalHeight);    
            u.buildDrawingCache(true);
            Bitmap b = Bitmap.createBitmap(u.getDrawingCache());             
            u.setDrawingCacheEnabled(false);

            //Save bitmap
            String extr = Environment.getExternalStorageDirectory().toString() +   File.separator + "Folder";
            String fileName = new SimpleDateFormat("yyyyMMddhhmm'_report.jpg'").format(new Date());
            File myPath = new File(extr, fileName);
            FileOutputStream fos = null;
            try {
                fos = new FileOutputStream(myPath);
                b.compress(Bitmap.CompressFormat.JPEG, 100, fos);
                fos.flush();
                fos.close();
                MediaStore.Images.Media.insertImage(getContentResolver(), b, "Screen", "screen");
            }catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
Reuben L.
  • 2,806
  • 2
  • 29
  • 45
  • I'm Sorry can I ask, is these codes really help you? I face the same problems like your question, but when I try your code, It doesn't display a view like what I want, only the black screen. – Menma Aug 29 '14 at 02:17
  • Yeah, the code worked well and the app was published 2 years ago. Did you adjust the variables accordingly? – Reuben L. Aug 30 '14 at 07:27
  • ooppss didn't see this code ` View u = findViewById(R.id.scroll);` thank you very much.... – Menma Sep 01 '14 at 02:37
  • it is possible to get screen shot of gridview, i tried you code it take whole gridview height and width but not content(iamge) it display black boxes – Hiren Dabhi Oct 03 '14 at 09:32
  • That works, however I needed to reset the width and height of the ScrollView after taking the screenshot. The u.layout(0, 0, totalWidth, totalHeight); code changes the dimensions. – Eren Yilmaz Oct 09 '14 at 19:52
  • I am getting error ..View too large to fit into drawing cache, needs 5258880 bytes, only 3686400 available ..Still i have not found solution so please help me – Girish Patel Jan 29 '15 at 16:07
3

try this it works fine for me

TableLayout tabLayout = (TableLayout) findViewById(R.id.allview);
if (tabLayout != null) {
    Bitmap image = Bitmap.createBitmap(tabLayout.getWidth(),
            tabLayout.getHeight(), Config.ARGB_8888);
    Canvas b = new Canvas(image);
    tabLayout.draw(b);
}
indivisible
  • 4,892
  • 4
  • 31
  • 50
Mahtab
  • 269
  • 3
  • 11
2

EDIT : after seeing OP's comment

You dont need to think about new activities at all.. Say you are in Activity right now.. Layout A is the main layout for the activity, Layout B and C are two child layouts inside Layout A. Like this,

 Layout A -> Parent
 |
  -------Layout B
 |
  -------Layout C

Now if you want to take screenshot of C only

1) in onCreate() of activity

 LinearLayout myCLayout = (LinearLayout)this.findViewbyId(R.id.my_c_layout);
 ViewTreeObserver vto   =  myCLayout.getViewTreeObserver();
 vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
   @Override
   public void onGlobalLayout() {
      //fully drawn, no need of listener anymore
      myCLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
      getDrawingBitmap();
   }
 });

where getDrawingBitmap() is a function..to take your screenshot..

public void getDrawingBitmap(){
    LinearLayout myCLayout = (LinearLayout)this.findViewbyId(R.id.my_c_layout);
    Bitmap b = myCLayout.getDrawingCache();

    File file = saveBitmapAsFile(b);
}

EDIT: For ScrollView

I never tried it.. But I think you can do this..

1) first override scrollView, and override onMeasure function..

public class MyScrollView extends ScrollView{
    public MyScrollView(Context context, AttributeSet attrs) {
         super(context, attrs);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
        super.onMeasure(widthMeasureSpec, yourFullScrollViewHeight));
    }
}

and use MyScrollView in your layout.. here yourFullScrollViewHeight is the height of all scrollView content you need to take screenshot of.. I never tried this.. But it might work..

Krishnabhadra
  • 34,169
  • 30
  • 118
  • 167
  • I am still unable to take a full image of the entire scrollview with this method. I guess it is slightly different from a normal out-of-screen issue as scrollview contents that are not visible are deemed out-of-screen. – Reuben L. May 18 '12 at 10:18
  • Please see my edit.. I cant guarantee whether it will work or not.. But I were you I will try.. – Krishnabhadra May 18 '12 at 10:33
  • 1
    Sorry you posted your xml after I put the answer.. You might need to override the LinearLayout inside scrollView instead, exactly the same way like I override scrollView in my answer.. Override onMeasure and return full content height.. Then when you take screenshot , take screenshot of the linear layout (the one inside scrollView) instead of scrollView.. I think that will work.. – Krishnabhadra May 18 '12 at 10:40
  • 1
    Though I ended up solving this another way I think you may be right. Thanks for the help! – Reuben L. May 18 '12 at 11:01
  • @ReubenL. I want to capture screen of RelativeLayout with 2 childviews ImageView and TextView, TextView is moveable, I have tried about code, but not getting bitmap, as its not showing after calling in another imageview. – Abdul Wahab Dec 11 '12 at 08:12
2

Here is the exact solution you want, It will display entire screen including content hidden in your ScrollView

LayoutInflater inflater = (LayoutInflater) this.getSystemService(LAYOUT_INFLATER_SERVICE);
FrameLayout root = (FrameLayout) inflater.inflate(R.layout.activity_main, null); // activity_main is UI(xml) file we used in our Activity class. FrameLayout is root view of my UI(xml) file.
root.setDrawingCacheEnabled(true);
Bitmap bitmap = getBitmapFromView(this.getWindow().findViewById(R.id.frameLayout)); // here give id of our root layout (here its my FrameLayout's id)

Display bitmap in your ImageView or use it as you want.
Enjoy..

Nirav Dangi
  • 3,607
  • 4
  • 49
  • 60
0

I also had this problem and coded it myself.

I used this code to take screenshot of whole layout.

I did modified the list size and some mathematical items.

See the following website,

ForceMagic
  • 6,230
  • 12
  • 66
  • 88
muruganvel
  • 17
  • 3
-1

Try this code

public Bitmap screenShot(View view) {

    Bitmap bitmap = Bitmap.createBitmap(view.getWidth(),
    view.getHeight(), Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    view.draw(canvas);
    return bitmap;
}
Thilina Anuradh
  • 211
  • 2
  • 11