2015-11-14 63 views
0

我正在嘗試用文本保存圖像。 要做到這一點,我使用位圖和畫布,但保存的圖像不清晰,所以我想這個解決方案是否可以加載相對視圖而不顯示它?

How do I convert a RelativeLayout with an Imageview and TextView to a PNG image?

現在這個事情是工作的罰款和圖像質量也不錯,但有一個問題

RelativeLayout relativeLayout = (RelativeLayout)findViewById(R.id.relativeLayout); 
    TextView textView = (TextView)relativeLayout.findViewById(R.id.quote); 
    textView.setText("My custom Text adding to Image hare ram"); 

    Bitmap bitmap = Bitmap.createBitmap(relativeLayout.getWidth(), relativeLayout.getHeight(), Bitmap.Config.ARGB_8888); 
    Canvas c = new Canvas(bitmap); 
    relativeLayout.draw(c); 

    new SaveToGalary(bitmap) 

但現在,如果我嘗試編輯此相對佈局這被反映在屏幕上, 有沒有什麼辦法讓我能得到這個觀點 或 的副本我可以加載一個佈局,不是顯示正確的沒有W上。 比如我會做

RelativeLayout relativeLayout = (RelativeLayout)findViewById(R.id.to_save_layout); 
    TextView textView = (TextView)relativeLayout.findViewById(R.id.quote); 
    textView.setText("My custom Text adding to Image hare ram"); 

    Bitmap bitmap = Bitmap.createBitmap(relativeLayout.getWidth(), relativeLayout.getHeight(), Bitmap.Config.ARGB_8888); 
    Canvas c = new Canvas(bitmap); 
    relativeLayout.draw(c); 

    new SaveToGalary(bitmap) 

在這裏,我將創建我將不顯示,但只是把它保存圖像的佈局。我試過這個,但這是給我空指針異常。

回答

0

邁克給了一個完美的答案,總結起來,我們可以做

public void GenerateImageRelative() 
{ 
    LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
    View view = inflater.inflate(R.layout.to_save_image, null); 

    RelativeLayout relativeLayout = (RelativeLayout)view.findViewById(R.id.to_save_image_relative); 

    Bitmap bitmap = getLayoutRender(view, -1, -1); 
    Canvas c = new Canvas(bitmap); 
    relativeLayout.draw(c); 

    new SaveToGalary().insertImage(getContentResolver(),bitmap,"man","ram"); 
} 

private Bitmap getLayoutRender(View rootView, int width, int height) { 

    TextView textView = (TextView)rootView.findViewById(R.id.quote_to_save); 
    textView.setText("My custom Text adding to Image hare ram"); 
    // Here you can call findViewById() on rootView just like usual 
    // to get references to Views you want to change. 
    Display display = getWindowManager().getDefaultDisplay(); 
    int w,h; 
    if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB_MR2) { 
     w = width < 0 ? display.getWidth():width; 
     h = height < 0 ? display.getHeight() : height; 
    } else { 
     Point size = new Point(); 
     display.getSize(size); 
     w = width < 0 ?size.x: width; 
     h = height < 0 ?size.y:height; 
    } 
    rootView.measure(View.MeasureSpec.makeMeasureSpec(w, View.MeasureSpec.EXACTLY), 
      View.MeasureSpec.makeMeasureSpec(h, View.MeasureSpec.EXACTLY)); 

    rootView.layout(0, 0, rootView.getMeasuredWidth(), rootView.getMeasuredHeight()); 

    rootView.setDrawingCacheEnabled(true); 
    rootView.buildDrawingCache(); 
    Bitmap bmp = rootView.getDrawingCache(); 

    return bmp; 
} 

,並保存圖像庫

import android.content.ContentResolver; 
import android.content.ContentUris; 
import android.content.ContentValues; 
import android.graphics.Bitmap; 
import android.graphics.Matrix; 
import android.net.Uri; 
import android.provider.MediaStore; 

import java.io.FileNotFoundException; 
import java.io.IOException; 
import java.io.OutputStream; 


public class SaveToGalary { 

public static final String insertImage(ContentResolver cr, Bitmap source, String title, String description) { 
    ContentValues values = new ContentValues(); 
    values.put(MediaStore.Images.Media.TITLE, title); 
    values.put(MediaStore.Images.Media.DISPLAY_NAME, title); 
    values.put(MediaStore.Images.Media.DESCRIPTION, description); 
    values.put(MediaStore.Images.Media.MIME_TYPE, "image/png"); 
    // Add the date meta data to ensure the image is added at the front of the gallery 
    values.put(MediaStore.Images.Media.DATE_ADDED, System.currentTimeMillis()); 
    values.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis()); 

    Uri url = null; 
    String stringUrl = null; /* value to be returned */ 

    try { 
     url = cr.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); 

     if (source != null) { 
      OutputStream imageOut = cr.openOutputStream(url); 
      try { 
       source.compress(Bitmap.CompressFormat.PNG, 100, imageOut); 
      } finally { 
       imageOut.close(); 
      } 

      long id = ContentUris.parseId(url); 
      // Wait until MINI_KIND thumbnail is generated. 
      Bitmap miniThumb = MediaStore.Images.Thumbnails.getThumbnail(cr, id, MediaStore.Images.Thumbnails.MINI_KIND, null); 
      // This is for backward compatibility. 
      storeThumbnail(cr, miniThumb, id, 50F, 50F, MediaStore.Images.Thumbnails.MICRO_KIND); 
     } else { 
      cr.delete(url, null, null); 
      url = null; 
     } 
    } catch (Exception e) { 
     if (url != null) { 
      cr.delete(url, null, null); 
      url = null; 
     } 
    } 

    if (url != null) { 
     stringUrl = url.toString(); 
    } 

    return stringUrl; 
} 

/** 
* A copy of the Android internals StoreThumbnail method, it used with the insertImage to 
* populate the android.provider.MediaStore.Images.Media#insertImage with all the correct 
* meta data. The StoreThumbnail method is private so it must be duplicated here. 
* @see android.provider.MediaStore.Images.Media (StoreThumbnail private method) 
*/ 
private static final Bitmap storeThumbnail(
     ContentResolver cr, 
     Bitmap source, 
     long id, 
     float width, 
     float height, 
     int kind) throws FileNotFoundException { 

    // create the matrix to scale it 
    Matrix matrix = new Matrix(); 

    float scaleX = width/source.getWidth(); 
    float scaleY = height/source.getHeight(); 

    matrix.setScale(scaleX, scaleY); 

    Bitmap thumb = Bitmap.createBitmap(source, 0, 0, 
      source.getWidth(), 
      source.getHeight(), matrix, 
      true 
    ); 

    ContentValues values = new ContentValues(4); 
    values.put(MediaStore.Images.Thumbnails.KIND,kind); 
    values.put(MediaStore.Images.Thumbnails.IMAGE_ID,(int)id); 
    values.put(MediaStore.Images.Thumbnails.HEIGHT,thumb.getHeight()); 
    values.put(MediaStore.Images.Thumbnails.WIDTH,thumb.getWidth()); 

    Uri url = cr.insert(MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, values); 

    try { 
     OutputStream thumbOut = cr.openOutputStream(url); 
     thumb.compress(Bitmap.CompressFormat.JPEG, 100, thumbOut); 
     thumbOut.close(); 
     return thumb; 
    } catch (FileNotFoundException ex) { 
     return null; 
    } catch (IOException ex) { 
     return null; 
    } 
} 

}

1

有沒有什麼辦法讓我不能在任何方便的方式獲得這一觀點

的副本,考慮你會改變所包含View秒。

我可以加載這是不正確的,現在顯示的佈局

是。可以加載離屏的View層次結構,並強制它將自身渲染到其繪圖緩存中。由於此佈局未顯示在屏幕上,因此必須提供所需的寬度和高度,因爲這些佈局通常是在佈局過程中確定的。

以下是我以前使用過的方法,稍作修改以更好地適合您的情況。

public static final int USE_SCREEN_DIM = -1; 

public static Bitmap getLayoutRender(Context context, int layoutId, int width, int height) { 
    View rootView = LayoutInflater.from(context).inflate(layoutId, null); 

    // Here you can call findViewById() on rootView just like usual 
    // to get references to Views you want to change. 

    WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 
    Display display = wm.getDefaultDisplay(); 

    int w = 0; 
    int h = 0; 

    if(Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB_MR2) { 
     w = width < 0 ? display.getWidth() : width; 
     h = height < 0 ? display.getHeight() : height; 
    } 
    else { 
     Point dims = new Point(); 
     display.getSize(dims); 

     w = width < 0 ? dims.x : width; 
     h = height < 0 ? dims.y : height; 
    } 

    rootView.measure(MeasureSpec.makeMeasureSpec(w, MeasureSpec.EXACTLY), 
        MeasureSpec.makeMeasureSpec(h, MeasureSpec.EXACTLY)); 
    rootView.layout(0, 0, rootView.getMeasuredWidth(), rootView.getMeasuredHeight()); 

    rootView.setDrawingCacheEnabled(true); 
    rootView.buildDrawingCache(); 
    Bitmap bitmap = Bitmap.createBitmap(rootView.getDrawingCache()); 

    return bmp; 
} 

在修正的方法中,爲寬度或高度傳遞負數將導致使用屏幕的尺寸。否則,您傳遞的寬度/高度就是您確定的確切度量。

+0

簡直妙不可言,有什麼辦法將高度和寬度設置爲match_parent,因爲硬編碼是不可銷售的?謝謝 –

+0

不是。由於佈局不在屏幕上,因此它沒有父項,所以'match_parent'是沒有意義的。如果你想要它的大小,這很容易,我會編輯我的答案,以顯示一個方法來做到這一點。如果您希望將其與屏幕上的視圖大小相匹配,則必須在繪製後獲取該視圖的尺寸。 –

+0

我已經更新了我的答案。請注意'MeasureSpec.makeMeasureSpec()'調用中的參數更改。 –

相關問題