Take a screenshot of a whole View

2019-01-02 20:47发布

I have built a table which is basically done by HorizontalScrollView inside a ScrollView. I made the user can edit the fields.

Now I want to save the table on a screen, jpg, png, pdf or anything else.

The problem is - the table is nearly always bigger than the screen.

Is there a way to make a screenshot of the whole ScrollView layout? If not what do you think can do the job?

13条回答
荒废的爱情
2楼-- · 2019-01-02 20:52

Download source code from here (Take screenshot of scrollview in android programmatically)

activity_main.xml

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#efefef"
    android:orientation="vertical">

    <Button
        android:id="@+id/btn_screenshot"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_margin="10dp"
        android:text="Take ScreenShot"/>

    <ScrollView
        android:id="@+id/scrollView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginBottom="10dp"
        android:background="#ffffff">

        <LinearLayout
            android:id="@+id/ll_linear"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="10dp"
            android:orientation="vertical">

            <ImageView
                android:layout_width="match_parent"
                android:layout_height="200dp"
                android:layout_gravity="center"
                android:layout_marginTop="10dp"
                android:scaleType="fitXY"
                android:src="@drawable/image2"/>

            <ImageView
                android:layout_width="match_parent"
                android:layout_height="200dp"
                android:layout_gravity="center"
                android:layout_marginTop="10dp"
                android:scaleType="fitXY"
                android:src="@drawable/image3"/>

            <ImageView
                android:layout_width="match_parent"
                android:layout_height="200dp"
                android:layout_gravity="center"
                android:layout_marginTop="10dp"
                android:scaleType="fitXY"
                android:src="@drawable/image5"/>

            <ImageView
                android:layout_width="match_parent"
                android:layout_height="200dp"
                android:layout_gravity="center"
                android:layout_marginTop="10dp"
                android:scaleType="fitXY"
                android:src="@drawable/image6"/>

        </LinearLayout>
    </ScrollView>
</LinearLayout>

MainActivity.xml

package deepshikha.com.screenshot;
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.Toast;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class MainActivity extends AppCompatActivity {

Button btn_screenshot;
ScrollView scrollView;
LinearLayout ll_linear;
public static int REQUEST_PERMISSIONS = 1;
boolean boolean_permission;
boolean boolean_save;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    init();
    fn_permission();
}

private void init() {
    btn_screenshot = findViewById(R.id.btn_screenshot);
    scrollView = findViewById(R.id.scrollView);
    ll_linear = findViewById(R.id.ll_linear);

    btn_screenshot.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            if (boolean_save) {
                Intent intent = new Intent(getApplicationContext(), Screenshot.class);
                startActivity(intent);

            } else {
                if (boolean_permission) {
                    Bitmap bitmap1 = loadBitmapFromView(ll_linear, ll_linear.getWidth(), ll_linear.getHeight());
                    saveBitmap(bitmap1);
                } else {

                }
            }

        }
    });
}

public void saveBitmap(Bitmap bitmap) {
    File imagePath = new File("/sdcard/screenshotdemo.jpg");
    FileOutputStream fos;
    try {
        fos = new FileOutputStream(imagePath);
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
        fos.flush();
        fos.close();
        Toast.makeText(getApplicationContext(), imagePath.getAbsolutePath() + "", Toast.LENGTH_SHORT).show();
        boolean_save = true;

        btn_screenshot.setText("Check image");

        Log.e("ImageSave", "Saveimage");
    } catch (IOException e) {
        Log.e("GREC", e.getMessage(), e);
    }
}

public static Bitmap loadBitmapFromView(View v, int width, int height) {
    Bitmap b = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
    Canvas c = new Canvas(b);
    v.draw(c);

    return b;
}

private void fn_permission() {
    if ((ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) ||
            (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)) {
        if ((!ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE))) {
            ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
                    REQUEST_PERMISSIONS);
        }

        if ((!ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE))) {
            ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                    REQUEST_PERMISSIONS);
        }
    } else {
        boolean_permission = true;
    }
}


@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);

    if (requestCode == REQUEST_PERMISSIONS) {
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            boolean_permission = true;

        } else {
            Toast.makeText(getApplicationContext(), "Please allow the permission", Toast.LENGTH_LONG).show();

        }
    }
}
}

Thanks!

查看更多
时光乱了年华
3楼-- · 2019-01-02 20:54

It is impossible to make a screenshot of not-yet-rendered content (like off-screen parts of the ScrollView). However, you can make a multiple screenshots, scrolling content between each shot, then join images. Here is a tool which can automate this for you: https://github.com/PGSSoft/scrollscreenshot

illustration

Disclaimer: I'm author of this tool, it was published by my employer. Feature requests are welcome.

查看更多
千与千寻千般痛.
4楼-- · 2019-01-02 20:56

You can pass the view a fresh instance of a Canvas built upon a Bitmap object.

Try with

Bitmap b = Bitmap.createBitmap(targetView.getWidth(), 
                               targetView.getHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
targetView.draw(c);
BitmapDrawable d = new BitmapDrawable(getResources(), b);
canvasView.setBackgroundDrawable(d);`

It actually did the job for me.

查看更多
零度萤火
5楼-- · 2019-01-02 20:59

Taking a screenshot of a view, pass the view in the parameter

public static Bitmap getViewBitmap(View v) {
    v.clearFocus();
    v.setPressed(false);

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

    int color = v.getDrawingCacheBackgroundColor();
    v.setDrawingCacheBackgroundColor(0);

    if (color != 0) {
        v.destroyDrawingCache();
    }
    v.buildDrawingCache();
    Bitmap cacheBitmap = v.getDrawingCache();
    if (cacheBitmap == null) {
        return null;
    }

    Bitmap bitmap = Bitmap.createBitmap(cacheBitmap);

    v.destroyDrawingCache();
    v.setWillNotCacheDrawing(willNotCache);
    v.setDrawingCacheBackgroundColor(color);

    return bitmap;
}
查看更多
荒废的爱情
6楼-- · 2019-01-02 21:01

I've tested a lot of codes and every time hitting NullPointerExeption. I discovered that when our view does not have a parent view, the provided width and height (Xml or Java) get ignored and get setted to MATCH_PARENT.

Finally I came up with this solution:

/**
 * Take screen shot of the View
 *
 * @param v the view
 * @param width_dp
 * @param height_dp
 *
 * @return screenshot of the view as bitmap
 */
public static Bitmap takeScreenShotOfView(View v, int width_dp, int height_dp) {

    v.setDrawingCacheEnabled(true);

    // this is the important code :)
    v.measure(View.MeasureSpec.makeMeasureSpec(dpToPx(v.getContext(), width_dp), View.MeasureSpec.EXACTLY),
            View.MeasureSpec.makeMeasureSpec(dpToPx(v.getContext(), height_dp), View.MeasureSpec.EXACTLY));
    v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());

    v.buildDrawingCache(true);

    // creates immutable clone
    Bitmap b = Bitmap.createBitmap(v.getDrawingCache());
    v.setDrawingCacheEnabled(false); // clear drawing cache
    return b;
}

public static int dpToPx(Context context, int dp) {
    Resources r = context.getResources();
    return Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, r.getDisplayMetrics()));
}
查看更多
梦寄多情
7楼-- · 2019-01-02 21:04

You might be able to use the drawing cache of a view, but I am not sure if this will hold the entire view or just what is rendered to the screen.

I would advise you hunt around on StackOverflow for similar questions, it has more than likely been asked before.

查看更多
登录 后发表回答