Coverage Summary for Class: ViewIds (kr.open.library.simple_ui.xml.extensions.view)

Class Class, % Method, % Branch, % Line, % Instruction, %
ViewIds 100% (1/1) 100% (3/3) 100% (3/3) 100% (9/9)


 package kr.open.library.simple_ui.xml.extensions.view
 
 import android.os.SystemClock
 import android.view.View
 import android.view.ViewGroup
 import androidx.annotation.MainThread
 import kr.open.library.simple_ui.core.logcat.Logx
 import kr.open.library.simple_ui.core.thread.assertMainThreadDebug
 import kr.open.library.simple_ui.xml.R
 
 /**
  * View extension functions for visibility, sizing, margins, padding, and click handling.<br>
  * Provides convenient methods to manipulate View properties and behavior.<br><br>
  * 가시성, 크기, 여백, 패딩 및 클릭 처리를 위한 View 확장 함수입니다.<br>
  * View 속성과 동작을 조작하는 편리한 메서드를 제공합니다.<br>
  *
  * Example usage:<br>
  * ```kotlin
  * // Visibility control
  * view.setVisible()
  * view.setGone()
  * view.setInvisible()
  *
  * // Debounced click listener
  * button.setOnDebouncedClickListener(1000L) {
  *     navigateToNextScreen()
  * }
  *
  * // Size and layout
  * view.setSize(200, 100)
  * view.setMargin(16)
  * view.setPadding(12)
  * view.setWidthMatchParent()
  * view.setHeightWrapContent()
  *
  * // ViewGroup iteration
  * viewGroup.forEachChild { child ->
  *     child.setVisible()
  * }
  * ```
  */
 
 internal object ViewIds {
     val LAST_CLICK_TIME = R.id.tag_last_click_time
     val PULSE_ANIMATOR = R.id.tag_pulse_animator
 
     /***************************
      * usefor LifeCycle*Layout
      ***************************/
     val TAG_OBSERVED_OWNER = R.id.tag_lifecycle_observer
 }
 
 /**
  * Sets the view's visibility to VISIBLE.<br><br>
  * View의 가시성을 VISIBLE로 설정합니다.<br>
  */
 @MainThread
 public fun View.setVisible() {
     assertMainThreadDebug("View.setVisible")
     if (this.visibility != View.VISIBLE) this.visibility = View.VISIBLE
 }
 
 /**
  * Sets the view's visibility to GONE.<br><br>
  * View의 가시성을 GONE으로 설정합니다.<br>
  */
 @MainThread
 public fun View.setGone() {
     assertMainThreadDebug("View.setGone")
     if (this.visibility != View.GONE) this.visibility = View.GONE
 }
 
 /**
  * Sets the view's visibility to INVISIBLE.<br><br>
  * View의 가시성을 INVISIBLE로 설정합니다.<br>
  */
 @MainThread
 public fun View.setInvisible() {
     assertMainThreadDebug("View.setInvisible")
     if (this.visibility != View.INVISIBLE) this.visibility = View.INVISIBLE
 }
 
 /**
  * Sets a debounced click listener on this view to prevent rapid consecutive clicks.<br>
  * Uses View's tag system to store timing information, preventing memory leaks.<br><br>
  * 연속적인 빠른 클릭을 방지하기 위해 디바운스된 클릭 리스너를 설정합니다.<br>
  * View의 tag 시스템을 사용하여 타이밍 정보를 저장하여 메모리 누수를 방지합니다.<br>
  *
  * @param debounceTime The minimum time interval between clicks in milliseconds (default: 600ms).<br><br>
  *                     클릭 간 최소 시간 간격(밀리초) (기본값: 600ms).<br>
  *
  * @param action The action to execute when a valid click occurs.<br><br>
  *               유효한 클릭이 발생했을 때 실행할 작업.<br>
  */
 @MainThread
 public fun View.setOnDebouncedClickListener(
     debounceTime: Long = 600L,
     action: (View) -> Unit,
 ) {
     assertMainThreadDebug("View.setOnDebouncedClickListener")
     setOnClickListener { view ->
         val currentTime = SystemClock.elapsedRealtime()
         val lastClickTime = (view.getTag(ViewIds.LAST_CLICK_TIME) as? Long) ?: 0L
 
         if (currentTime - lastClickTime >= debounceTime) {
             view.setTag(ViewIds.LAST_CLICK_TIME, currentTime)
             action(view)
         }
     }
 }
 
 /**
  * Iterates over all child views of this ViewGroup.<br><br>
  * 이 ViewGroup의 모든 자식 View를 반복합니다.<br>
  *
  * @param action The action to execute for each child view.<br><br>
  *               각 자식 View에 대해 실행할 작업.<br>
  */
 @MainThread
 public fun ViewGroup.forEachChild(action: (View) -> Unit) {
     assertMainThreadDebug("ViewGroup.forEachChild")
     for (i in 0 until childCount) {
         action(getChildAt(i))
     }
 }
 
 /**
  * Sets all margin values at once.<br><br>
  * 모든 여백 값을 한 번에 설정합니다.<br>
  *
  * @param left Left margin in pixels.<br><br>
  *             왼쪽 여백(픽셀 단위).<br>
  *
  * @param top Top margin in pixels.<br><br>
  *            상단 여백(픽셀 단위).<br>
  *
  * @param right Right margin in pixels.<br><br>
  *              오른쪽 여백(픽셀 단위).<br>
  *
  * @param bottom Bottom margin in pixels.<br><br>
  *               하단 여백(픽셀 단위).<br>
  */
 @MainThread
 public fun View.setMargins(
     left: Int,
     top: Int,
     right: Int,
     bottom: Int,
 ) {
     assertMainThreadDebug("View.setMargins")
     if (layoutParams is ViewGroup.MarginLayoutParams) {
         val params = layoutParams as ViewGroup.MarginLayoutParams
         params.setMargins(left, top, right, bottom)
         layoutParams = params
     } else {
         Logx.w("View.setMargins", "layoutParams is not MarginLayoutParams: ${layoutParams?.javaClass?.simpleName}")
     }
 }
 
 /**
  * Sets uniform margin for all sides.<br><br>
  * 모든 면에 대해 동일한 여백을 설정합니다.<br>
  *
  * @param margin Margin value in pixels for all sides.<br><br>
  *               모든 면의 여백 값(픽셀 단위).<br>
  */
 @MainThread
 public fun View.setMargin(margin: Int) {
     assertMainThreadDebug("View.setMargin")
     setMargins(margin, margin, margin, margin)
 }
 
 /**
  * Sets uniform padding for all sides.<br><br>
  * 모든 면에 대해 동일한 패딩을 설정합니다.<br>
  *
  * @param padding Padding value in pixels for all sides.<br><br>
  *                모든 면의 패딩 값(픽셀 단위).<br>
  */
 @MainThread
 public fun View.setPadding(padding: Int) {
     assertMainThreadDebug("View.setPadding")
     setPadding(padding, padding, padding, padding)
 }
 
 /**
  * Sets the width of the view.<br><br>
  * View의 너비를 설정합니다.<br>
  *
  * @param width Width in pixels.<br><br>
  *              너비(픽셀 단위).<br>
  */
 @MainThread
 public fun View.setWidth(width: Int) {
     assertMainThreadDebug("View.setWidth")
     layoutParams?.let { params ->
         params.width = width
         layoutParams = params
     }
 }
 
 /**
  * Sets the height of the view.<br><br>
  * View의 높이를 설정합니다.<br>
  *
  * @param height Height in pixels.<br><br>
  *               높이(픽셀 단위).<br>
  */
 @MainThread
 public fun View.setHeight(height: Int) {
     assertMainThreadDebug("View.setHeight")
     layoutParams?.let { params ->
         params.height = height
         layoutParams = params
     }
 }
 
 /**
  * Sets both width and height of the view.<br><br>
  * View의 너비와 높이를 모두 설정합니다.<br>
  *
  * @param width Width in pixels.<br><br>
  *              너비(픽셀 단위).<br>
  *
  * @param height Height in pixels.<br><br>
  *               높이(픽셀 단위).<br>
  */
 @MainThread
 public fun View.setSize(
     width: Int,
     height: Int,
 ) {
     assertMainThreadDebug("View.setSize")
     layoutParams?.let { params ->
         params.width = width
         params.height = height
         layoutParams = params
     }
 }
 
 /**
  * Sets the view width to match parent.<br><br>
  * View의 너비를 부모에 맞춥니다.<br>
  */
 @MainThread
 public fun View.setWidthMatchParent() {
     assertMainThreadDebug("View.setWidthMatchParent")
     setWidth(ViewGroup.LayoutParams.MATCH_PARENT)
 }
 
 /**
  * Sets the view height to match parent.<br><br>
  * View의 높이를 부모에 맞춥니다.<br>
  */
 @MainThread
 public fun View.setHeightMatchParent() {
     assertMainThreadDebug("View.setHeightMatchParent")
     setHeight(ViewGroup.LayoutParams.MATCH_PARENT)
 }
 
 /**
  * Sets the view width to wrap content.<br><br>
  * View의 너비를 내용에 맞춥니다.<br>
  */
 @MainThread
 public fun View.setWidthWrapContent() {
     assertMainThreadDebug("View.setWidthWrapContent")
     setWidth(ViewGroup.LayoutParams.WRAP_CONTENT)
 }
 
 /**
  * Sets the view height to wrap content.<br><br>
  * View의 높이를 내용에 맞춥니다.<br>
  */
 @MainThread
 public fun View.setHeightWrapContent() {
     assertMainThreadDebug("View.setHeightWrapContent")
     setHeight(ViewGroup.LayoutParams.WRAP_CONTENT)
 }