作者:蒼王 時間:2018.7.12 以下是我這個系列的相關文章,有興趣可以參考一下,可以給個喜歡或者關注我的文章。
[Android]如何做一個崩潰率少於千分之三噶應用app--章節列表
這裡說的坑的情況是使用了Material過渡+Glide顯示圖片的情況。
1.使用了Material過渡+Glide的圖片顯示Bitmap能正常過渡的。
2.如果Glide載入圖片加入圓角的Transform,此時glide過渡到新的顯示頁沒問題,back鍵返回首先顯示原圖(不帶圓角)然後再顯示圓角,這是感覺會被重新整理了一下。這裡可以直接用圓角的ImageView來處理,用shape是無效的。
3.如果glide載入的是gif圖片,這裡使用是要使用asGif提示Glide載入的是gif圖。使用material過渡效果,會發現,gif圖會被卡住不顯示動圖,只顯示當前幀,使用除錯後卻了顯示動圖的情況。如果延遲顯示也是能正常顯示動圖,但是中間會有一段時間黑屏需要用loading處理。如果gif圖加上圓角,不要使用自定義擴充套件ImageView作為圓角View,這樣gif圖會播放不了,最好使用原生的Glide Transform+ImageView。
4.如果使用glide載入mp4,能正常顯示首幀,但是如果使用了material過渡,使用google的exoplayer會發現開始的一秒視訊無法正常播放,拉回去發現是可以播放出來的,這裡估計是繪製繁忙導致的,這裡還是得自行延遲處理或者換回正常的過渡方式了。
5.使用獲取視訊首幀的問題,這裡如果是網路視訊最好是上傳資訊時,已經將首幀的圖上傳伺服器,不然需要線上獲取視訊的首幀資源。如果視訊經過加密處理,那麼只能先快取到本地才能完成,所以這種折騰太過耗時,請設計協議時一定要設計上傳視訊預覽圖。
/**
* 通過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轉md5作為唯一標識
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 //獲取第一幀關鍵幀
} 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 預覽圖地址
*/
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 {
//根據檔案路徑獲取縮圖
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.如果上傳的圖片是二進位制流格式,需要使用讀取檔案的前幾個位元組來判斷圖片的格式。
/**
* 判斷檔案型別
*/
@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有可能調整被移動。
如果有其他情況,將會在這裡補充,遇到其他問題的童孩,也可以留言,謝謝。
天星技術團QQ:557247785。