Android 拍摄整个视图的屏幕截图

Android 拍摄整个视图的屏幕截图,android,screenshot,Android,Screenshot,我已经构建了一个表,它基本上是由水平滚动视图在滚动视图中完成的。我让用户可以编辑字段 现在我想在屏幕上保存表格,jpg、png、pdf或其他任何格式 问题是——桌子几乎总是比屏幕大 有没有办法制作整个ScrollView布局的屏幕截图?如果没有,您认为什么可以完成这项工作?您可能可以使用视图的图形缓存,但我不确定这是否会保存整个视图,或者只是保存渲染到屏幕上的内容 我建议您在StackOverflow上四处寻找类似的问题,以前很可能有人问过类似的问题。事实上,我找到了答案: public sta

我已经构建了一个表,它基本上是由
水平滚动视图
滚动视图
中完成的。我让用户可以编辑字段

现在我想在屏幕上保存表格,jpg、png、pdf或其他任何格式

问题是——桌子几乎总是比屏幕大


有没有办法制作整个
ScrollView
布局的屏幕截图?如果没有,您认为什么可以完成这项工作?

您可能可以使用视图的图形缓存,但我不确定这是否会保存整个视图,或者只是保存渲染到屏幕上的内容


我建议您在StackOverflow上四处寻找类似的问题,以前很可能有人问过类似的问题。

事实上,我找到了答案:

public static Bitmap loadBitmapFromView(View v) {
    Bitmap b = Bitmap.createBitmap(v.getWidth() , v.getHeight(), Bitmap.Config.ARGB_8888);                
    Canvas c = new Canvas(b);
    v.draw(c);
    return b;
}

试试这个对我来说很好

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);
}

不可能为尚未呈现的内容(如ScrollView的屏幕外部分)制作屏幕截图。但是,您可以制作多个屏幕截图,在每个截图之间滚动内容,然后加入图像。以下是一个可以为您实现自动化的工具:


免责声明:我是这个工具的作者,它是由。欢迎功能请求。

您可以向视图传递基于位图对象构建的画布的新实例

试一试

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);`

它实际上为我做了这项工作。

在我的情况下,使用@softwaresupply-answer会导致问题,我的视图被重新绘制并变得完全白色。有一个更简单的解决方案可以获得屏幕截图,您甚至不需要提供宽度和高度作为参数。
  ScrollView iv = (ScrollView) findViewById(R.id.scrollView);
  Bitmap bitmap = Bitmap.createBitmap(
        iv.getChildAt(0).getWidth(), 
        iv.getChildAt(0).getHeight(), 
        Bitmap.Config.ARGB_8888);
  Canvas c = new Canvas(bitmap);
  iv.getChildAt(0).draw(c);

  // Do whatever you want with your bitmap
  saveBitmap(bitmap);
使用图形缓存

public static Bitmap loadBitmapFromView(View v) {
    Bitmap bitmap;
    v.setDrawingCacheEnabled(true);
    bitmap = Bitmap.createBitmap(v.getDrawingCache());
    v.setDrawingCacheEnabled(false);
    return bitmap;
}

//设置按钮单击侦听器

    share = (Button)findViewById(R.id.share);
    share.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Bitmap bitmap = takeScreenshot();
            saveBitmap(bitmap);

        }
    });
//然后您必须创建两个方法

    public Bitmap takeScreenshot() {
    View rootView = findViewById(android.R.id.content).getRootView();
    rootView.setDrawingCacheEnabled(true);
    return rootView.getDrawingCache();
    }

    public void saveBitmap(Bitmap bitmap) {
    File imagePath = new File(Environment.getExternalStorageDirectory() + "/screenshot.png");
    FileOutputStream fos;
    try {
        fos = new FileOutputStream(imagePath);
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
        fos.flush();
        fos.close();
    } catch (FileNotFoundException e) {
        Log.e("GREC", e.getMessage(), e);
    } catch (IOException e) {
        Log.e("GREC", e.getMessage(), e);
    }
   }

将此代码添加到应用程序后,运行应用程序并检查您的本地存储,您已经创建了整个页面的屏幕截图。

这项工作对我来说很有用,希望对您也有帮助

public static Bitmap getBitmapByView(ScrollView scrollView) {
    int h = 0;
    Bitmap bitmap = null;
    //get the actual height of scrollview
    for (int i = 0; i < scrollView.getChildCount(); i++) {
        h += scrollView.getChildAt(i).getHeight();
        scrollView.getChildAt(i).setBackgroundResource(R.color.white);
    }
    // create bitmap with target size
    bitmap = Bitmap.createBitmap(scrollView.getWidth(), h,
            Bitmap.Config.ARGB_8888);
    final Canvas canvas = new Canvas(bitmap);
    scrollView.draw(canvas);
    FileOutputStream out = null;
    try {
        out = new FileOutputStream("/sdcard/screen_test.png");
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }
    try {
        if (null != out) {
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
            out.flush();
            out.close();
        }
    } catch (IOException e) {
        // TODO: handle exception
    }
    return bitmap;
}
公共静态位图getBitmapByView(ScrollView ScrollView){
int h=0;
位图=空;
//获取scrollview的实际高度
对于(int i=0;i
从这里下载源代码()

活动\u 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>
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();

        }
    }
}
}

谢谢

我已经测试了很多代码,每次点击
NullPointerExeption
。我发现当我们的视图没有父视图时,提供的宽度和高度(Xml或Java)会被忽略,并被设置为
MATCH\u parent

最后我提出了这个解决方案:

/**
 * 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()));
}

拍摄视图的屏幕截图,在参数中传递视图

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;
}

在这篇文章中,我找到了一些解决方案:我在这里尝试了被接受的答案,但是生成的输出有一些问题。这里的答案是对我有效的:实际上我没有找到合适的解决方案。不幸的是,图形缓存无法获取整个视图。这是一个非常复杂的解决方案。设备不会渲染屏幕外的任何内容(因为它不必渲染),因此在请求之前不会渲染视图。这里的问题是,平均布局没有实际的高度/宽度值,通常设置为匹配父/填充父。在我的例子中,我需要调查一个真实大小可访问的父级。Leon,你可以随时调用view.getWidth()和view.getHeight来获取飞行视图的尺寸。这段代码对我来说很好,但我想在一秒钟内连续拍摄24-25个屏幕截图,我可以每秒截图14-15张,但不能截图24-25张。“你能告诉我该怎么做吗?”法拉克耶维德,我和你有同样的问题,你有更好的解决办法吗?谢谢,很好,但是背景是黑色的。如何设置背景色?谢谢!有一段时间我很困惑,因为我想“但是我需要在设备中运行的部分是什么?”-没想到它会像那样工作。检查此答案以获得可能的解决方案。此库使用与上面相同的过程,但使用的形式更一般。(这不是一种优化的技术,但肯定是一种可用的技术)这种方法不太安全,图形缓存有一个限制,当您的视图很大(如滚动视图)时,getDrawingCache将返回null。在Android SDK中查找View.java和method buildDrawingCacheImpl,日志中也有警告“由于太大,无法放入软件层(或绘图缓存),需要…”它可以工作,但背景为黑色。我怎么能改变它?我知道了。需要更改第一个子元素的背景色。屏幕包含谷歌地图。它成功了,但是谷歌地图在截图中显示为黑色。
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;
}
fun View.getScreenShot():Bitmap{
    return Bitmap.createBitmap(width,height,Bitmap.Config.ARGB_8888).apply { 
        draw(Canvas(this))
    }
}