欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android View轉(zhuǎn)換為Bitmap實(shí)現(xiàn)應(yīng)用內(nèi)截屏功能

 更新時(shí)間:2022年09月13日 11:15:53   作者:艾陽Blog  
這篇文章主要介紹了Android View轉(zhuǎn)換為Bitmap實(shí)現(xiàn)應(yīng)用內(nèi)截屏功能,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

前言

安卓設(shè)備一般都自帶截圖功能,但是用戶體驗(yàn)有不好之處。就是會(huì)連帶著狀態(tài)欄??、??、時(shí)間日期、其他不必要頁面中信息,等等與用戶想截屏的內(nèi)容不符的信息也會(huì)被保存下來。通常,截圖后用戶會(huì)再次裁剪一次才能想把真正需求分享出去。

因此,咱們技術(shù)研發(fā)會(huì)遇到針對(duì)性的會(huì)做一些應(yīng)用內(nèi)的截屏功能。

一、getDrawingCache

getDrawingCache()是其中一種截圖手段,使用方便,主要針對(duì)應(yīng)用內(nèi)截圖。

1、創(chuàng)建View

fun getShareView() : View {
     val shareView: View =
            LayoutInflater.from(context).inflate(R.layout.share_layout, null)
     //內(nèi)容...
     return  shareView
}

注意:一般大家實(shí)現(xiàn)思路都是點(diǎn)擊事件里進(jìn)行創(chuàng)建View繪制,很可能會(huì)遇到網(wǎng)絡(luò)圖片還未加載完的情況。因此,建議做延遲處理,或在點(diǎn)擊前前置創(chuàng)建好。

2、測(cè)試和繪制

 public static void layoutView(View v, int width, int height) {
        v.layout(0, 0, width, height);
        int measuredWidth = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY);
        int measuredHeight = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY);
        v.measure(measuredWidth, measuredHeight);
        v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
    }

如果不走這個(gè)方法,bitmap轉(zhuǎn)換時(shí)會(huì)沒有視圖(黑屏情況)。

調(diào)用方法:

// 設(shè)置視圖的dp寬高
layoutView(share_view, dp2px(210), dp2px(180));
  public static int dp2px(float dp) {
        float scale = Resources.getSystem().getDisplayMetrics().density;
        return (int) (dp * scale + 0.5f);
    }

3、轉(zhuǎn)換Bitmap

 public static Bitmap getCacheBitmapFromView(View view) {
        final boolean drawingCacheEnabled = true;
        view.setDrawingCacheEnabled(drawingCacheEnabled);
      //設(shè)置背景色  //view.setBackgroundColor(CommonUtils.getContext().getResources().getColor(R.color.half_white));
        view.buildDrawingCache(drawingCacheEnabled);
        final Bitmap drawingCache = view.getDrawingCache();
        Bitmap bitmap;
        if (drawingCache != null) {
            bitmap = Bitmap.createBitmap(drawingCache);
            view.setDrawingCacheEnabled(false);
        } else {
            bitmap = null;
        }
        return bitmap;
    }

二、黑屏問題

一般情況下,上面的代碼能夠正常實(shí)現(xiàn)效果。但有時(shí)候,生成Bitmap會(huì)出現(xiàn)問題(Bitmap全黑色)。主要原因是drawingCache的值大于系統(tǒng)給定的值。我們可以看一下buildDrawingCache()方法中的一段代碼:

    //所要cache的view繪制的寬度和高度
if (width <= 0 || height <= 0 ||
    //計(jì)算的是當(dāng)前所需要的drawingCache 大小
    (width * height * (opaque && !translucentWindow ? 2 : 4) > 
    //得到的是系統(tǒng)所提供的最大的DrawingCache的值
   ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize())) {
    destroyDrawingCache();
    return;
}

當(dāng)所需要的drawingCache > 系統(tǒng)所提供的最大DrawingCache值時(shí),生成Bitmap就會(huì)出現(xiàn)問題,此時(shí)獲取的Bitmap就為null。

所以在只需要修改所需的cache值就可以解決問題了。于是我們引入第二種方法:

解決方案:

public static Bitmap convertViewToBitmap(View view){
    view.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
    view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
    view.buildDrawingCache();
    Bitmap bitmap = view.getDrawingCache();
    return bitmap;
}

view 使用 "getMeasuredWidth()"、 "getMeasuredHeight()"方法計(jì)算長(zhǎng)寬。此時(shí),Bitmap就能正確獲取了。

三、源碼分析

    public void buildDrawingCache() {
        buildDrawingCache(false);
    }
    public Bitmap getDrawingCache() {
        return getDrawingCache(false);
    }
    public Bitmap getDrawingCache(boolean autoScale) {
        if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
            return null;
        }
        if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
            buildDrawingCache(autoScale);
        }
        return autoScale ? mDrawingCache : mUnscaledDrawingCache;
    }   
    public void buildDrawingCache(boolean autoScale) {
        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
                mDrawingCache == null : mUnscaledDrawingCache == null)) {
            if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
                Trace.traceBegin(Trace.TRACE_TAG_VIEW,
                        "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
            }
            try {
                buildDrawingCacheImpl(autoScale);
            } finally {
                Trace.traceEnd(Trace.TRACE_TAG_VIEW);
            }
        }
    }
    private void buildDrawingCacheImpl(boolean autoScale) {
        mCachingFailed = false;
        int width = mRight - mLeft;
        int height = mBottom - mTop;
        final AttachInfo attachInfo = mAttachInfo;
        final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
        if (autoScale && scalingRequired) {
            width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
            height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
        }
        final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
        final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
        final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
        final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
        final long drawingCacheSize =
                ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
        if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
            if (width > 0 && height > 0) {
                Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
                        + " too large to fit into a software layer (or drawing cache), needs "
                        + projectedBitmapSize + " bytes, only "
                        + drawingCacheSize + " available");
            }
            destroyDrawingCache();
            mCachingFailed = true;
            return;
        }
     ..檢測(cè)drawingCache原有數(shù)據(jù)操作..
	    try {
                bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
                        width, height, quality);
                bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
                if (autoScale) {
                    mDrawingCache = bitmap;
                } else {
                    mUnscaledDrawingCache = bitmap;
                }
                if (opaque && use32BitCache) bitmap.setHasAlpha(false);
            } catch (OutOfMemoryError e) {
                // If there is not enough memory to create the bitmap cache, just
                // ignore the issue as bitmap caches are not required to draw the
                // view hierarchy
                if (autoScale) {
                    mDrawingCache = null;
                } else {
                    mUnscaledDrawingCache = null;
                }
                mCachingFailed = true;
                return;
            }
	..執(zhí)行Bitmap寫入autoScale ? mDrawingCache : mUnscaledDrawingCache操作..
    }

從以上源碼中,可以看到getDrawingcache = null的條件共有四個(gè):

1、(mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING為true

2、沒有設(shè)置setDrawingCacheEnabled(true)

3、width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize為true

4、OutOfMemory

除了第一個(gè)條件,其他的都是buildDrawingCache執(zhí)行時(shí)才會(huì)觸發(fā)。下面來分析下條件三。既然子布局可以正常顯示,那么一定是滿足width>0和height>0的, drawingCacheSize肯定是一個(gè)固定值,就是當(dāng)前設(shè)備系統(tǒng)所允許的最大繪制緩存值。projectedBitmapSize的計(jì)算方式為width * height * (opaque && !use32BitCache ? 2 : 4),顧名思義,就是當(dāng)前計(jì)劃緩存的圖片大小,(opaque && !use32BitCache ? 2 : 4)不可能為0,也不可能是導(dǎo)致計(jì)劃緩存值變大的主因,width就是屏幕的寬,這個(gè)沒有變動(dòng)的條件,那么可以肯定就是height出現(xiàn)了異常,對(duì)于視圖高度的計(jì)算,android源碼表示如下:

@ViewDebug.ExportedProperty(category = "layout")
public final int getHeight() {
  return mBottom - mTop;
}

一個(gè)View的高度getHeight()就是底-高,其中mBottom指的是視圖自身的底邊到父視圖頂邊的距離,mTop指的是視圖自身的頂邊到父視圖頂邊的距離。

四、View轉(zhuǎn)Canvas轉(zhuǎn)Bitmap

    Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    view.measure(View.MeasureSpec.makeMeasureSpec(view.getWidth(), View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(view.getHeight(), View.MeasureSpec.EXACTLY));
    view.layout((int) view.getX(), (int) view.getY(), (int) view.getX() + view.getMeasuredWidth(), (int) view.getY() + view.getMeasuredHeight());
    view.draw(canvas);
    return bitmap;

到此這篇關(guān)于Android View轉(zhuǎn)換為Bitmap實(shí)現(xiàn)應(yīng)用內(nèi)截屏功能的文章就介紹到這了,更多相關(guān)Android View轉(zhuǎn)換為Bitmap內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Retrofit之OKHttpCall源碼分析

    Retrofit之OKHttpCall源碼分析

    這篇文章主要介紹了Retrofit之OKHttpCall源碼分析,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-05-05
  • Android中刪除Preference詳解

    Android中刪除Preference詳解

    這篇文章主要介紹了Android中刪除Preference詳解,很多時(shí)候刪除Preference總會(huì)失敗,本文著重分析刪除失敗的原因,需要的朋友可以參考下
    2015-01-01
  • Android如何解決虛擬按鍵欄遮擋問題

    Android如何解決虛擬按鍵欄遮擋問題

    這篇文章主要介紹了Android如何解決虛擬按鍵欄遮擋問題,幫助大家更好的理解和學(xué)習(xí)使用Android開發(fā),感興趣的朋友可以了解下
    2021-03-03
  • Android 下的 QuickJS Binding 庫特性使用詳解

    Android 下的 QuickJS Binding 庫特性使用詳解

    這篇文章主要介紹了Android 下的 QuickJS Binding 庫特性使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • Android OKHttp源碼解析Https安全處理

    Android OKHttp源碼解析Https安全處理

    這篇文章主要為大家介紹了Android OKHttp源碼解析Https安全處理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • Android開發(fā)中使用顏色矩陣改變圖片顏色,透明度及亮度的方法

    Android開發(fā)中使用顏色矩陣改變圖片顏色,透明度及亮度的方法

    這篇文章主要介紹了Android開發(fā)中使用顏色矩陣改變圖片顏色,透明度及亮度的方法,涉及Android針對(duì)圖片的讀取、運(yùn)算、設(shè)置等相關(guān)操作技巧,需要的朋友可以參考下
    2017-10-10
  • Android實(shí)現(xiàn)拍照和錄制視頻功能

    Android實(shí)現(xiàn)拍照和錄制視頻功能

    這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)拍照和錄制視頻功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-05-05
  • Java程序員轉(zhuǎn)Android開發(fā)必讀經(jīng)驗(yàn)一份

    Java程序員轉(zhuǎn)Android開發(fā)必讀經(jīng)驗(yàn)一份

    小編最近幾日偷偷的發(fā)現(xiàn)部分Java程序員想轉(zhuǎn)安卓開發(fā),故此加緊補(bǔ)充知識(shí),為大家搜集資料,積極整理前人的經(jīng)驗(yàn),希望可以給正處于困惑中的你,帶來些許的幫助。
    2017-11-11
  • Android PopupWindow增加半透明蒙層

    Android PopupWindow增加半透明蒙層

    這篇文章主要為大家詳細(xì)介紹了Android PopupWindow增加半透明蒙層,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-10-10
  • Jetpack Compose布局的使用詳細(xì)介紹

    Jetpack Compose布局的使用詳細(xì)介紹

    Jetpack Compose是用于構(gòu)建原生Android界面的新工具包。它可簡(jiǎn)化并加快Android上的界面開發(fā),使用更少的代碼、強(qiáng)大的工具和直觀的 Kotlin API,快速讓應(yīng)用生動(dòng)而精彩
    2022-09-09

最新評(píng)論