整合大量開源庫專案(八)可以載入Gif動畫的GifImageView
上週大多數時間都是根據興起,想到什麼做什麼寫了幾個自定義控制元件,把Soyi丟在那沒怎麼動,今天就把寫的東西整合進來,順便把SOyi”個人研發的結構理一下”。
先上一下今天整合之後的效果,以及新加進來的幾個庫:
按照慣例,貼一下Gradle的配置:
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.1.1'
compile 'cn.pedant.sweetalert:library:1.3'
compile 'com.apkfuns.logutils:library:1.0.6'
compile 'com.nineoldandroids:library:2.4.0'
compile 'com.squareup.okhttp:okhttp:2.7.0'
compile 'commons-io:commons-io:2.4'
compile 'com.ikimuhendis:ldrawer:0.1'
compile 'com.dodola:listviewext:1.0'
compile 'com.bm.photoview:library:1.3.6'
compile 'com.lsjwzh:materialloadingprogressbar:0.5.8-RELEASE'
compile 'net.frakbot:jumpingbeans:1.3.0'
compile 'com.bigkoo:convenientbanner:1.1.4'
compile files('libs/universal-image-loader-1.9.4.jar')
compile 'com.google.code.gson:gson:2.5'
compile 'com.android.support:recyclerview-v7:23.1.+'
compile 'com.felipecsl:gifimageview:2.0.0'
compile 'com.android.support:support-annotations:23.1.1'
}
是不是加進來的東西越來越多了? 之後還會繼續新增(當然,實際專案中不建議使用過多的第三方框架,畢竟大框架的個別功能你是用不到的,而自己卻載入了那麼多內容,容易加大apk無謂的容積)
這一篇我們加了什麼,講些什麼??
GifImageView和簡單的程式碼梳理。(有一定工作經歷的小夥伴可以不看第二部分,原始碼還是在最下面)
通常為我們的ImageView只支援普通的靜態圖片的展現(png,jpg等),如果是動圖什麼的就需要我們自己寫了,但是有人給我們寫好了,為何不用呢?
樓主這邊為大家簡單的分析下這個庫的實現。
public class GifImageView extends ImageView implements Runnable
↑ 繼承於ImageView繼承Runnable,也就是說我們的各種繪畫的操作其實是在多執行緒的環境下進行的。
private final Runnable updateResults = new Runnable() {
@Override
public void run() {
if (tmpBitmap != null && !tmpBitmap.isRecycled()) {
setImageBitmap(tmpBitmap);
}
}
};
判斷暫時的tmpBitmap 不為空,並且沒有被釋放,然後給imageview設定這張圖片,這個方法在handle中被多次傳遞。
private final Runnable cleanupRunnable = new Runnable() {
@Override
public void run() {
if (tmpBitmap != null && !tmpBitmap.isRecycled()) {
tmpBitmap.recycle();
}
tmpBitmap = null;
gifDecoder = null;
animationThread = null;
shouldClear = false;
}
};
↑ 回收tmpBitmap 並且,清空一系列引數。
@Override public void run() {
if (shouldClear) {
handler.post(cleanupRunnable);
return;
}
final int n = gifDecoder.getFrameCount();
do {
for (int i = 0; i < n; i++) {
if (!animating) {
break;
}
//milliseconds spent on frame decode
long frameDecodeTime = 0;
try {
long before = System.nanoTime();
tmpBitmap = gifDecoder.getNextFrame();
frameDecodeTime = (System.nanoTime() - before) / 1000000;
if (frameCallback != null) {
tmpBitmap = frameCallback.onFrameAvailable(tmpBitmap);
}
if (!animating) {
break;
}
handler.post(updateResults);
} catch (final ArrayIndexOutOfBoundsException | IllegalArgumentException e) {
Log.w(TAG, e);
}
if (!animating) {
break;
}
gifDecoder.advance();
try {
int delay = gifDecoder.getNextDelay();
// Sleep for frame duration minus time already spent on frame decode
// Actually we need next frame decode duration here,
// but I use previous frame time to make code more readable
delay -= frameDecodeTime;
if (delay > 0) {
Thread.sleep(framesDisplayDuration > 0 ? framesDisplayDuration : delay);
}
} catch (final Exception e) {
// suppress any exception
// it can be InterruptedException or IllegalArgumentException
}
}
} while (animating);
}
主要實現的run方法,先判斷是否clear,預設false.(也就是animationThread 這條工作執行緒的行為)
然後獲取從檔案讀取的幀的數目(這邊只解釋下主實現類的內容,Gif其實就是幀動畫)
接下來迴圈,開始更替圖片操作(理論上一幀一畫面)
判斷如果正在動畫效果中,就不進行在此迴圈操作(因為可能出現手動呼叫startAnimation()的可能)
接下來就是一幀持續多久,然後替換,然後直到最後一幀的顯示結束,再繼續。
整個包大概 10來個類,大家可以自己有時間詳細讀取。
總結:現對於https://github.com/frapontillo/ImageViewEx的實現屬於比較輕量級的了,畢竟簡單實用是大家更喜歡的。實現大致就是根據傳入的陣列進行計算,把每一幀的動畫進行迭代的呈現在UI介面上,然後在呼叫StopAnimation()或者clear()之前會形成一個環。當然這樣的頻繁刷UI介面還是會有一定的效能影響,看你怎麼使用了。
接下來再說下“個人研發”模組,那這是什麼東西呢?
很顯然看上去就是一個ListView套著一個ListView然後第一層的ListView的選擇會讓第二層的內容大不相同,像這樣。
那麼難道,我去寫一大堆新的xml麼?
No,找共同點,遵循OOP會發現共同點。
統一的item,統一的呈現頁面(一個Title,1個展示圖,一個文字描述,一個超級連結)
那就是基本的MVC模式我們在 View,Controller層面的內容是大致相同的那麼就只要在Model層做出一些改變就好了,那麼從頭到尾 我 只需要一個佈局檔案,像這樣
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".Activity.CodeActivityPro.CodeActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/codeListView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:choiceMode="singleChoice"
android:scrollbars="none"
android:layoutAnimation="@anim/code_item_anim" />
</RelativeLayout>
然後就是展示頁面,像這樣
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="soyi.pro.com.soyi.Activity.CodeActivityPro.ShowCodeViewActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.felipecsl.gifimageview.library.GifImageView
android:id="@+id/showCodeViewImage"
android:layout_gravity="center"
android:layout_width="350dp"
android:layout_height="450dp"
android:src="@drawable/tempimage"/>
<TextView
android:layout_marginTop="30dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="載入中..."
android:textSize="20dp"
android:id="@+id/jumpText"
android:layout_alignBottom="@id/showCodeViewImage"
android:layout_gravity="center"/>
</LinearLayout>
</ScrollView>
其他一系列就從arrays.xml裡面獲取內容就好了當然,傳遞通過intent.putExtra
,或者如果要2層都做在一個頁面裡那就設定點靜態變數什麼的,記錄使用者的選擇吧。
如何讓你的TextView可以變為連結?
textView.setText(Html.fromHtml(getIntent().getStringExtra("CodeActivityToShowCodeActivityMSG") +"<br><a href=\""+getIntent().getStringExtra("CodeActivityToShowCodeActivityGitUrl")+"\">點選連結可訪問專案地址</a>"));
textView.setMovementMethod(LinkMovementMethod.getInstance());
記得點個贊哦!