Skip to content

Commit

Permalink
[feat] #1 core-ui extension
Browse files Browse the repository at this point in the history
  • Loading branch information
Sangwook123 committed Apr 10, 2024
1 parent c776650 commit d90a82b
Show file tree
Hide file tree
Showing 11 changed files with 300 additions and 0 deletions.
26 changes: 26 additions & 0 deletions core/ui/src/main/java/org/sopt/ui/base/BindingActivity.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package org.sopt.ui.base

import android.os.Bundle
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.viewbinding.ViewBinding
import org.sopt.ui.context.hideKeyboard

abstract class BindingActivity<T : ViewBinding>(
private val inflater: (LayoutInflater) -> T,
) : AppCompatActivity() {
protected lateinit var binding: T

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = inflater(layoutInflater)
setContentView(binding.root)
}

override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
hideKeyboard(currentFocus ?: View(this))
return super.dispatchTouchEvent(ev)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package org.sopt.ui.base

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import androidx.viewbinding.ViewBinding
import com.google.android.material.bottomsheet.BottomSheetDialogFragment

abstract class BindingBottomSheetDialogFragment<T : ViewBinding>(
private val inflater: (LayoutInflater) -> T,
) : BottomSheetDialogFragment() {
private var _binding: T? = null
protected val binding get() = requireNotNull(_binding) { { "binding object is not initialized" } }

override fun onStart() {
super.onStart()
dialog?.window?.apply {
setLayout(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT,
)
}
}

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?,
): View {
_binding = inflater(layoutInflater)
return binding.root
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
}

override fun onDestroyView() {
_binding = null
super.onDestroyView()
}
}
44 changes: 44 additions & 0 deletions core/ui/src/main/java/org/sopt/ui/base/BindingDialogFragment.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package org.sopt.ui.base

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import androidx.fragment.app.DialogFragment
import androidx.viewbinding.ViewBinding

abstract class BindingDialogFragment<T : ViewBinding>(
private val inflater: (LayoutInflater) -> T,
) : DialogFragment() {
private var _binding: T? = null
protected val binding get() = requireNotNull(_binding) { { "binding object is not initialized" } }

override fun onStart() {
super.onStart()
dialog?.window?.apply {
setLayout(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
)
}
}

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?,
): View {
_binding = inflater(layoutInflater)
return binding.root
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
}

override fun onDestroyView() {
_binding = null
super.onDestroyView()
}
}
33 changes: 33 additions & 0 deletions core/ui/src/main/java/org/sopt/ui/base/BindingFragment.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package org.sopt.ui.base

import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.viewbinding.ViewBinding

abstract class BindingFragment<T : ViewBinding>(
private val inflater: (LayoutInflater) -> T,
) : Fragment() {
private var _binding: T? = null
protected val binding
get() = requireNotNull(_binding) {
Log.d("error", "$_binding")
}

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?,
): View? {
_binding = inflater(layoutInflater)
return binding.root
}

override fun onDestroyView() {
_binding = null
super.onDestroyView()
}
}
52 changes: 52 additions & 0 deletions core/ui/src/main/java/org/sopt/ui/context/ContextExt.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package org.sopt.ui.context

import android.app.Activity
import android.content.Context
import android.content.res.Resources
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.view.View
import android.view.WindowManager
import android.view.inputmethod.InputMethodManager
import android.widget.Toast
import androidx.annotation.ColorRes
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import androidx.core.content.ContextCompat
import androidx.fragment.app.DialogFragment
import com.google.android.material.snackbar.Snackbar

fun Context.toast(message: String) {
Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
}

fun Context.longToast(message: String) {
Toast.makeText(this, message, Toast.LENGTH_LONG).show()
}

fun Context.snackBar(anchorView: View, message: () -> String) {
Snackbar.make(anchorView, message(), Snackbar.LENGTH_SHORT).show()
}

fun Context.stringOf(@StringRes resId: Int) = getString(resId)

fun Context.colorOf(@ColorRes resId: Int) = ContextCompat.getColor(this, resId)

fun Context.drawableOf(@DrawableRes resId: Int) = ContextCompat.getDrawable(this, resId)

fun Context.hideKeyboard(view: View) {
val inputMethodManager = getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
inputMethodManager.hideSoftInputFromWindow(view.windowToken, 0)
}

fun Context.dialogFragmentResize(dialogFragment: DialogFragment, horizontalMargin: Float) {
val dpToPixel = Resources.getSystem().displayMetrics.density
val dialogHorizontalMarginInPixels =
(dpToPixel * horizontalMargin + 0.5f).toInt() // 반올림 처리
val deviceWidth = Resources.getSystem().displayMetrics.widthPixels
dialogFragment.dialog?.window?.setLayout(
deviceWidth - 2 * dialogHorizontalMarginInPixels,
WindowManager.LayoutParams.WRAP_CONTENT,
)
dialogFragment.dialog?.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
}
8 changes: 8 additions & 0 deletions core/ui/src/main/java/org/sopt/ui/context/ResourceProvider.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.sopt.ui.context

import androidx.annotation.StringRes


interface ResourceProvider {
fun getString(@StringRes id: Int): String
}
12 changes: 12 additions & 0 deletions core/ui/src/main/java/org/sopt/ui/context/ResourceProviderImpl.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.sopt.ui.context

import android.content.Context
import androidx.annotation.StringRes
import dagger.hilt.android.qualifiers.ApplicationContext
import javax.inject.Inject

class ResourceProviderImpl @Inject constructor(
@ApplicationContext private val context: Context
) : ResourceProvider {
override fun getString(@StringRes id: Int) = context.stringOf(id)
}
17 changes: 17 additions & 0 deletions core/ui/src/main/java/org/sopt/ui/di/ResourceProviderModule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.sopt.ui.di

import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import org.sopt.ui.context.ResourceProvider
import org.sopt.ui.context.ResourceProviderImpl
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
abstract class ResourceProviderModule {
@Binds
@Singleton
abstract fun bindsResourceProvider(resourceProvider: ResourceProviderImpl): ResourceProvider
}
36 changes: 36 additions & 0 deletions core/ui/src/main/java/org/sopt/ui/fragment/FragmentExt.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package org.sopt.ui.fragment

import android.view.View
import android.widget.Toast
import androidx.annotation.ColorRes
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import com.google.android.material.snackbar.Snackbar

fun Fragment.toast(message: String) {
Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show()
}

fun Fragment.longToast(message: String) {
Toast.makeText(requireContext(), message, Toast.LENGTH_LONG).show()
}

fun Fragment.snackBar(anchorView: View, message: () -> String) {
Snackbar.make(anchorView, message(), Snackbar.LENGTH_SHORT).show()
}

fun Fragment.stringOf(@StringRes resId: Int) = getString(resId)

fun Fragment.colorOf(@ColorRes resId: Int) = ContextCompat.getColor(requireContext(), resId)

fun Fragment.drawableOf(@DrawableRes resId: Int) =
ContextCompat.getDrawable(requireContext(), resId)

val Fragment.viewLifeCycle
get() = viewLifecycleOwner.lifecycle

val Fragment.viewLifeCycleScope
get() = viewLifecycleOwner.lifecycleScope
10 changes: 10 additions & 0 deletions core/ui/src/main/java/org/sopt/ui/intent/IntentExt.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.sopt.ui.intent

import android.content.Intent
import android.os.Build
import android.os.Parcelable

fun <T : Parcelable> Intent.getParcelable(key: String, c: Class<T>): T? = when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU -> getParcelableExtra(key, c)
else -> getParcelableExtra(key) as? T
}
18 changes: 18 additions & 0 deletions core/ui/src/main/java/org/sopt/ui/view/ItemDiffCallback.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.sopt.ui.view

import androidx.recyclerview.widget.DiffUtil

class ItemDiffCallback<T : Any>(
val onItemsTheSame: (T, T) -> Boolean,
val onContentsTheSame: (T, T) -> Boolean,
) : DiffUtil.ItemCallback<T>() {
override fun areItemsTheSame(
oldItem: T,
newItem: T,
): Boolean = onItemsTheSame(oldItem, newItem)

override fun areContentsTheSame(
oldItem: T,
newItem: T,
): Boolean = onContentsTheSame(oldItem, newItem)
}

0 comments on commit d90a82b

Please sign in to comment.