代码之家  ›  专栏  ›  技术社区  ›  Wackaloon

将多个TextView保存为大分辨率图像

  •  2
  • Wackaloon  · 技术社区  · 9 年前

    情境:我有一张图片,用户可以在上面添加文本,更改颜色、大小、位置、旋转、字体大小等,我需要将所有文本保存在一张图片中。没关系,我正在使用绘图缓存保存它们。

       //RelativeLayout layout - layout with textviews
        layout.setDrawingCacheEnabled(true);
        Bitmap bitmap = null;
        if (layout.getDrawingCache() != null)
            bitmap = Bitmap.createBitmap(layout.getDrawingCache());
        layout.setDrawingCacheEnabled(false);
    

    问题:由于用户设备的屏幕大小,结果图像可能较小。我需要分辨率为1500-2000像素的图像。如果只是调整图像的大小,文本看起来很模糊,不像屏幕上显示的那么好。

    问:有没有其他方法可以将文本视图保存为图像,而不需要调整大小和降低文本质量?

    1 回复  |  直到 9 年前
        1
  •  2
  •   Community CDub    8 年前

    好的,我终于找到了可行的解决方案。

    想法是:用户在800x800像素大小的图像上添加文本视图,对其进行一些处理,然后我需要得到相同的图像,但尺寸为2000x2000像素。问题是,调整文本大小后,文本变得模糊而嘈杂。但是,我如何才能拍摄比屏幕更大的未渲染视图的屏幕截图呢?

    这里的代码,我使用的,它工作得很好,我得到了相同的图像,文本在相同的位置,相同的大小等,但没有调整大小的噪音,文本看起来清晰而不模糊。此外,此代码保存的位图比屏幕大小大得多,并且不会显示给用户。

    private Bitmap makeTextLayer(int maxWidth, int maxHeight, ImageObject imageObject) {
            Context c = mContext;
            View v = LayoutInflater.from(c).inflate(R.layout.text_view_generator, new LinearLayout(c), false);
            RelativeLayout editTexts = (RelativeLayout) v.findViewById(R.id.editTexts);
    
            initView(v, maxWidth, maxHeight);
    
            for (int i = 0; i < imageObject.getEditTexts().size(); ++i) {
                ImageObject.TextInImage textInImage = imageObject.getEditTexts().get(i);
                //text view in relative layout - init his size, in my case it's as big as image
                CustomEditText editText = new CustomEditText(c);
                RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.FILL_PARENT, RelativeLayout.LayoutParams.FILL_PARENT);
                params.addRule(RelativeLayout.CENTER_HORIZONTAL, RelativeLayout.TRUE);
                // don't forget to add your view to layout, this view will be saved as screenshot
                editTexts.addView(editText, params);
                editText.getLayoutParams().width = maxWidth;
                editText.getLayoutParams().height = maxHeight;
                editText.loadTextParams(textInImage);
                editText.loadSizeAndRotation(textInImage);
                // this is important, without new init - position of text will be wrong
                initView(v, maxWidth, maxHeight);
                // and here i configure position
                editText.loadPosition();
            }
    
            Bitmap result = getViewBitmap(v, maxWidth, maxHeight);
            return result;
        }
    
        Bitmap getViewBitmap(View v, int maxWidth, int maxHeight) {
            //Get the dimensions of the view so we can re-layout the view at its current size
            //and create a bitmap of the same size
            int width = v.getWidth();
            int height = v.getHeight();
    
            int measuredWidth = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY);
            int measuredHeight = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY);
    
            //Cause the view to re-layout
            v.measure(measuredWidth, measuredHeight);
            v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
    
            //Create a bitmap backed Canvas to draw the view into
            Bitmap b = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
            Canvas c = new Canvas(b);
    
            //Now that the view is laid out and we have a canvas, ask the view to draw itself into the canvas
            v.draw(c);
    
            return b;
        }
    
        private void initView(View view,  int maxWidth, int maxHeight){
            ViewGroup.LayoutParams vParams = view.getLayoutParams();
            //If the View hasn't been attached to a layout, or had LayoutParams set
            //return null, or handle this case however you want
            if (vParams == null) {
                return;
            }
            int wSpec = measureSpecFromDimension(vParams.width, maxWidth);
            int hSpec = measureSpecFromDimension(vParams.height, maxHeight);
            view.measure(wSpec, hSpec);
            int width = view.getMeasuredWidth();
            int height = view.getMeasuredHeight();
            //Cannot make a zero-width or zero-height bitmap
            if (width == 0 || height == 0) {
                return;
            }
            view.layout(0, 0, width, height);
        }
    
        private int measureSpecFromDimension(int dimension, int maxDimension) {
            switch (dimension) {
                case ViewGroup.LayoutParams.MATCH_PARENT:
                    return View.MeasureSpec.makeMeasureSpec(maxDimension, View.MeasureSpec.EXACTLY);
                case ViewGroup.LayoutParams.WRAP_CONTENT:
                    return View.MeasureSpec.makeMeasureSpec(maxDimension, View.MeasureSpec.AT_MOST);
                default:
                    return View.MeasureSpec.makeMeasureSpec(dimension, View.MeasureSpec.EXACTLY);
            }
        }
    

    我要感谢这些帖子中评论的作者:

    Converting a view to Bitmap without displaying it in Android?

    Taking a "screenshot" of a specific layout in Android

    Take a screenshot of a whole View

    Capture whole scrollview bigger than screen

    How to screenshot or snapshot a view before it's rendered?

    我在阅读它们时找到了我的解决方案,如果我的解决办法对你不起作用,请查看这篇文章。

    推荐文章