-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[AN-UI] 상성 페이지 UI 구현 #8
Changes from all commits
53418f4
86d136f
691f23e
e6c4655
4f2db34
680895b
a450f04
70c3ed1
5fd0bac
080725e
50692ed
938d138
8c5726b
82adeb1
e8da64d
ce8dd47
a196140
b912518
3dfea73
f1aaca3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package poke.rogue.helper.data.model | ||
|
||
enum class MatchedResult { | ||
NORMAL, | ||
STRONG, | ||
WEAK, | ||
INEFFECTIVE, | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package poke.rogue.helper.data.model | ||
|
||
data class TypeInfo( | ||
val id: Int, | ||
val name: String, | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package poke.rogue.helper.local.dao | ||
|
||
import poke.rogue.helper.data.model.TypeInfo | ||
|
||
object TypeDao { | ||
val allTypes = | ||
listOf( | ||
TypeInfo(0, "노말"), | ||
TypeInfo(1, "불꽃"), | ||
TypeInfo(2, "물"), | ||
TypeInfo(3, "전기"), | ||
TypeInfo(4, "풀"), | ||
TypeInfo(5, "얼음"), | ||
TypeInfo(6, "격투"), | ||
TypeInfo(7, "독"), | ||
TypeInfo(8, "땅"), | ||
TypeInfo(9, "비행"), | ||
TypeInfo(10, "에스퍼"), | ||
TypeInfo(11, "벌레"), | ||
TypeInfo(12, "바위"), | ||
TypeInfo(13, "고스트"), | ||
TypeInfo(14, "드래곤"), | ||
TypeInfo(15, "악"), | ||
TypeInfo(16, "강철"), | ||
TypeInfo(17, "페어리"), | ||
) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,19 @@ | ||
package poke.rogue.helper.presentation.home | ||
|
||
import android.content.Intent | ||
import android.os.Bundle | ||
import poke.rogue.helper.R | ||
import poke.rogue.helper.databinding.ActivityHomeBinding | ||
import poke.rogue.helper.presentation.base.BindingActivity | ||
import poke.rogue.helper.presentation.type.TypeActivity | ||
|
||
class HomeActivity : BindingActivity<ActivityHomeBinding>(R.layout.activity_home) { | ||
override fun onCreate(savedInstanceState: Bundle?) { | ||
super.onCreate(savedInstanceState) | ||
binding.tvTmp.setOnClickListener { | ||
Intent(this, TypeActivity::class.java).apply { | ||
startActivity(this) | ||
} | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package poke.rogue.helper.presentation.type | ||
|
||
import android.os.Bundle | ||
import poke.rogue.helper.R | ||
import poke.rogue.helper.databinding.ActivityTypeBinding | ||
import poke.rogue.helper.local.dao.TypeDao | ||
import poke.rogue.helper.presentation.base.BindingActivity | ||
import poke.rogue.helper.presentation.type.mapper.toResultUiModel | ||
import poke.rogue.helper.presentation.type.model.TypeMatchedResultUiModel | ||
import poke.rogue.helper.presentation.type.typeselection.TypeSelectionBottomSheetFragment | ||
|
||
class TypeActivity : BindingActivity<ActivityTypeBinding>(R.layout.activity_type) { | ||
override fun onCreate(savedInstanceState: Bundle?) { | ||
super.onCreate(savedInstanceState) | ||
binding.ivTypeMyTypeContent.setOnClickListener { | ||
displayBottomSheet() | ||
} | ||
val dummy = | ||
TypeMatchedResultUiModel("페어리", R.drawable.img_property_tmp_2, true, "강한 타입", TypeDao.allTypes.map { it.toResultUiModel() }) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 사소한 부분이지만, 저는 개인적으로 멤버 참조를 사용하는 게 읽기 좋아서 그렇게 사용하고 있기는 합니다. |
||
binding.typeResult = dummy | ||
} | ||
|
||
private fun displayBottomSheet() { | ||
TypeSelectionBottomSheetFragment().show( | ||
supportFragmentManager, | ||
TypeSelectionBottomSheetFragment.TAG, | ||
) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package poke.rogue.helper.presentation.type | ||
|
||
import android.view.LayoutInflater | ||
import android.view.ViewGroup | ||
import androidx.recyclerview.widget.RecyclerView | ||
import poke.rogue.helper.databinding.ItemTypeNameBinding | ||
import poke.rogue.helper.presentation.type.model.TypeUiModel | ||
|
||
class TypeResultAdapter(private val types: List<TypeUiModel> = listOf()) : | ||
RecyclerView.Adapter<TypeResultViewHolder>() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ListAdapter 가 아닌 RecyclerView.Adapter 를 사용한 이유가 따로 있을까요? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. #8 (comment) |
||
override fun onCreateViewHolder( | ||
parent: ViewGroup, | ||
viewType: Int, | ||
): TypeResultViewHolder { | ||
val view = ItemTypeNameBinding.inflate(LayoutInflater.from(parent.context)) | ||
return TypeResultViewHolder(view) | ||
} | ||
|
||
override fun onBindViewHolder( | ||
holder: TypeResultViewHolder, | ||
position: Int, | ||
) { | ||
val item = types[position] | ||
holder.bind(item) | ||
} | ||
|
||
override fun getItemCount(): Int { | ||
return types.size | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
package poke.rogue.helper.presentation.type | ||
|
||
import android.content.Context | ||
import android.graphics.Color | ||
import android.text.SpannableStringBuilder | ||
import android.text.Spanned | ||
import android.text.style.ForegroundColorSpan | ||
import android.util.AttributeSet | ||
import android.view.LayoutInflater | ||
import androidx.constraintlayout.widget.ConstraintLayout | ||
import androidx.databinding.BindingAdapter | ||
import com.google.android.flexbox.FlexDirection | ||
import com.google.android.flexbox.FlexWrap | ||
import com.google.android.flexbox.FlexboxLayoutManager | ||
import com.google.android.flexbox.JustifyContent | ||
import poke.rogue.helper.databinding.ItemTypeResultBinding | ||
import poke.rogue.helper.presentation.type.model.TypeMatchedResultUiModel | ||
|
||
class TypeResultView(context: Context, attrs: AttributeSet) : | ||
ConstraintLayout(context, attrs) { | ||
private val binding: ItemTypeResultBinding by lazy { | ||
ItemTypeResultBinding.inflate(LayoutInflater.from(context), this, true) | ||
} | ||
private val flexboxLayoutManager: FlexboxLayoutManager by lazy { | ||
FlexboxLayoutManager(context).apply { | ||
flexWrap = FlexWrap.WRAP | ||
flexDirection = FlexDirection.ROW | ||
justifyContent = JustifyContent.FLEX_START | ||
} | ||
} | ||
|
||
fun bind(typeResult: TypeMatchedResultUiModel) { | ||
binding.typeResult = typeResult | ||
binding.tvResultMyTypeStrength.text = | ||
SpannableStringBuilder(typeResult.matchedResult).apply { | ||
setSpan( | ||
ForegroundColorSpan(Color.RED), | ||
0, | ||
2, | ||
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE, | ||
) | ||
} | ||
binding.ivResultMyType.setImageResource(typeResult.typeIconResId) | ||
binding.rvResultMatchedTypes.layoutManager = flexboxLayoutManager | ||
binding.rvResultMatchedTypes.adapter = TypeResultAdapter(typeResult.matchedItem) | ||
} | ||
|
||
companion object { | ||
@JvmStatic | ||
@BindingAdapter("typeResult") | ||
fun setTypeResult( | ||
view: TypeResultView, | ||
typeResult: TypeMatchedResultUiModel, | ||
) { | ||
view.bind(typeResult) | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package poke.rogue.helper.presentation.type | ||
|
||
import androidx.recyclerview.widget.RecyclerView | ||
import poke.rogue.helper.databinding.ItemTypeNameBinding | ||
import poke.rogue.helper.presentation.type.model.TypeUiModel | ||
|
||
class TypeResultViewHolder( | ||
private val binding: ItemTypeNameBinding, | ||
) : RecyclerView.ViewHolder(binding.root) { | ||
fun bind(typeItem: TypeUiModel) { | ||
binding.type = typeItem | ||
binding.ivTypeNameIcon.setImageResource(typeItem.iconResId) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 제가 imageRes 는 바인딩 어뎁터를 추가 설정을 안했군요.. // CommonBIndingAdapter
@BindingAdapter("imageRes")
fun ImageView.setImageRes(imageRes: Int) {
setImageResource(imageRes)
} 추가하도록 하겠습니다 |
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
package poke.rogue.helper.presentation.type.mapper | ||
|
||
import poke.rogue.helper.R | ||
import poke.rogue.helper.data.model.TypeInfo | ||
import poke.rogue.helper.presentation.type.model.TypeUiModel | ||
|
||
fun TypeInfo.toSelectionUiModel(): TypeUiModel { | ||
val imageResId = | ||
when (this.id) { | ||
0 -> R.drawable.img_type_tmp_1 | ||
1 -> R.drawable.img_type_tmp_1 | ||
2 -> R.drawable.img_type_tmp_1 | ||
3 -> R.drawable.img_type_tmp_1 | ||
4 -> R.drawable.img_type_tmp_1 | ||
5 -> R.drawable.img_type_tmp_1 | ||
6 -> R.drawable.img_type_tmp_1 | ||
7 -> R.drawable.img_type_tmp_1 | ||
8 -> R.drawable.img_type_tmp_1 | ||
9 -> R.drawable.img_type_tmp_1 | ||
10 -> R.drawable.img_type_tmp_1 | ||
11 -> R.drawable.img_type_tmp_1 | ||
12 -> R.drawable.img_type_tmp_1 | ||
13 -> R.drawable.img_type_tmp_1 | ||
14 -> R.drawable.img_type_tmp_1 | ||
15 -> R.drawable.img_type_tmp_1 | ||
16 -> R.drawable.img_type_tmp_1 | ||
17 -> R.drawable.img_type_tmp_1 | ||
else -> throw IllegalArgumentException("Unknown type ID") | ||
} | ||
return TypeUiModel(this.id, this.name, imageResId) | ||
} | ||
|
||
fun TypeInfo.toResultUiModel(): TypeUiModel { | ||
val imageResId = | ||
when (this.id) { | ||
0 -> R.drawable.img_property_tmp_1 | ||
1 -> R.drawable.img_property_tmp_1 | ||
2 -> R.drawable.img_property_tmp_1 | ||
3 -> R.drawable.img_property_tmp_1 | ||
4 -> R.drawable.img_property_tmp_1 | ||
5 -> R.drawable.img_property_tmp_1 | ||
6 -> R.drawable.img_property_tmp_1 | ||
7 -> R.drawable.img_property_tmp_1 | ||
8 -> R.drawable.img_property_tmp_1 | ||
9 -> R.drawable.img_property_tmp_1 | ||
10 -> R.drawable.img_property_tmp_1 | ||
11 -> R.drawable.img_property_tmp_1 | ||
12 -> R.drawable.img_property_tmp_1 | ||
13 -> R.drawable.img_property_tmp_1 | ||
14 -> R.drawable.img_property_tmp_1 | ||
15 -> R.drawable.img_property_tmp_1 | ||
16 -> R.drawable.img_property_tmp_1 | ||
17 -> R.drawable.img_property_tmp_1 | ||
else -> throw IllegalArgumentException("Unknown type ID") | ||
} | ||
return TypeUiModel(this.id, this.name, imageResId) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package poke.rogue.helper.presentation.type.mapper | ||
|
||
import poke.rogue.helper.R | ||
import poke.rogue.helper.data.model.MatchedResult | ||
|
||
fun MatchedResult.displayName(): String { | ||
return when (this) { | ||
MatchedResult.STRONG -> "강한" | ||
MatchedResult.WEAK -> "약한" | ||
MatchedResult.INEFFECTIVE -> "무효한" | ||
MatchedResult.NORMAL -> throw IllegalStateException("") | ||
} | ||
} | ||
|
||
fun MatchedResult.displayColor(): Int { | ||
return when (this) { | ||
MatchedResult.STRONG -> R.color.white | ||
MatchedResult.WEAK -> R.color.white | ||
MatchedResult.INEFFECTIVE -> R.color.white | ||
MatchedResult.NORMAL -> throw IllegalStateException("") | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package poke.rogue.helper.presentation.type.model | ||
|
||
import androidx.annotation.DrawableRes | ||
|
||
data class TypeMatchedResultUiModel( | ||
val typeName: String, | ||
@DrawableRes val typeIconResId: Int, | ||
val isMyType: Boolean, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 내 타입만 선택 or 상대 타입만 선택에 따라서 보여지는 텍스트의 위치가 달라지는데, 이를 처리하기 위해서 넣었습니다! |
||
val matchedResult: String, | ||
val matchedItem: List<TypeUiModel>, | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package poke.rogue.helper.presentation.type.model | ||
|
||
import androidx.annotation.DrawableRes | ||
|
||
data class TypeUiModel( | ||
val id: Int, | ||
val name: String, | ||
@DrawableRes val iconResId: Int, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. DrawableRes 애노테이션 좋아요 👍 |
||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package poke.rogue.helper.presentation.type.typeselection | ||
|
||
import android.view.LayoutInflater | ||
import android.view.ViewGroup | ||
import androidx.recyclerview.widget.RecyclerView | ||
import poke.rogue.helper.databinding.ItemTypeChoiceBinding | ||
import poke.rogue.helper.presentation.type.model.TypeUiModel | ||
|
||
class TypeSelectionAdapter(private val types: List<TypeUiModel> = listOf()) : | ||
RecyclerView.Adapter<TypeSelectionViewHolder>() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ViewModel 작업할 때 ListAdapter 로 바꿔주시는건가요?! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 흠 |
||
override fun onCreateViewHolder( | ||
parent: ViewGroup, | ||
viewType: Int, | ||
): TypeSelectionViewHolder { | ||
val view = ItemTypeChoiceBinding.inflate(LayoutInflater.from(parent.context)) | ||
return TypeSelectionViewHolder(view) | ||
} | ||
|
||
override fun getItemCount(): Int { | ||
return types.size | ||
} | ||
|
||
override fun onBindViewHolder( | ||
holder: TypeSelectionViewHolder, | ||
position: Int, | ||
) { | ||
val item = types[position] | ||
holder.bind(item) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package poke.rogue.helper.presentation.type.typeselection | ||
|
||
import android.os.Bundle | ||
import android.view.LayoutInflater | ||
import android.view.View | ||
import android.view.ViewGroup | ||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment | ||
import poke.rogue.helper.databinding.FragmentTypeChoiceBottomSheetBinding | ||
import poke.rogue.helper.local.dao.TypeDao | ||
import poke.rogue.helper.presentation.type.mapper.toSelectionUiModel | ||
import poke.rogue.helper.presentation.util.view.GridSpacingItemDecoration | ||
import poke.rogue.helper.presentation.util.view.dp | ||
|
||
class TypeSelectionBottomSheetFragment : BottomSheetDialogFragment() { | ||
private var _binding: FragmentTypeChoiceBottomSheetBinding? = null | ||
private val binding get() = requireNotNull(_binding) | ||
private val adapter by lazy { | ||
TypeSelectionAdapter(TypeDao.allTypes.map { it.toSelectionUiModel() }) | ||
} | ||
|
||
override fun onCreateView( | ||
inflater: LayoutInflater, | ||
container: ViewGroup?, | ||
savedInstanceState: Bundle?, | ||
): View { | ||
_binding = FragmentTypeChoiceBottomSheetBinding.inflate(inflater, container, false) | ||
return binding.root | ||
} | ||
|
||
override fun onViewCreated( | ||
view: View, | ||
savedInstanceState: Bundle?, | ||
) { | ||
super.onViewCreated(view, savedInstanceState) | ||
initAdapter() | ||
} | ||
|
||
private fun initAdapter() { | ||
binding.rvTypeChoice.adapter = adapter | ||
val decoration = | ||
GridSpacingItemDecoration(spanCount = 4, spacing = 19.dp, includeEdge = false) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 👍 👍 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 아하 spacing 에 |
||
binding.rvTypeChoice.addItemDecoration(decoration) | ||
} | ||
|
||
override fun onDestroyView() { | ||
super.onDestroyView() | ||
_binding = null | ||
} | ||
|
||
companion object { | ||
const val TAG = "type_selection_bottom_sheet_fragment" | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
추가하느라 고생하셨습니다 👍