Capture screenshot of a HorizontalScrollView including offscreen elements

爷,独闯天下 提交于 2020-08-10 05:41:44

问题


I have tried many methods. I am able to take screenshot of whole screen BUT my requirement is to take screenshot of whole HorizontalScrollView and save it as an image file. Here is the sample XML layout I am using:

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

    <HorizontalScrollView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/hsv" >

        <LinearLayout 
            android:layout_height="wrap_content"
            android:layout_width="wrap_content"
            android:orientation="horizontal"
            android:id="@+id/ll">

             <Button 
                android:layout_height="wrap_content"
            android:layout_width="wrap_content"
            android:onClick="click"
            android:id="@+id/b"
            android:text="capture"
            android:layout_margin="20dp"/> 

            <ImageView 
                android:layout_height="wrap_content"
            android:layout_width="wrap_content"
            android:id="@+id/img1"
            android:src="@drawable/plug1"
            android:layout_margin="20dp"/>

            <ImageView 
                android:layout_height="wrap_content"
            android:layout_width="200dp"
            android:id="@+id/img2"
            android:src="@drawable/plug3"
            android:layout_margin="20dp"/>

        </LinearLayout>

    </HorizontalScrollView>

</RelativeLayout>

Activity Code:

Button b; 
    ImageView img1, img2; 
    LinearLayout ll; View v; 
    HorizontalScrollView s; 
    int h,w;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        b = (Button)findViewById(R.id.b);
        img1 = (ImageView)findViewById(R.id.img1);
        img2 = (ImageView)findViewById(R.id.img2);

        ll = (LinearLayout)findViewById(R.id.ll);

        s = (HorizontalScrollView) findViewById(R.id.hsv);
        s.setDrawingCacheEnabled(true);

    }

     //Fired onClick of the button
       public void click(View v) {
           shoot();
       }

    // To capture layout, create a bitmap and replace an image with the resulting bitmap.
    public void shoot() {

        s.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);

        int totalHeight = s.getMeasuredHeight();
        int totalWidth = s.getMeasuredWidth();

        s.layout(0, 0, totalHeight, totalWidth);    
        s.buildDrawingCache(true);

        Bitmap b = Bitmap.createBitmap(s.getDrawingCache());             
        s.setDrawingCacheEnabled(false);

        img1.setImageBitmap(b);     
    }

I don't get correct layout height and width if I don't use MeasureSpec.

OnClick of the button I am getting image of half button only. I think this is happening as I am not using ViewTreeObserver. But when i use ViewTreeObserver, I am not getting the result. Also, the application crashes when I click the button twice - NullPointerException in Bitmap.

I have tried nearly everything available on StackOverFlow. Please help me to find a way to do this. Is it even possible ?


回答1:


Found a SIMPLE way to do it.

XML

        <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="horizontal"
    android:layout_gravity="center_vertical">

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

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

    <Button 
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:text="capture"
        android:onClick="click"/>

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello" />

    <ImageView 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/black"
        android:id="@+id/img"/>

    <ImageView 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/a"/>

    </LinearLayout>

    </HorizontalScrollView>

</LinearLayout>

Acivity Code:

public class CaptureBeyondActivity extends Activity {
/** Called when the activity is first created. */

LinearLayout def;
ImageView img;
HorizontalScrollView hsv;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

def = (LinearLayout)findViewById(R.id.def);
img = (ImageView)findViewById(R.id.img);

}

public void click(View v) {
Bitmap bitmap;
def.setDrawingCacheEnabled(true);
def.buildDrawingCache(true);

        bitmap = Bitmap.createBitmap(def.getWidth(), def.getHeight(),
                Config.ARGB_8888);
        def.layout(0, 0, def.getLayoutParams().width,
                def.getLayoutParams().height);
        Canvas c = new Canvas(bitmap);
        def.draw(c);

def.setDrawingCacheEnabled(false);

if(bitmap!=null){
    img.setImageBitmap(bitmap);
    img.invalidate();
}
}}

Here I have placed some elements in a HorizontalScrollView. OnClick of the button a screenshot is taken and the second image is replaced by the screenshot taken. It takes screenshots of the offscreen elements also. You can further enhance the code and save the final bitmap image on SD card.




回答2:


it's the second time I see this same question (yes, here in stack overflow) and the simple answer is: There is no simple way to do it!

All the methods to save a screen shot uses the same principle of enabling the draw to the bitmap cache and obtaining this bitmap. But if the views are not on screen, they won't be drawn.

You could create a very complex system that would auto-scroll the Horizontal screen view, taking several screen shots and stitching the different bitmaps together. Or maybe a very complex system that would create an infinite width canvas and ask the layout to draw on it, but it's likely that you would run out of memory on this situation. But as I said, none of those is a simple task.



来源:https://stackoverflow.com/questions/14234371/capture-screenshot-of-a-horizontalscrollview-including-offscreen-elements

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!