|
@@ -1,38 +1,255 @@
|
|
package com.kdanmobile.reader.screen.view
|
|
package com.kdanmobile.reader.screen.view
|
|
|
|
|
|
|
|
+import android.animation.*
|
|
import android.content.Context
|
|
import android.content.Context
|
|
|
|
+import android.graphics.Color
|
|
import android.support.constraint.ConstraintLayout
|
|
import android.support.constraint.ConstraintLayout
|
|
|
|
+import android.support.v4.content.ContextCompat
|
|
import android.util.AttributeSet
|
|
import android.util.AttributeSet
|
|
import android.view.LayoutInflater
|
|
import android.view.LayoutInflater
|
|
import android.view.View
|
|
import android.view.View
|
|
|
|
+import android.view.View.OnClickListener
|
|
|
|
+import android.view.animation.AccelerateDecelerateInterpolator
|
|
|
|
+import android.widget.ImageButton
|
|
import com.kdanmobile.reader.R
|
|
import com.kdanmobile.reader.R
|
|
|
|
+import com.kdanmobile.reader.screen.view.edit.*
|
|
import kotlinx.android.synthetic.main.view_viewer_edit.view.*
|
|
import kotlinx.android.synthetic.main.view_viewer_edit.view.*
|
|
|
|
+import kotlinx.android.synthetic.main.view_viewer_edit_tab.view.*
|
|
|
|
|
|
-class ViewerEditView : ConstraintLayout {
|
|
|
|
|
|
+class ViewerEditView @JvmOverloads constructor(
|
|
|
|
+ context: Context,
|
|
|
|
+ attrs: AttributeSet? = null,
|
|
|
|
+ defStyleAttr: Int = 0
|
|
|
|
+): ConstraintLayout(context, attrs, defStyleAttr) {
|
|
|
|
|
|
- constructor(context: Context) : super(context) {
|
|
|
|
- initView()
|
|
|
|
|
|
+ private companion object {
|
|
|
|
+ const val COLOR_DISMISS = Color.TRANSPARENT
|
|
|
|
+ val COLOR_SHOW = Color.parseColor("#42000000")
|
|
|
|
+ const val DEFAULT_DURATION_ANIMATION = 300L
|
|
}
|
|
}
|
|
|
|
|
|
- constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
|
|
|
|
- initView()
|
|
|
|
|
|
+ private enum class ViewerEditTabType {
|
|
|
|
+ NONE, TEXT_BOX, SIGNATURE, STAMP, SHAPE, FORM
|
|
}
|
|
}
|
|
|
|
|
|
- constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) {
|
|
|
|
- initView()
|
|
|
|
- }
|
|
|
|
|
|
+ var onShowListener: Runnable? = null
|
|
|
|
+ var onDismissListener: Runnable? = null
|
|
|
|
+ var animationDuration = DEFAULT_DURATION_ANIMATION
|
|
|
|
|
|
- private fun initView() {
|
|
|
|
- LayoutInflater.from(context).inflate(R.layout.view_viewer_edit, this)
|
|
|
|
|
|
+ private var mediaBoxAnimator: ObjectAnimator? = null
|
|
|
|
+ private var maskAnimator: ValueAnimator? = null
|
|
|
|
+ private var tabType = ViewerEditTabType.NONE
|
|
|
|
+ private var selected: ImageButton? = null
|
|
|
|
+ var onViewerEditTabAddButtonClickListener: OnViewerEditTabAddButtonClickListener? = null
|
|
|
|
|
|
|
|
+ init {
|
|
|
|
+ LayoutInflater.from(context).inflate(R.layout.view_viewer_edit, this)
|
|
|
|
+ visibility = View.INVISIBLE
|
|
setupTabView()
|
|
setupTabView()
|
|
|
|
+
|
|
|
|
+ /** Set empty listener to prevent dismissing by clicking box **/
|
|
|
|
+ view_viewEdit_content.setOnClickListener {}
|
|
|
|
+
|
|
|
|
+ /** Move media box view to bottom of parent(hide it) **/
|
|
|
|
+ val size = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
|
|
|
|
+ val v = view_viewEdit_content
|
|
|
|
+ v.measure(size, size)
|
|
|
|
+ v.y = v.top + v.measuredHeight.toFloat()
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ fun show() {
|
|
|
|
+ visibility = View.VISIBLE
|
|
|
|
+ setOnClickListener { dismiss() }
|
|
|
|
+ post {
|
|
|
|
+ showMaskWithAnimation()
|
|
|
|
+ showMediaBoxWithAnimation()
|
|
|
|
+ }
|
|
|
|
+ onShowListener?.run()
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ fun dismiss() {
|
|
|
|
+ setOnClickListener(null)
|
|
|
|
+ hideMaskWithAnimation()
|
|
|
|
+ hideMediaBoxWithAnimation()
|
|
|
|
+ onDismissListener?.run()
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private fun showMaskWithAnimation() {
|
|
|
|
+ maskAnimator?.cancel()
|
|
|
|
+ val from = maskAnimator?.animatedValue ?: COLOR_DISMISS
|
|
|
|
+ val to = COLOR_SHOW
|
|
|
|
+ maskAnimator = ValueAnimator.ofObject(ArgbEvaluator(), from, to).apply {
|
|
|
|
+ duration = DEFAULT_DURATION_ANIMATION
|
|
|
|
+ interpolator = AccelerateDecelerateInterpolator()
|
|
|
|
+ addUpdateListener {
|
|
|
|
+ setBackgroundColor(it.animatedValue as Int)
|
|
|
|
+ }
|
|
|
|
+ start()
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private fun hideMaskWithAnimation() {
|
|
|
|
+ maskAnimator?.cancel()
|
|
|
|
+ val from = maskAnimator?.animatedValue ?: COLOR_SHOW
|
|
|
|
+ val to = COLOR_DISMISS
|
|
|
|
+ maskAnimator = ValueAnimator.ofObject(ArgbEvaluator(), from, to).apply {
|
|
|
|
+ duration = DEFAULT_DURATION_ANIMATION
|
|
|
|
+ interpolator = AccelerateDecelerateInterpolator()
|
|
|
|
+ addUpdateListener {
|
|
|
|
+ setBackgroundColor(it.animatedValue as Int)
|
|
|
|
+ }
|
|
|
|
+ start()
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private fun showMediaBoxWithAnimation() {
|
|
|
|
+ mediaBoxAnimator?.cancel()
|
|
|
|
+ val v = view_viewEdit_content
|
|
|
|
+ v.visibility = View.VISIBLE
|
|
|
|
+ val from = v.y
|
|
|
|
+ val to = v.top.toFloat()
|
|
|
|
+ val holder = PropertyValuesHolder.ofFloat("Y", from, to)
|
|
|
|
+ mediaBoxAnimator = ObjectAnimator.ofPropertyValuesHolder(v, holder).apply {
|
|
|
|
+ interpolator = AccelerateDecelerateInterpolator()
|
|
|
|
+ duration = animationDuration
|
|
|
|
+ addListener(object : AnimatorListenerAdapter() {
|
|
|
|
+ override fun onAnimationEnd(animation: Animator?) {
|
|
|
|
+ super.onAnimationEnd(animation)
|
|
|
|
+ removeListener(this)
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ start()
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private fun hideMediaBoxWithAnimation() {
|
|
|
|
+ mediaBoxAnimator?.cancel()
|
|
|
|
+ val v = view_viewEdit_content
|
|
|
|
+ val from = v.y
|
|
|
|
+ val to = v.top.toFloat() + v.height
|
|
|
|
+ val holder = PropertyValuesHolder.ofFloat("Y", from, to)
|
|
|
|
+ mediaBoxAnimator = ObjectAnimator.ofPropertyValuesHolder(v, holder).apply {
|
|
|
|
+ interpolator = AccelerateDecelerateInterpolator()
|
|
|
|
+ duration = animationDuration
|
|
|
|
+ addListener(object : AnimatorListenerAdapter() {
|
|
|
|
+ override fun onAnimationEnd(animation: Animator?) {
|
|
|
|
+ super.onAnimationEnd(animation)
|
|
|
|
+ removeListener(this)
|
|
|
|
+ v.visibility = View.INVISIBLE
|
|
|
|
+ this@ViewerEditView.visibility = View.GONE
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ start()
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
private fun setupTabView() {
|
|
private fun setupTabView() {
|
|
viewerEdit_tab.onClickListenerTabTextBox = OnClickListener(this::setupTextBoxView)
|
|
viewerEdit_tab.onClickListenerTabTextBox = OnClickListener(this::setupTextBoxView)
|
|
|
|
+ viewerEdit_tab.onClickListenerTabSignature = OnClickListener(this::setupSignatureView)
|
|
|
|
+ viewerEdit_tab.onClickListenerTabStamp = OnClickListener(this::setupStampView)
|
|
|
|
+ viewerEdit_tab.onClickListenerTabShape = OnClickListener(this::setupShapeView)
|
|
|
|
+ viewerEdit_tab.onClickListenerTabForm = OnClickListener(this::setupFormView)
|
|
|
|
+
|
|
|
|
+ setupTextBoxView(viewerEdit_tab_textBox)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private fun getButtonDrawable(tabType: ViewerEditTabType, isSelected: Boolean): Int {
|
|
|
|
+ return when (tabType) {
|
|
|
|
+ ViewerEditTabType.NONE, ViewerEditTabType.TEXT_BOX ->
|
|
|
|
+ if (isSelected) R.drawable.ic_textbox_selected else R.drawable.ic_textbox
|
|
|
|
+ ViewerEditTabType.SIGNATURE ->
|
|
|
|
+ if (isSelected) R.drawable.ic_signature_selected else R.drawable.ic_signature
|
|
|
|
+ ViewerEditTabType.STAMP ->
|
|
|
|
+ if (isSelected) R.drawable.ic_stamp_selected else R.drawable.ic_stamp
|
|
|
|
+ ViewerEditTabType.SHAPE ->
|
|
|
|
+ if (isSelected) R.drawable.ic_shape_selected else R.drawable.ic_shape
|
|
|
|
+ ViewerEditTabType.FORM ->
|
|
|
|
+ if (isSelected) R.drawable.ic_form_selected else R.drawable.ic_form
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private fun setupContent(button: ImageButton, tabType: ViewerEditTabType): Boolean {
|
|
|
|
+ var changed = false
|
|
|
|
+ if (this.tabType != tabType) {
|
|
|
|
+ selected?.setImageDrawable(ContextCompat.getDrawable(context, getButtonDrawable(this.tabType, false)))
|
|
|
|
+ this.tabType = tabType
|
|
|
|
+ selected = button
|
|
|
|
+ button.setImageDrawable(ContextCompat.getDrawable(context, getButtonDrawable(this.tabType, true)))
|
|
|
|
+
|
|
|
|
+ viewEdit_layout_tab_content.removeAllViews()
|
|
|
|
+ changed = true
|
|
|
|
+ }
|
|
|
|
+ return changed
|
|
}
|
|
}
|
|
|
|
|
|
private fun setupTextBoxView(view: View) {
|
|
private fun setupTextBoxView(view: View) {
|
|
|
|
+ val changed = setupContent(view as ImageButton, ViewerEditTabType.TEXT_BOX)
|
|
|
|
+ if (changed) {
|
|
|
|
+ val textBoxTabView = TextBoxTabView(context)
|
|
|
|
+ val params = ConstraintLayout.LayoutParams(ConstraintLayout.LayoutParams.MATCH_PARENT, ConstraintLayout.LayoutParams.MATCH_PARENT)
|
|
|
|
+ viewEdit_layout_tab_content.addView(textBoxTabView, params)
|
|
|
|
+ textBoxTabView.onTitleButtonClickListener = object: TitleButton.OnTitleButtonClickListener {
|
|
|
|
+ override fun onTitleButtonClick() {
|
|
|
|
+ onViewerEditTabAddButtonClickListener?.onTabTextBoxAddButtonClick(textBoxTabView)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private fun setupSignatureView(view: View) {
|
|
|
|
+ val changed = setupContent(view as ImageButton, ViewerEditTabType.SIGNATURE)
|
|
|
|
+ if (changed) {
|
|
|
|
+ val signatureTabView = SignatureTabView(context)
|
|
|
|
+ val params = ConstraintLayout.LayoutParams(ConstraintLayout.LayoutParams.MATCH_PARENT, ConstraintLayout.LayoutParams.MATCH_PARENT)
|
|
|
|
+ viewEdit_layout_tab_content.addView(signatureTabView, params)
|
|
|
|
+ signatureTabView.onTitleButtonClickListener = object: TitleButton.OnTitleButtonClickListener {
|
|
|
|
+ override fun onTitleButtonClick() {
|
|
|
|
+ onViewerEditTabAddButtonClickListener?.onTabSignatureAddButtonClick(signatureTabView)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private fun setupStampView(view: View) {
|
|
|
|
+ val changed = setupContent(view as ImageButton, ViewerEditTabType.STAMP)
|
|
|
|
+ if (changed) {
|
|
|
|
+ val stampTabView = StampTabView(context)
|
|
|
|
+ val params = ConstraintLayout.LayoutParams(ConstraintLayout.LayoutParams.MATCH_PARENT, ConstraintLayout.LayoutParams.MATCH_PARENT)
|
|
|
|
+ viewEdit_layout_tab_content.addView(stampTabView, params)
|
|
|
|
+ stampTabView.onTitleButtonClickListener = object: TitleButton.OnTitleButtonClickListener {
|
|
|
|
+ override fun onTitleButtonClick() {
|
|
|
|
+ onViewerEditTabAddButtonClickListener?.onTabStampAddButtonClick(stampTabView)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private fun setupShapeView(view: View) {
|
|
|
|
+ val changed = setupContent(view as ImageButton, ViewerEditTabType.SHAPE)
|
|
|
|
+ if (changed) {
|
|
|
|
+ val shapeTabView = ShapeTabView(context)
|
|
|
|
+ val params = ConstraintLayout.LayoutParams(ConstraintLayout.LayoutParams.MATCH_PARENT, ConstraintLayout.LayoutParams.MATCH_PARENT)
|
|
|
|
+ viewEdit_layout_tab_content.addView(shapeTabView, params)
|
|
|
|
+ shapeTabView.onTitleButtonClickListener = object: TitleButton.OnTitleButtonClickListener {
|
|
|
|
+ override fun onTitleButtonClick() {
|
|
|
|
+ onViewerEditTabAddButtonClickListener?.onTabShapeAddButtonClick(shapeTabView)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private fun setupFormView(view: View) {
|
|
//TODO implements tab view and add to viewEdit_layout_tab_content
|
|
//TODO implements tab view and add to viewEdit_layout_tab_content
|
|
|
|
+ val changed = setupContent(view as ImageButton, ViewerEditTabType.FORM)
|
|
|
|
+ if (changed) {
|
|
|
|
+ LayoutInflater.from(context).inflate(R.layout.view_viewer_edit_tab, viewEdit_layout_tab_content)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ interface OnViewerEditTabAddButtonClickListener {
|
|
|
|
+ fun onTabTextBoxAddButtonClick(textBoxTabView: TextBoxTabView)
|
|
|
|
+ fun onTabSignatureAddButtonClick(signatureTabView: SignatureTabView)
|
|
|
|
+ fun onTabStampAddButtonClick(stampTabView: StampTabView)
|
|
|
|
+ fun onTabShapeAddButtonClick(shapeTabView: ShapeTabView)
|
|
}
|
|
}
|
|
}
|
|
}
|