Сделать скриншот всего просмотра
Я построил таблицу, которая в основном делается HorizontalScrollView
внутри ScrollView
, Я сделал пользователь может редактировать поля.
Теперь я хочу сохранить таблицу на экране, JPG, PNG, PDF или что-нибудь еще.
Проблема в том, что таблица почти всегда больше экрана.
Есть ли способ сделать скриншот всего ScrollView
макет? Если нет, то, что вы думаете, может сделать эту работу?
16 ответов
На самом деле я нашел ответ:
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.layout(0, 0, v.getLayoutParams().width, v.getLayoutParams().height);
v.draw(c);
return b;
}
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);
Использование ответа @softwaresupply вызывает проблему в моем случае, когда мое представление перерисовывалось и становилось полностью белым. Существует более простое решение, чтобы получить скриншот, где вам даже не нужно указывать ширину и высоту в качестве параметров. Используйте чертежный кэш.
public static Bitmap loadBitmapFromView(View v) {
Bitmap bitmap;
v.setDrawingCacheEnabled(true);
bitmap = Bitmap.createBitmap(v.getDrawingCache());
v.setDrawingCacheEnabled(false);
return bitmap;
}
Невозможно сделать скриншот еще не отрендеренного контента (например, закадровых частей ScrollView). Тем не менее, вы можете сделать несколько скриншотов, прокручивая контент между каждым снимком, а затем объединять изображения. Вот инструмент, который может автоматизировать это для вас: https://github.com/PGSSoft/scrollscreenshot
Отказ от ответственности: я автор этого инструмента, он был опубликован моим работодателем. Запросы на функции приветствуются.
Загрузите исходный код отсюда ( программно сделайте скриншот scrollview в android)
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();
}
}
}
}
Спасибо!
Вы можете передать представление свежему экземпляру Canvas, построенному на растровом объекте.
Попробуй с
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);`
Это фактически сделало работу для меня.
Эта работа для меня, надеюсь, она будет полезна и для вас.
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;
}
Я проверял много кодов и каждый раз нажимал NullPointerExeption
, Я обнаружил, что, когда у нашего представления нет родительского представления, предоставленные ширина и высота (Xml или Java) игнорируются и устанавливаются в MATCH_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()));
}
Пожалуйста, попробуйте этот код:
Bitmap bitmap = getBitmapFromView(scrollview, scrollview.getChildAt(0).getHeight(), scrollview.getChildAt(0).getWidth());
//create bitmap from the ScrollView
private Bitmap getBitmapFromView(View view, int height, int width) {
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
Drawable bgDrawable = view.getBackground();
if (bgDrawable != null)
bgDrawable.draw(canvas);
else
canvas.drawColor(Color.WHITE);
view.draw(canvas);
return bitmap;
}
Как упоминалось здесь , вы можете использовать
View::drawToBitmap
функция:
val bitmap = myView.drawToBitmap(/*Optional:*/ Bitmap.Config.ARGB_8888)
Просто убедитесь , что использовать -ktx версию AndroidX ядра библиотеки:
implementation("androidx.core:core-ktx:1.6.0")
Примечание. Версия библиотек -ktx такая же, как и версии библиотек, отличных от ktx, за исключением того, что они содержат полезные функции расширения Kotlin.
Делая скриншот вида, передайте вид в параметре
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;
}
Возможно, вы сможете использовать кэш чертежа вида, но я не уверен, что он будет содержать весь вид или только то, что отображается на экране.
Я бы посоветовал вам поохотиться на Stackru по схожим вопросам, он, скорее всего, задавался раньше.
Попробуйте это работает хорошо для меня
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);
}
// установить слушателя нажатия кнопки
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 loadBitmapFromView(ScrollView v) {
Bitmap b = Bitmap.createBitmap(v.getWidth() , v.getChildAt(0).getHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
v.draw(c);
return b;
}
fun View.getScreenShot():Bitmap{
return Bitmap.createBitmap(width,height,Bitmap.Config.ARGB_8888).apply {
draw(Canvas(this))
}
}