为整个布局截屏时,只有屏幕上可见的列表项才会出现在位图中

When taking screenshot for whole layout only visible listitems on screen are coming in bitmap

我正在尝试为整个视图截屏并通过 pdf 或图像共享它。 这是我的布局视图。

activity.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/mainView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/White"
    tools:context="com.tally.enjay.tallyandroid.activity.LedgerTransactionHistoryActivity">

    <include
        android:id="@+id/toolbar"
        layout="@layout/toolbar" />

    <RelativeLayout
        android:id="@+id/relativeLayout"
        style="@style/Base.CardView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/toolbar"
        android:background="@color/DateTheme"
        android:elevation="2dp"
        android:padding="10dp">


        <RelativeLayout
            android:id="@+id/relative_date"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content">

            <TextView
                android:id="@+id/current_date"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentStart="true"
                android:layout_marginEnd="5dp"
                android:text="01/04/17 - 31/03/18"
                android:textColor="@color/Black"
                android:textSize="14sp"
                android:textStyle="bold"
                tools:ignore="HardcodedText" />

            <TextView
                android:id="@+id/vs"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentStart="true"
                android:layout_below="@+id/current_date"
                android:padding="2dp"
                android:text="vs."
                android:textColor="@color/colorGreyshred"
                android:textSize="13sp"
                android:visibility="gone"
                tools:ignore="HardcodedText,RtlSymmetry" />

            <TextView
                android:id="@+id/previous_date"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@id/current_date"
                android:layout_marginStart="1dp"
                android:layout_toEndOf="@+id/vs"
                android:padding="2dp"
                android:text="01/04/16 - 31/03/17"
                android:textColor="@color/colorGreyshred"
                android:textSize="13sp"
                android:visibility="gone"
                tools:ignore="HardcodedText" />


        </RelativeLayout>

    </RelativeLayout>

    <TextView
        android:id="@+id/amount"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/relativeLayout"
        android:layout_marginBottom="10dp"
        android:background="@color/DateTheme"
        android:gravity="center"
        android:padding="5dp"
        android:textColor="?attr/colorPrimary"
        android:textSize="18sp"
        android:textStyle="" />

    <RelativeLayout
        android:id="@+id/table_header"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/amount">

        <TextView
            android:id="@+id/header_date"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="5dp"
            android:padding="5dp"
            android:text="Date"
            android:textSize="15sp"
            android:textStyle="bold" />

        <TextView
            android:id="@+id/header_vch"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="25dp"
            android:layout_toEndOf="@id/header_date"
            android:padding="5dp"
            android:text="Vch No. / Vch Type"
            android:textSize="15sp"
            android:textStyle="bold" />

        <TextView
            android:id="@+id/header_amt"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentEnd="true"
            android:padding="5dp"
            android:paddingEnd="50dp"
            android:text="Amount"
            android:textSize="15sp"
            android:textStyle="bold" />

    </RelativeLayout>

    <FrameLayout
        android:id="@+id/empty_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:visibility="gone">

        <TextView
            android:id="@+id/ledger_empty_txt"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:text="@string/no_data_available_for_this_ledger"
            android:textSize="15sp" />

    </FrameLayout>

    <android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/swipe"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/table_header">

        <ListView
            android:id="@+id/list"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@android:color/white" />

    </android.support.v4.widget.SwipeRefreshLayout>

</RelativeLayout>

现在,当我单击工具栏中的共享按钮时,它将打开弹出菜单以共享图像或 pdf。在选择图像或 pdf 时,我的方法 shareViaPdfOrImage(String Selection) 被调用,其中选择将包含每个弹出菜单选择的 PDF 或图像字符串。

activity.class

     private void shareViaPdfOrImage(String selection) {
            Bitmap bitmap = takeScreenshot();   //method called to take screen shot here is think my issues is happening.
            saveBitmap(bitmap, selection);

        }

       //This whole method is woking fine so i am not expnading it.
        private void saveBitmap(Bitmap myBitmap, String selection) {
            final String dirPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/myappxyz";

            if (selection.equals("PDF")) {
                createPdf(myBitmap, dirPath);
            } else if (selection.equals("Image")) {
                createImage(myBitmap, dirPath);
            }


        }

 // My issues starts with this method
 private Bitmap takeScreenshot() {
        //View view = getWindow().findViewById(R.id.mainView);
        //  int width = view.getWidth();
        //  int height = view.getHeight();
        RelativeLayout mainView = findViewById(R.id.mainView);
        int childcount = mainView.getChildCount();
        Log.e("childCount", "==>" + childcount);

        ArrayList<Bitmap> bitmaps = new ArrayList<>();
        for (int i = 0; i < childcount; i++) {

            View subview = mainView.getChildAt(i);

            if (subview instanceof SwipeRefreshLayout) {
                Log.e("subview is swipe", "==>" + i);
                bitmaps.add(getWholeListViewItemsToBitmap(listView));

            } else {
                bitmaps.add(Bitmap.createBitmap(subview.getWidth(), subview.getHeight(), Bitmap.Config.ARGB_8888));
            }
            //bitmaps.add(Bitmap.createBitmap(mainView.getChildAt(i).getWidth(), mainView.getChildAt(i).getHeight(), Bitmap.Config.ARGB_8888));


        }



        Bitmap tempbitmap = combineImageIntoOne(bitmaps, mainView);

        Bitmap bitmap = tempbitmap.copy(Bitmap.Config.ARGB_8888, true);

        Canvas canvas = new Canvas(bitmap);
        mainView.layout(0, 0, mainView.getLayoutParams().width, mainView.getLayoutParams().height);
        Drawable bgDrawable = mainView.getBackground();
        if (bgDrawable != null)
            bgDrawable.draw(canvas);
        else
            canvas.drawColor(Color.WHITE);
        mainView.draw(canvas);
        return bitmap;
    }

    private Bitmap combineImageIntoOne(ArrayList<Bitmap> bitmap, RelativeLayout mainView) {
        int w = 0, h = 0;
        for (int i = 0; i < bitmap.size(); i++) {
            if (i < bitmap.size() - 1) {
                w = bitmap.get(i).getWidth() > bitmap.get(i + 1).getWidth() ? bitmap.get(i).getWidth() : bitmap.get(i + 1).getWidth();
            }
            h += bitmap.get(i).getHeight();
        }

        Bitmap temp = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(temp);
        int top = 0;
        for (int i = 0; i < bitmap.size(); i++) {
            //Log.d("HTML", "Combine: "+i+"/"+bitmap.size()+1);

            top = (i == 0 ? 0 : top + bitmap.get(i).getHeight());
            canvas.drawBitmap(bitmap.get(i), 0f, top, null);
            // canvas.drawBitmap(bitmap.get(i), new Matrix(), null);
            //canvas.drawBitmap(bitmap.get(i+1), 0, 0, null);
        }
        //canvas.drawColor(Color.WHITE);

        return temp;
    }

  // This method will get all list items screen shot in one bitmap.
  public Bitmap getWholeListViewItemsToBitmap(ListView p_ListView) {
        ListView listview = p_ListView;
        ListAdapter adapter = listview.getAdapter();
        int itemscount = adapter.getCount();
        int allitemsheight = 0;
        List<Bitmap> bmps = new ArrayList<Bitmap>();
        for (int i = 0; i < itemscount; i++) {
            View childView = adapter.getView(i, null, listview);
            childView.measure(
                    View.MeasureSpec.makeMeasureSpec(listview.getWidth(), View.MeasureSpec.EXACTLY),
                    View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
            childView.layout(0, 0, childView.getMeasuredWidth(), childView.getMeasuredHeight());
            childView.setDrawingCacheEnabled(true);
            childView.buildDrawingCache();
            bmps.add(childView.getDrawingCache());
            allitemsheight += childView.getMeasuredHeight();
        }
        Bitmap bigbitmap = Bitmap.createBitmap(listview.getMeasuredWidth(), allitemsheight,
                Bitmap.Config.ARGB_8888);
        Canvas bigcanvas = new Canvas(bigbitmap);
        //bigcanvas.drawColor(Color.WHITE);

        Paint paint = new Paint();
        int iHeight = 0;
        for (int i = 0; i < bmps.size(); i++) {
            Bitmap bmp = bmps.get(i);
            bigcanvas.drawBitmap(bmp, 0, iHeight, paint);
            iHeight += bmp.getHeight();
            bmp.recycle();
            bmp = null;
        }
        //Long tsLong = System.currentTimeMillis() / 1000;


        return storeImage(bigbitmap);
    }

    //This method will save bitmap and store it in app data and will return a bitmap to the mani method.
    public Bitmap storeImage(Bitmap imageData) {
        // get path to external storage (SD card)
        final String dirPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/myappxyz";

        File dir = new File(dirPath);
        if (!dir.exists())
            dir.mkdirs();

        String fileName = "LastSharedImage.jpg";
        File file = new File(dirPath, fileName);
        try {
            FileOutputStream fOut = new FileOutputStream(file);
            imageData.compress(Bitmap.CompressFormat.PNG, 85, fOut);
            fOut.flush();
            fOut.close();

        } catch (Exception e) {
            e.printStackTrace();
        }

        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inPreferredConfig = Bitmap.Config.ARGB_8888;
        Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath(), options);
        Log.e("AbosolutePath","==>"+file.getAbsolutePath());


        return bitmap;

    }

ISSUE:: 我正在获取最终位图并将其传递以创建 pdf 或图像,但最终的结果是我的位图仅用于当前的视图即使我通过简单地在其中传递一个列表视图,使用 getWholeListViewItemsToBitmap(ListView p_ListView) 方法获取整个列表视图屏幕截图,也是可见的。目前我在屏幕上看到了 10 个可见项目的屏幕截图,以及相对 _main 视图到相对 _tablelayout 的布局,然后是一个长长的白色空白 space,我认为这是一个 space 由于对于屏幕上不可见但在列表视图中的剩余列表视图项目,即使向下滚动到最后也会发生这种情况。各种方法都试过了,还是不行。

注意:: 我在列表视图中有 52 个列表项,在屏幕截图中只有 10-12 个列表项是可见的,它们当前显示在列表视图中。

Reqiurement:: 只需要在 android 端解决这个问题,不想为此使用任何第三方库。

请看下面的代码。

private void shareViaPdfOrImage(String selection) {
        Bitmap bitmap = takeScreenshot();
        saveBitmap(bitmap, selection);
    }

    private void saveBitmap(Bitmap myBitmap, String selection) {
        final String dirPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/tallyandroid";

        if (selection.equals("PDF")) {
            createPdf(myBitmap, dirPath);
        } else if (selection.equals("Image")) {
            createImage(myBitmap, dirPath);
        }
    }

        WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
        Display display = wm.getDefaultDisplay();
        DisplayMetrics displaymetrics = new DisplayMetrics();
        this.getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
        float hight = displaymetrics.heightPixels;
        float width = displaymetrics.widthPixels;

        int convertHighet = (int) hight, convertWidth = (int) width;


        PdfDocument document = new PdfDocument();
        PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo.Builder(myBitmap.getWidth(), myBitmap.getHeight(), 1).create();
        PdfDocument.Page page = document.startPage(pageInfo);

        Canvas canvas = page.getCanvas();


        Paint paint = new Paint();
        paint.setColor(Color.parseColor("#ffffff"));
        canvas.drawPaint(paint);


        myBitmap = Bitmap.createScaledBitmap(myBitmap, myBitmap.getWidth(), myBitmap.getHeight(), true);

        paint.setColor(Color.BLUE);
        canvas.drawBitmap(myBitmap, 0, 0, null);
        document.finishPage(page);


        // write the document content
        File dir = new File(dirPath);
        if (!dir.exists())
            dir.mkdirs();
      // Long tsLong = System.currentTimeMillis() / 1000;

        String fileName = "LastImageShared.pdf";
        File filePath = new File(dirPath, fileName);
        try {
            document.writeTo(new FileOutputStream(filePath));
        } catch (IOException e) {
            e.printStackTrace();
            Toast.makeText(this, "Something wrong: " + e.toString(), Toast.LENGTH_LONG).show();
        }

        // close the document
        document.close();

        //sending broadcast to the system file manager
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            final Intent scanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
            final Uri contentUri = Uri.fromFile(filePath);
            scanIntent.setData(contentUri);
            sendBroadcast(scanIntent);
        } else {
            final Intent intent = new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + Environment.getExternalStorageDirectory()));
            sendBroadcast(intent);
        }

        File outputFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/tallyandroid", fileName);
        sharePdf(outputFile);
    }
    private void shareImg(File dir) {
        try {
            Uri uri = FileProvider.getUriForFile(LedgerTransactionHistoryActivity.this, LedgerTransactionHistoryActivity.this.getApplicationContext().getPackageName() + ".provider", dir);
            Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
            sharingIntent.setType("image/*");
            sharingIntent.putExtra(Intent.EXTRA_STREAM, uri);
            startActivity(Intent.createChooser(sharingIntent, "Share via"));
        } catch (Exception e) {
            Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG).show();
        }

    }

    private void sharePdf(File dir) {
        try {
            progress_dialog.dismiss();
            Uri uri = FileProvider.getUriForFile(LedgerTransactionHistoryActivity.this, LedgerTransactionHistoryActivity.this.getApplicationContext().getPackageName() + ".provider", dir);
            Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
            sharingIntent.setType("application/pdf");
            sharingIntent.putExtra(Intent.EXTRA_STREAM, uri);
            startActivity(Intent.createChooser(sharingIntent, "Share via"));
        } catch (Exception e) {
            Log.e("Error", e.getMessage());
            Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG).show();
        }
    }

    private Bitmap takeScreenshot() {

        RelativeLayout mainView = findViewById(R.id.mainView);
        int childcount = mainView.getChildCount();
        Log.e("childCount", "==>" + childcount);
        ArrayList<Bitmap> bitmaps = new ArrayList<>();
        //bitmaps.add(getBitmapFromView(mainView));
        height = 0;
        for (int i = 0; i < childcount; i++) {
            View subview = mainView.getChildAt(i);
            if (subview.getId() != findViewById(R.id.empty_view).getId()) {
                if (subview instanceof SwipeRefreshLayout) {
                    bitmaps.add(getListViewBitmap(listView));
                } else {
                    bitmaps.add(getBitmapFromView(subview));
                }
            }
        }

        Bitmap bigbitmap = Bitmap.createBitmap(mainView.getMeasuredWidth(), height,
                Bitmap.Config.ARGB_8888);
        Canvas bigcanvas = new Canvas(bigbitmap);
        bigcanvas.drawColor(Color.WHITE);
        Paint paint = new Paint();
        int iHeight = 0;
        for (int i = 0; i < bitmaps.size(); i++) {
            Bitmap bmp = bitmaps.get(i);
            bigcanvas.drawBitmap(bmp, 0, iHeight, paint);
            iHeight += bmp.getHeight();
            bmp.recycle();
            bmp = null;
        }
        return bigbitmap;
    }

    public Bitmap getListViewBitmap(ListView p_ListView) {
        ListView listview = p_ListView;
        ListAdapter adapter = listview.getAdapter();
        int itemscount = adapter.getCount();
        int allitemsheight = 0;
        List<Bitmap> bmps = new ArrayList<Bitmap>();

        for (int i = 0; i < itemscount; i++) {
            View childView = adapter.getView(i, null, listview);
            childView.measure(
                    View.MeasureSpec.makeMeasureSpec(listview.getWidth(), View.MeasureSpec.EXACTLY),
                    View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
            childView.layout(0, 0, childView.getMeasuredWidth(), childView.getMeasuredHeight());

            height = height + childView.getMeasuredHeight();
            childView.setDrawingCacheEnabled(true);
            childView.buildDrawingCache();
            bmps.add(childView.getDrawingCache());
            allitemsheight += childView.getMeasuredHeight();
        }
        Bitmap bigbitmap = Bitmap.createBitmap(listview.getMeasuredWidth(), allitemsheight,
                Bitmap.Config.ARGB_8888);
        Canvas bigcanvas = new Canvas(bigbitmap);
        bigcanvas.drawColor(Color.WHITE);
        Paint paint = new Paint();
        int iHeight = 0;
        for (int i = 0; i < bmps.size(); i++) {
            Bitmap bmp = bmps.get(i);
            bigcanvas.drawBitmap(bmp, 0, iHeight, paint);
            iHeight += bmp.getHeight();
            bmp.recycle();
            bmp = null;
        }
        return bigbitmap;
    }


    public Bitmap getBitmapFromView(View view) {
        Bitmap returnedBitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
        height = height + view.getHeight();
        Canvas canvas = new Canvas(returnedBitmap);
        Drawable bgDrawable = view.getBackground();
        if (bgDrawable != null) bgDrawable.draw(canvas);
        else canvas.drawColor(Color.WHITE);
        view.draw(canvas);
        return returnedBitmap;
    }

检查这段代码,看看位图是否正在合并。在我的上下文中,它肯定会起作用。