這篇就來用上次學到的Canvas,來做這個範例動畫。

需求很簡單,點下+按鈕會展開3個Icon讓使用者選擇。
我們先來分析一下怎麼做。
UI分為2個部分
事件:點下+按鈕時
事件:點下x按鈕時
這個範例,我們把他做成CustomView,讓使用這個CustomSelector的人可以自行決定要傳入多少dialog上的icon
完成後的使用方式:
activity_main.xml,加入CustomSelector
<evan.chen.tutorial.customselector.CustomSelector
    android:id="@+id/select_dialog"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerVertical="true" />
MainMactivity,使用setSelectIcon設定展開的圖示,使用IConSelectListener接收事件。
//放大icon array
val drawables = intArrayOf(R.mipmap.icon1, R.mipmap.icon2, R.mipmap.icon3)
selectDialog.setSelectIcon(drawables)
//事件
selectDialog.setListener(object : CustomSelector.IconSelectListener {
    //開啟Dialog
    override fun onOpen() {
        selectResult.text = ""
    }
    //被選取事件
    override fun onSelected(iconIndex: Int) {
        selectResult.text = "Select  icon: $iconIndex"
    }
    //點X事件。
    override fun onCancel() {
        selectResult.text = "Cancel"
    }
})
繪圖及設定Button點擊事件
private fun setting() {
    View.inflate(context, R.layout.custom_selector, this)
    //繪制+的按鈕
    drawButton()
    //繪制Dialog
    drawDialog()
    //控制是否顯示Dialog
    displayDialog(false)
    //點下Button的事件
    select_imageview.setOnClickListener {
        //旋轉+按鈕
        rotateSelectImageView()
        //顯示Dialog
        displayDialog(!isOpen)
        //Callback
        if (isOpen) {
            listener?.onCancel()
        } else {
            listener?.onOpen()
        }
        isOpen = !isOpen
    }
}
處理點下+按鈕的事件
1.+按鈕要變為x按鈕
要轉+變成x,只要將圖片旋轉-45度即可
private fun rotateSelectImageView() {
    //點選+後,旋轉變成x
    val fromDegree: Float
    val toDegree: Float
    if (isOpen) {
        //旋轉由-45度到0度。開啟狀態(x) -> 關閉狀態(+)
        fromDegree = -45.0f
        toDegree = 0.0f
    } else {
        //旋轉由0度到-45度。開啟狀態(x) -> 關閉狀態(+)
        fromDegree = 0.0f
        toDegree = -45.0f
    }
    val animRotate = RotateAnimation(fromDegree, toDegree,
            RotateAnimation.RELATIVE_TO_SELF, 0.5f,
            RotateAnimation.RELATIVE_TO_SELF, 0.5f)
    animRotate.duration = 300
    animRotate.fillAfter = true
    select_imageview.startAnimation(animRotate)
}
2.由小至大顯示Dialog
private fun displayDialog(display: Boolean) {
    //開啟、關閉Dialog
    var fromScale = 0.0f
    var toScale = 1.0f
    if (display) {
        //由小變大展開
        fromScale = 0.0f
        toScale = 1.0f
        this.dialog_select_linearlayout.visibility = View.VISIBLE
        this.dialog_select_linearlayout.bringToFront()
    } else {
        //由大變小縮起
        fromScale = 1.0f
        toScale = 0.0f
        this.dialog_select_linearlayout.visibility = View.GONE
    }
    //Scale動畫,顯示時由小放大,關閉時由大放小
    val anim = ScaleAnimation(
            fromScale, toScale,
            fromScale, toScale,
            Animation.RELATIVE_TO_SELF, 0.5f,
            Animation.RELATIVE_TO_SELF, 1f)
    anim.duration = 300
    this.dialog_select_linearlayout.startAnimation(anim)
}
還記得嗎?我們是CustomView,可以讓使用者決定放多少icon
fun setSelectIcon(drawables: IntArray) {
    this.drawables = drawables
    setting()
}
//開啟、選取、取消的Listener
interface IconSelectListener {
    fun onOpen()
    fun onSelected(iconIndex: Int)
    fun onCancel()
}
完整程式:
https://github.com/evanchen76/CustomSelector