發表文章

目前顯示的是有「kotlin」標籤的文章

Android shared element transition

圖片
Shared Element 什麼是共享元素?從單一意義上講,共享元素是在兩個不同 Activity 或 Fragment 中存在的一對 View。這些 View 顯示相同的信息,例如文字或圖像,但它們在螢幕上的大小或位置可能不同。為了在切換畫面期間有保留視圖的錯覺,可以使用過渡來移動和重塑第一個 View,使其“成為”第二個 View。由於共享元素實際上包含兩個不同的視圖,實際上來講,並不是真正的共享它們。 現在,可以使用共享元素轉換來實現;但是這裡有個限制。此過渡效果僅在運行在Lollipop(Android 5.0 – API級別21)及更高版本上的設備上可用。 Android 5.0中引入了共享元素過渡,讓跨螢幕的 View 過渡更加無縫且易於實現。使用此過渡,“Activity”或“Fragment”之間的切換似乎更加自然且不受約束。 現在,讓我們來看看如何實現共享元素過渡 Step 1:Enable Window Content Transitions in styles.xml <!-- Base application theme. --> <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <!-- enable window content transitions --> <item name="android:windowContentTransitions">true</item> </style> Step 2: Set a Common Transition Name for Respective Views on Both Screens 在兩個佈局中的共享元素設定一個共同的 transitionName,View不必具有相同的 id,只需要transitionName 相同 在activity_home.xml中: <LinearLayout ...> <ImageView android:id="@+id/iv_list_object_image

Android Navigation 學習筆記

圖片
為什麼要用Navigation? 當你專案中的頁面越來越多,Fragment和Activity之間的跳轉越來越繁雜,是不是搞得你一團亂呢?你是否羨慕Xcode中能將頁面跳轉視覺化的Storyboard呢? Xcode Storyboard 好在Google終於提供了Navigation套件來幫我們處理這些問題,讓我們一起來試玩看看吧。 Android Navigation Graph 環境設定 如果你的Android Studio版本是3.2的話,必須到Setting將Navigation Editor打開,3.3以上版本無需此動作 enable Navigation Editor dependencies 首先設定module層的build.gradle,我的Demo會用androidx的版本示範 androidx version dependencies { implementation "androidx.navigation:navigation-fragment:2.0.0" implementation "androidx.navigation:navigation-ui:2.0.0" } 新建三個Fragment class MainPage1Fragment : Fragment() { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { return inflater.inflate(R.layout.fragment_main_page1, container, false) } } class MainPage2Fragment : Fragment() { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,

Kotlin - dagger 2

Dependencies Project build.gradle buildscript { ext.dagger_version = '2.5' } App build.gradle apply plugin: 'kotlin-kapt' dependencies { implementation "com.google.dagger:dagger:$dagger_version" kapt "com.google.dagger:dagger-compiler:$dagger_version" } 下面我們直接來看一個範例: 我這邊使用四個Model,分別為Model A B C D ModelA 裡面包含了 B跟C ModelC 裡面包含了 D 先看ModelA: class ModelA @Inject constructor(val context: Context, var modelB: ModelB, var modelC: ModelC){ var somethingData: String = "modelA haha " fun print() { Log.d("ModelA", somethingData + modelB.somethingData + modelC.somethingData) } } 傳入的context,實際上沒用到只是純粹練習  print()  會印出ModelA的data,data會將ABC的data加起來 ModelB: class ModelB @Inject constructor(){ var somethingData: String = "modelB haha " } ModelC: class ModelC @Inject constructor(modelD: ModelD){ var somethingData: String = "modelC haha " + modelD.somethingData

Kotlin - 實現Android中的Parcelable

圖片
使用 Parcelable 的最基本用例是當我們需要將模型從一個活動傳遞到另一個活動時。當傳遞原始類型時,很簡單,但是當我們想要傳遞自己的對象時,我們需要對它們做一些事情: class ActivityA : Activity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val intent = Intent(this, ActivityB::class.java) val person = Person("name", 32, "email@email.com", 1234) intent.putExtra("A_STRING", "some string") intent.putExtra("A_NUMBER", 1234) intent.putExtra("AN_OBJECT", person) // compilation error startActivity(intent) } } 如果我們認為我們使用的 Person 對象與上一篇文章相同,則會在第11行收到編譯錯誤,因為我們無法照原樣傳遞 Person 模型。 我們的模型不符合以上任何條件,因此我們需要對此做些事情,我們有一些選擇: Implement Serializable: 希望您不再這樣做,儘管它有效且易於實施,但由於它基於反射,因此性能相當差。 Json String representation : 您也可以這樣做,並將模型作為String傳遞。同樣,這也非常簡單,特別是如果您已經Gson在項目中使用了類似功能,但又不是最佳選擇。 Implement Parcelable: 這顯然是正確的答案。根據官方文檔,這是推薦的方式。它也適用於   marshalling/unmarshallingJava 對象,例如序列化,但性能更高。 因此,Parcelable是最好

Android Coroutine Recipes

圖片
本文的原始碼可以在 YangQiRen/coroutine-recipes 中找到 基於Coroutine v1.0.0版本 引入依賴 implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.0.0' implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.0' 如何啟動協程(Coroutine) 在 kotlinx.coroutines 庫中,您可以使用 launch 或 async 函數來啟動新的協程。 從概念上講, async 就像 launch 。它啟動一個單獨的協程,這是一個輕量級線程,可與所有其他協程同時工作。區別在於, launch 返回一個 Job 且不攜帶任何結果值,而 async 返回一個 Deferred 輕量無阻塞的未來,表示希望稍後提供結果。您可以使用 .await() 延期的值來獲得其最終結果,但是 Deferred 它也是一個 Job ,因此可以根據需要取消它。 ***重點*** 如果裡面的代碼 launch 以異常終止,然後將其視為未捕獲線程中的異常會使Android應用程序崩潰。內部未捕獲的異常 async 代碼存儲在結果中 Deferred 並且不會在其他任何地方交付,除非經過處理,否則它將被靜默丟棄。 協程調度員(Coroutine Dispatcher) 在Android中,我們通常使用兩個調度程序: uiDispatcher將執行分派到Android主UI線程(用於父協程)。 bgDispatcher在後台線程中分派執行(用於子協程)。 //將執行分派到Android主線程中 val uiDispatcher:CoroutineDispatcher = Dispatchers.Main //將共享線程池表示為協程分派器 val bgDispatcher:CoroutineDispatcher = Dispatchers.I0 在下面的例子中,我們將使用 CommonPool 用於 bgContext 這限制並行運行為值64個線程或核的數量

Kotlin - Convert Unix Timestamp to Date 時間戳記的轉換

What is a Unix Timestamp 參考連結 直接進入程式碼的部分: object TimeUtil { @JvmStatic fun StampToDate(time: Long, locale: Locale): String { // 進來的time以秒為單位,Date輸入為毫秒為單位,要注意 val simpleDateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", locale) return simpleDateFormat.format(Date(time)) } @JvmStatic fun DateToStamp(date: String, locale: Locale): Long { val simpleDateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", locale) /// 輸出為毫秒為單位 return simpleDateFormat.parse(date).time } } 使用: println(TimeUtil.StampToDate(1560839160000, Locale.TAIWAN)) println(TimeUtil.DateToStamp("2019-06-18 14:26:00", Locale.TAIWAN)) 以台灣為例,GMT+8  Date 格式是 "yyyy-MM-dd HH:mm:ss" 假如 台灣 Date = "2020-10-21 18:00:00" 轉換成時間戳是  1603274400 同時間 在 GMT +0 時區的地方 Date =  "2020-10-21 10:00:00" 轉換成時間戳也是  1603274400