Material過渡+Glide顯示問題踩坑

大家好,我系蒼王。
以下是我這個系列的相關(guān)文章,有興趣可以參考一下,可以給個喜歡或者關(guān)注我的文章。

[Android]如何做一個崩潰率少于千分之三噶應(yīng)用app--章節(jié)列表

Android組件化架構(gòu)熱賣中

這里說的坑的情況是使用了Material過渡+Glide顯示圖片的情況。

1.使用了Material過渡+Glide的圖片顯示Bitmap能正常過渡的。

2.如果Glide加載圖片加入圓角的Transform,此時glide過渡到新的顯示頁沒問題,back鍵返回首先顯示原圖(不帶圓角)然后再顯示圓角,這是感覺會被刷新了一下。這里可以直接用圓角的ImageView來處理,用shape是無效的。

3.如果glide加載的是gif圖片,這里使用是要使用asGif提示Glide加載的是gif圖。使用material過渡效果,會發(fā)現(xiàn),gif圖會被卡住不顯示動圖,只顯示當(dāng)前幀,使用調(diào)試后卻了顯示動圖的情況。如果延遲顯示也是能正常顯示動圖,但是中間會有一段時間黑屏需要用loading處理。如果gif圖加上圓角,不要使用自定義擴(kuò)展ImageView作為圓角View,這樣gif圖會播放不了,最好使用原生的Glide Transform+ImageView。

4.如果使用glide加載mp4,能正常顯示首幀,但是如果使用了material過渡,使用google的exoplayer會發(fā)現(xiàn)開始的一秒視頻無法正常播放,拉回去發(fā)現(xiàn)是可以播放出來的,這里估計是繪制繁忙導(dǎo)致的,這里還是得自行延遲處理或者換回正常的過渡方式了。

5.使用獲取視頻首幀的問題,這里如果是網(wǎng)絡(luò)視頻最好是上傳信息時,已經(jīng)將首幀的圖上傳服務(wù)器,不然需要在線獲取視頻的首幀資源。如果視頻經(jīng)過加密處理,那么只能先緩存到本地才能完成,所以這種折騰太過耗時,請設(shè)計協(xié)議時一定要設(shè)計上傳視頻預(yù)覽圖。

/**
     * 通過url去獲取視頻的第一幀
     * Android 原生給我們提供了一個MediaMetadataRetriever類
     * 提供了獲取url視頻第一幀的方法,返回Bitmap對象
     *
     * @param videoUrl
     * @return
     */
    fun getPreviewFromUri(uri: String?, result: (url: String?, previewPath: String?) -> Unit) {
        if (uri == null) {
            return result(null, null)
        }
        val tmpPath = Environment.getExternalStorageDirectory().toString() + File.separator + "XXX/cache/" + EncryptUtils.encryptMD5ToString(uri)  //這里用Sring轉(zhuǎn)md5作為唯一標(biāo)識
        if (File(tmpPath).exists()) {   //判斷圖片是否存在
            return result(uri, tmpPath)
        }

        Observable.create(ObservableOnSubscribe<String> {
            var bitmap: Bitmap? = null
            val retriever = MediaMetadataRetriever()  //原生取幀圖
            try {
                val resourceUri = uri.trim()
                if (resourceUri.startsWith("http", true)) {
                    retriever.setDataSource(uri, HashMap())
                } else {
                    retriever.setDataSource(uri)
                }
                bitmap = retriever.frameAtTime    //獲取第一幀關(guān)鍵幀
            } catch (e: IllegalArgumentException) {
                e.printStackTrace()
            } finally {
                retriever.release()
            }


            var path: String? = null
            if (null != bitmap) {
                path = saveBitmap2File(bitmap, EncryptUtils.encryptMD5ToString(uri))  //保存到本地
            }

            if (null != path) {
                it.onNext(path)
            } else {
                it.onError(Exception("loading bitmap failed"))
            }
            it.onComplete()
        }).subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe({
                    result(uri, it)
                }, {
                    result(uri, null)
                })
    }

    /**
     * 獲取本地視頻的第一幀
     *
     * @param uri 本地uri地址
     * @return 預(yù)覽圖地址
     */
    fun getLocalVideoBitmap(context: Context, uri: Uri?, result: (uri: Uri?, previewPath: String?) -> Unit) {
        if (uri == null) {
            return result(null, null)
        }
        val tmpPath = Environment.getExternalStorageDirectory().toString() + File.separator + "XXX/cache/" + EncryptUtils.encryptMD5ToString(uri.toString())
        if (File(tmpPath).exists()) {
            return result(uri, tmpPath)
        }

        val videoPath = FileUtils.getFileAbsolutePath(context, uri)
        var bitmap: Bitmap? = null
        val retriever = MediaMetadataRetriever()
        try {
            //根據(jù)文件路徑獲取縮略圖
            retriever.setDataSource(videoPath)
            //獲得第一幀圖片
            bitmap = retriever.frameAtTime
        } catch (e: IllegalArgumentException) {
            e.printStackTrace()
        } finally {
            retriever.release()
        }
        var imgPath: String? = null
        if (null != bitmap) {
            imgPath = saveBitmap2File(bitmap, EncryptUtils.encryptMD5ToString(uri.toString()))
        }

        return result(uri, imgPath)
    }

//保存圖片到本地
    fun saveBitmap2File(bitmap: Bitmap, imgName: String): String? {
        val dir = Environment.getExternalStorageDirectory().toString() + File.separator + "XXX/cache/"
        if (!File(dir).exists()) {
            File(dir).mkdirs()
        }
        val path = dir + imgName
        val file = File(path)
        var out: FileOutputStream? = null
        try {
            out = FileOutputStream(file)
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, out)
            return path
        } catch (e: Exception) {
            e.printStackTrace()
        } finally {
            try {
                out?.close()
            } catch (e: IOException) {
                e.printStackTrace()
            }
        }
        return null
    }

6.如果上傳的圖片是二進(jìn)制流格式,需要使用讀取文件的前幾個字節(jié)來判斷圖片的格式。

 /**
     * 判斷文件類型
     */
    @Throws(IOException::class)
    fun getType(filePath: String): FileType? {

        var fileHead: String? = getFileHeader(filePath)
        if (fileHead == null || fileHead.isEmpty()) {
            return null
        }
        fileHead = fileHead.toUpperCase()
        val fileTypes = FileType.values()
        for (type in fileTypes) {
            if (fileHead.startsWith(type.value)) {
                return type
            }
        }
        return null
    }

enum class FileType constructor(value: String) {
        JPEG("FFD8FF"),
        PNG("89504E47"),
        GIF("47494638"),
        TIFF("49492A00"),
        RTF("7B5C727466"),
        DOC("D0CF11E0"),
        XLS("D0CF11E0"),
        MDB("5374616E64617264204A"),
        BMP("424D"),
        DWG("41433130"),
        PSD("38425053"),
        XML("3C3F786D6C"),
        HTML("68746D6C3E"),
        PDF("255044462D312E"),
        ZIP("504B0304"),
        RAR("52617221"),
        WAV("57415645"),
        AVI("41564920");

        var value = ""
        init {
            this.value = value
        }
 }

7.glide的override指定圖片大小和imageView指定大小,最后會是imageView最后生效,對圖片有拉伸的效果。如果圖片是在RecylverView且圖片適配使用wrap_content的情況,RecylerView有可能調(diào)整被移動。

如果有其他情況,將會在這里補(bǔ)充,遇到其他問題的童孩,也可以留言,謝謝。

Android組件化群2
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,094評論 25 709
  • <站位:中>親愛的頭馬小伙伴們,我的前半生(熱點)一路走過來,做了很多三分鐘熱度的事情! <站位:左>“學(xué)開車”三...
    大萌在路上閱讀 271評論 0 0
  • 一、柵格圖形和矢量圖形柵格圖形:也稱位圖,圖像由一組二維像素網(wǎng)格表示。Canvas 2d API 就是一款柵格圖形...
    linda102閱讀 1,215評論 0 4
  • 我家的狗死了,就在一八年二月四號的那個晚上。 坦白地講,聽見這個噩耗我是不信的,畢竟她才三歲半,用狗命年算她正是青...
    浩瀚星空下是寂寞的海閱讀 858評論 0 1

友情鏈接更多精彩內(nèi)容