Skip to content

view model

hotsummmer edited this page Jul 29, 2019 · 10 revisions

ChViewModel[목차]

ChStyleModel[목차]

ChViewModel(abstract class)

  • ChViewModel를 상속해서 VM클래스를 만든다.
  • style이 아닌 데이터를 바꾸는 것이 기본
  • style인 속성의 경우 @PROP var alpha = 1.0 이렇게 앞에 @PROP를 붙인다.
  • ChStyleModel은 반대로 기본이 style속성이며 object앞에 @STYLE이라는 에노테이션을 붙이고 style속성이 아닌 속성에 @EX val time0 = 700 이렇게 앞에 @EX를 붙인다.
//SigninVM
@VM
@SuppressLint("StaticFieldLeak")
object SigninVM:ChViewModel(){
    override fun start(){
        holder.start()
        mx.forEachIndexed { i, _ -> mx[i] = 100.0 }
        ma.forEachIndexed { i, _ -> mx[i] = 0.0 }
    }
    override fun end(){
        holder.end()
        mx.forEachIndexed { i, _ -> mx[i] = 0.0 }
        ma.forEachIndexed { i, _ -> mx[i] = 0.0 }
    }
    override fun paused(){
        holder.paused()
    }
    val mx = mutableListOf(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
}
//SplashVM
@VM
object SplashVM:ChViewModel(){
    override fun start() {
        holder.start()
        title.start()
        alpha = 0.0
    }
    override fun end() {
        holder.end()
        title.end()
        alpha = 1.0
    }
    override fun resumeAnimation(it:ChItem){
        alpha = it.circleOut(0.0, 1.0)
    }
    val time = 500
    @PROP var alpha = 1.0

    val holder = Holder(0.0, 0.0, 1.0, 1.0)
    val title = Title
}

start() : ChViewModel

start()
  • View가 start될 때 데이터를 변경시키는 데 사용
override fun start() {
    holder.start()
    title.start()
    alpha = 0.0
}

end() : ChViewModel

end()
  • View가 end될 때 데이터를 변경시키는 데 사용
override fun end() {
    holder.end()
    title.end()
    alpha = 1.0
}

paused() : ChViewModel

paused()
  • View가 paused될 때 데이터를 변경시키는 데 사용
override fun paused(){
    holder.paused()
}

resumeAnimation() : ChViewModel

resumeAnimation(it: ChItem)
  • View가 resumeAnimation될 때 데이터를 변경시키는 데 사용
  • 매개변수가 ChItem으로 오기 때문에 easing처리를 할 수 있다.
  • 참고문서 - ChItem
override fun resumeAnimation(it: ChItem) {
    x = it.circleOut(Ch.window.width.toDouble(), 0.0)
    alpha = it.circleOut(0.5, 1.0)
}
override fun resumeAnimation(it:ChItem){
    alpha = it.circleOut(0.0, 1.0)
}

pauseAnimation() : ChViewModel

pauseAnimation(it: ChItem)
  • View가 pauseAnimation될 때 데이터를 변경시키는 데 사용
  • 매개변수가 ChItem으로 오기 때문에 easing처리를 할 수 있다.
  • 참고문서 - ChItem
override fun pauseAnimation(it: ChItem) {
    x = it.circleOut(0.0, -Ch.window.width.toDouble())
    alpha = it.circleOut(1.0, 0.5)
}

ChStyleModel(abstract class)

  • ChStyleModel를 상속해서 VM클래스를 만들어 뷰에 적용하면, 랜더링시 Ch.view.property에 등록된 속성들이 뷰에 반영이 된다.
@STYLE
class TagTitle(var text:String = ""):ChStyleModel(){
    var style = "font_black"
    var textAlignment = "center"
    var marginStart = "16dp"
    var marginEnd = "16dp"
    val visibility:Boolean get() = text.isNotEmpty()
}
  • ChStyleModel 객체에 @STYLE 에노테이션을 붙이면 컴파일 시 속성에 대한 밸리데이션을 진행한다. 밸리데이션의 기준은 Chela Annotation에 ChProcessor에 등록된 것인지 아닌지 여부인데, 여기에 등록해두지 않은 이름을 속성으로 지정하면 컴파일시 에러가 나게 된다.
@STYLE
object ProductTotal: ChStyleModel(){
   var cnt= 0    //컴파일 에러 "e: error: cnt in ProductTotal of xxxxx- invalid field"
   val text:String get() = "Product total : $cnt"
}
  • ChProcessor에 등록되지 않은 속성을 뷰에 적용하고 싶으면 다음 절차에 따라 커스텀 스타일 속성을 만들어 적용할 수 있다.
    1. Ch.prop.add으로 속성을 등록한다.
    2. @STYLE 에노테이션에 만든 속성 명을 인자로 기술해준다.
Ch.prop.add("scrolltotop"){view, v->
    view.scrollTo(0, 0)
}
@STYLE("scrolltotop")
open class WrapStyle: ChStyleModel(){
    open val background = "#ffffff"
    val style = "wrapper"
    var scrolltotop = true    //scrolltotop 속성이 바뀌면 render시 스크롤이 위로 움직인다.
    fun scrollToTop() = scrolltotop != scrolltotop
}
  3. 커스텀 속성을 상속하는 클래스를 만들면, 자식 객체에도 @STYLE 어노테이션 안에 커스텀 속성 이름을 인자로 넘겨줘야 한다.
@STYLE
object ProductContainer: WrapStyle(){
    override val background = "#ff0000" //e: error: scrolltotop in ProductContainer of xxxxxx - invalid field
                                        //scrolltotop을 오버라이드 하지 않아도 STYLE 어노테이션으로 속성을 기술해줘야 함
}
  • 뷰에 적용할 스타일 속성이 아닌 것은 @EX 어노테이션을 붙여 컴파일 에러를 피할 수 있다.
//SplashVM
@STYLE object Title:ChStyleModel(){
    @EX val time0 = 700
    @EX val time1 = 300
    var alpha = 0.0
    var marginTop = 50.0.DptoPx
    var scaleX = 0.8
    var scaleY = 0.8
    override fun start(){
        alpha = 0.0
        marginTop = 50.0.DptoPx
        scaleX = 0.8
        scaleY = 0.8
    }
    override fun end(){
        alpha = 1.0
        marginTop = 0.0
        scaleX = 1.0
        scaleY = 1.0
    }
    override fun resumeAnimation(it:ChItem){
        alpha = it.circleOut(0.0, 1.0)
        marginTop = it.circleOut(50.0.DptoPx, 0.0)
        scaleX = it.circleOut(0.8, 1.0)
        scaleY = it.circleOut(0.8, 1.0)
    }
}
  • 복잡한 ChStyleModel 객체의 예시
//SigninVM
@STYLE object InputId:ChStyleModel(){
    @EX var userid = ""
    val style = "input"
    val marginStart:Double get() = SigninVM.mx[1]
    val alpha:Double get() = SigninVM.ma[1]
    val inputType = Ch.prop.text.type.text

    val maxLength = 30
    val focusChange = AppVM.inputFocus
    @SuppressLint("StaticFieldLeak")
    val textChanged = object: Ch.OnTextChanged(){
        override fun onChanged(view: EditText, s:CharSequence, start:Int, before:Int, count:Int){
            val v = "$s"
            if(v.isEmpty()) userid = ""
            else if(!Ch.ruleset.isOk("se.useridInput" to v)){
                if(Vali0.text == ""){
                    Vali0.text = Ch.i18n["signin.valiId"]
                    Signin.renderSync()
                }
                view.setText(userid)
                view.setSelection(userid.length)
                SigninVM.inputEffect(pos(), view, R.drawable.crop_fa635c)
            }else{
                userid = v
                if(before < count) {
                    if (Vali0.text != "") {
                        Vali0.text = ""
                        Signin.renderSync()
                    }
                    SigninVM.inputEffect(pos(), view, R.drawable.crop)
                }
            }
            SigninVM.isValid()
        }
    }
}
@STYLE class ModalHolder:ChStyleModel(){
    companion object {
        val popTime = Ch.time(320)
        val pushTime = Ch.time(350)
    }
    var visibility = View.VISIBLE
    var y = 0.0
    var alpha = 1.0
    override fun start(){
        y = Ch.window.height.toDouble()
        alpha = 0.0
        visibility = View.VISIBLE
    }
    override fun end(){
        y = 0.0
        alpha = 1.0
    }
    override fun paused(){
        start()
        visibility = View.GONE
    }
    override fun resumeAnimation(it: ChItem) {
        y = it.sineOut(Ch.window.height.toDouble(), 0.0)
        alpha = it.sineOut(0.0, 1.0)
    }
    override fun pauseAnimation(it: ChItem) {
        y = it.sineIn(0.0, Ch.window.height.toDouble())
        alpha = it.sineIn(1.0, 0.0)
    }
}

start() : ChStyleModel

start()
  • View가 start될 때 데이터를 변경시키는 데 사용
  • ChViewModel의 start 메서드와 동일함
override fun start(){
    alpha = 0.0
    marginTop = 50.0.DptoPx
    scaleX = 0.8
    scaleY = 0.8
}

end() : ChStyleModel

end()
  • View가 end될 때 데이터를 변경시키는 데 사용
  • ChViewModel의 end메서드와 동일함
override fun end(){
    alpha = 1.0
    marginTop = 0.0
    scaleX = 1.0
    scaleY = 1.0
}

paused() : ChStyleModel

paused()
  • View가 paused될 때 데이터를 변경시키는 데 사용
  • ChViewModel의 paused메서드와 동일함
override fun paused(){
    start()
    visibility = View.GONE
}

resumeAnimation() : ChStyleModel

resumeAnimation(it: ChItem)
  • View가 resumeAnimation될 때 데이터를 변경시키는 데 사용
  • 매개변수가 ChItem으로 오기 때문에 easing처리를 할 수 있다.
  • 참고문서 - ChItem
override fun resumeAnimation(it: ChItem) {
    y = it.sineOut(Ch.window.height.toDouble(), 0.0)
    alpha = it.sineOut(0.0, 1.0)
}

pauseAnimation() : ChStyleModel

pauseAnimation(it: ChItem)
  • View가 pauseAnimation될 때 데이터를 변경시키는 데 사용
  • 매개변수가 ChItem으로 오기 때문에 easing처리를 할 수 있다.
  • 참고문서 - ChItem
override fun pauseAnimation(it: ChItem) {
    y = it.sineIn(0.0, Ch.window.height.toDouble())
    alpha = it.sineIn(1.0, 0.0)
}