diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 5373128e..c41bcfd2 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -31,6 +31,7 @@ android { testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" buildConfigField("String", "BASE_URL", properties["base.url"].toString()) buildConfigField("String", "ACCESS_TOKEN", properties["access.token"].toString()) + buildConfigField("String", "NAVER_MAP_CLIENT_ID", properties["naver.map.client.id"].toString()) manifestPlaceholders["IO_SENTRY_DSN"] = properties["io.sentry.dsn"] as String } @@ -89,6 +90,12 @@ dependencies { implementation(libs.bundles.okhttp) implementation(libs.bundles.retrofit) implementation(libs.kotlin.serialization.json) + + // Naver Map + implementation(libs.naver.maps) + + // Location + implementation(libs.play.services.location) } ktlint { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 988dfb5e..f978e34b 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -3,6 +3,8 @@ xmlns:tools="http://schemas.android.com/tools"> + + + R.drawable.ic_map_marker_play_small + CategoryType.STUDY.toString() -> R.drawable.ic_map_marker_study_small + CategoryType.MULTI.toString() -> R.drawable.ic_map_marker_multi_small + else -> R.drawable.ic_map_marker_other_small + } + ) +} diff --git a/app/src/main/java/org/sopt/pingle/presentation/ui/joingroup/JoinGroupSuccessActivity.kt b/app/src/main/java/org/sopt/pingle/presentation/ui/joingroup/JoinGroupSuccessActivity.kt new file mode 100644 index 00000000..3510fba4 --- /dev/null +++ b/app/src/main/java/org/sopt/pingle/presentation/ui/joingroup/JoinGroupSuccessActivity.kt @@ -0,0 +1,58 @@ +package org.sopt.pingle.presentation.ui.joingroup + +import android.os.Bundle +import android.text.Spannable +import android.text.SpannableString +import android.text.style.ForegroundColorSpan +import android.text.style.TextAppearanceSpan +import androidx.core.content.ContextCompat +import org.sopt.pingle.R +import org.sopt.pingle.databinding.ActivityJoinGroupSuccessBinding +import org.sopt.pingle.util.base.BindingActivity + +class JoinGroupSuccessActivity : + BindingActivity(R.layout.activity_join_group_success) { + private lateinit var groupName: String + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + initLayout() + } + + private fun initLayout() { + // TODO 이전 화면에서 Intent를 통해서 groupName을 가져옴 + groupName = "SOPT" + + binding.tvJoinGroupSuccessDescriptionGroupName.text = SpannableString( + getString( + R.string.join_group_success_description_group_name, + groupName + ) + ).apply { + setSpan( + TextAppearanceSpan( + this@JoinGroupSuccessActivity, + R.style.TextAppearance_Pingle_Sub_Semi_16 + ), + GROUP_NAME_START, + groupName.length, + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE + ) + setSpan( + ForegroundColorSpan( + ContextCompat.getColor( + this@JoinGroupSuccessActivity, + R.color.g_01 + ) + ), + GROUP_NAME_START, + groupName.length, + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE + ) + } + } + + companion object { + const val GROUP_NAME_START = 0 + } +} diff --git a/app/src/main/java/org/sopt/pingle/presentation/ui/main/MainActivity.kt b/app/src/main/java/org/sopt/pingle/presentation/ui/main/MainActivity.kt index 92a6236b..51bbda25 100644 --- a/app/src/main/java/org/sopt/pingle/presentation/ui/main/MainActivity.kt +++ b/app/src/main/java/org/sopt/pingle/presentation/ui/main/MainActivity.kt @@ -63,8 +63,10 @@ class MainActivity : BindingActivity(R.layout.activity_main } private inline fun navigateToFragment() { - supportFragmentManager.commit { - replace(R.id.fcv_main_all_navi, T::class.java.canonicalName) + if (supportFragmentManager.findFragmentById(R.id.fcv_main_all_navi) !is T) { + supportFragmentManager.commit { + replace(R.id.fcv_main_all_navi, T::class.java.canonicalName) + } } } } diff --git a/app/src/main/java/org/sopt/pingle/presentation/ui/main/home/map/MapFragment.kt b/app/src/main/java/org/sopt/pingle/presentation/ui/main/home/map/MapFragment.kt index 8349651d..074d46f3 100644 --- a/app/src/main/java/org/sopt/pingle/presentation/ui/main/home/map/MapFragment.kt +++ b/app/src/main/java/org/sopt/pingle/presentation/ui/main/home/map/MapFragment.kt @@ -1,13 +1,179 @@ package org.sopt.pingle.presentation.ui.main.home.map +import android.Manifest +import android.content.pm.PackageManager +import android.location.Location import android.os.Bundle import android.view.View +import androidx.activity.result.contract.ActivityResultContracts +import androidx.core.content.ContextCompat +import androidx.fragment.app.add +import androidx.fragment.app.commit +import androidx.fragment.app.viewModels +import androidx.lifecycle.flowWithLifecycle +import androidx.lifecycle.lifecycleScope +import com.google.android.gms.location.LocationServices +import com.naver.maps.geometry.LatLng +import com.naver.maps.map.CameraAnimation +import com.naver.maps.map.CameraUpdate +import com.naver.maps.map.LocationTrackingMode +import com.naver.maps.map.MapFragment +import com.naver.maps.map.NaverMap +import com.naver.maps.map.OnMapReadyCallback +import com.naver.maps.map.overlay.OverlayImage +import com.naver.maps.map.util.FusedLocationSource +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach import org.sopt.pingle.R import org.sopt.pingle.databinding.FragmentMapBinding +import org.sopt.pingle.presentation.mapper.toMarker +import org.sopt.pingle.presentation.type.CategoryType import org.sopt.pingle.util.base.BindingFragment +import org.sopt.pingle.util.component.PingleChip +import org.sopt.pingle.util.fragment.showToast + +class MapFragment : BindingFragment(R.layout.fragment_map), OnMapReadyCallback { + private val mapViewModel by viewModels() + private lateinit var naverMap: NaverMap + private lateinit var locationSource: FusedLocationSource -class MapFragment : BindingFragment(R.layout.fragment_map) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + + initMap() + initLayout() + addListeners() + collectData() + setLocationTrackingMode() + } + + override fun onMapReady(naverMap: NaverMap) { + this.naverMap = naverMap.apply { + isNightModeEnabled = true + mapType = NaverMap.MapType.Navi + + with(uiSettings) { + isZoomControlEnabled = false + isScaleBarEnabled = false + } + } + + makeMarkers() + } + + private fun initMap() { + val mapFragment = + childFragmentManager.findFragmentById(R.id.fragment_map_naver_map) as MapFragment? + ?: MapFragment.newInstance().also { + childFragmentManager.commit { + add(R.id.fragment_map_naver_map) + setReorderingAllowed(true) + } + } + + mapFragment.getMapAsync(this@MapFragment) + } + + private fun initLayout() { + with(binding) { + chipMapCategoryPlay.setChipCategoryType(CategoryType.PLAY) + chipMapCategoryStudy.setChipCategoryType(CategoryType.STUDY) + chipMapCategoryMulti.setChipCategoryType(CategoryType.MULTI) + chipMapCategoryOthers.setChipCategoryType(CategoryType.OTHER) + } + } + + private fun addListeners() { + binding.fabMapHere.setOnClickListener { + if (::locationSource.isInitialized) { + locationSource.lastLocation?.let { location -> moveMapCamera(location) } + } + } + + binding.cgMapCategory.setOnCheckedStateChangeListener { group, checkedIds -> + mapViewModel.setCategory( + category = checkedIds.getOrNull(SINGLE_SELECTION) + ?.let { group.findViewById(it).categoryType } + ) + } + } + + private fun collectData() { + mapViewModel.category.flowWithLifecycle(lifecycle).onEach { + // TODO 서버 통신 구현 시 삭제 예정 + showToast(it?.name ?: "null") + }.launchIn(lifecycleScope) + } + + private fun setLocationTrackingMode() { + if (LOCATION_PERMISSIONS.any { permission -> + ContextCompat.checkSelfPermission( + requireContext(), + permission + ) == PackageManager.PERMISSION_GRANTED + } + ) { + locationSource = FusedLocationSource(this, LOCATION_PERMISSION_REQUEST_CODE) + } else { + requestLocationPermission() + } + + LocationServices.getFusedLocationProviderClient(requireContext()).lastLocation.addOnSuccessListener { location -> + if (::naverMap.isInitialized) { + with(naverMap) { + locationSource = this@MapFragment.locationSource + locationTrackingMode = LocationTrackingMode.NoFollow + + locationOverlay.apply { + isVisible = true + icon = OverlayImage.fromResource(R.drawable.ic_map_location_overlay) + } + } + } + + moveMapCamera(location) + } + } + + private fun requestLocationPermission() { + val locationPermissionRequest = registerForActivityResult( + ActivityResultContracts.RequestMultiplePermissions() + ) { permissions -> + when { + permissions[LOCATION_PERMISSIONS[0]] == true || permissions[LOCATION_PERMISSIONS[1]] == true -> { + setLocationTrackingMode() + } + } + } + + locationPermissionRequest.launch(LOCATION_PERMISSIONS) + } + + private fun moveMapCamera(location: Location) { + if (::naverMap.isInitialized) { + naverMap.moveCamera( + CameraUpdate.scrollTo( + LatLng( + location.latitude, + location.longitude + ) + ).animate(CameraAnimation.Linear) + ) + } + } + + private fun makeMarkers() { + mapViewModel.dummyPinList.map { pinEntity -> + pinEntity.toMarker().map = naverMap + } + } + + companion object { + private const val LOCATION_PERMISSION_REQUEST_CODE = 1000 + private val LOCATION_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_FINE_LOCATION, + Manifest.permission.ACCESS_COARSE_LOCATION + ) + private const val SINGLE_SELECTION = 0 } } diff --git a/app/src/main/java/org/sopt/pingle/presentation/ui/main/home/map/MapViewModel.kt b/app/src/main/java/org/sopt/pingle/presentation/ui/main/home/map/MapViewModel.kt new file mode 100644 index 00000000..d4a9947d --- /dev/null +++ b/app/src/main/java/org/sopt/pingle/presentation/ui/main/home/map/MapViewModel.kt @@ -0,0 +1,47 @@ +package org.sopt.pingle.presentation.ui.main.home.map + +import androidx.lifecycle.ViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import org.sopt.pingle.domain.model.PinEntity +import org.sopt.pingle.presentation.type.CategoryType + +class MapViewModel() : ViewModel() { + val dummyPinList = listOf( + PinEntity( + id = 1, + x = 126.9275108, + y = 37.5262935, + category = "PLAY", + meetingCount = 1 + ), + PinEntity( + id = 2, + x = 126.9283122, + y = 37.5259168, + category = "STUDY", + meetingCount = 2 + ), + PinEntity( + id = 3, + x = 126.9276423, + y = 37.5258711, + category = "MULTI", + meetingCount = 1 + ), + PinEntity( + id = 4, + x = 126.9286719, + y = 37.5253629, + category = "OTHERS", + meetingCount = 2 + ) + ) + + private val _category = MutableStateFlow(null) + val category get() = _category.asStateFlow() + + fun setCategory(category: CategoryType?) { + _category.value = category + } +} diff --git a/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/PlanActivity.kt b/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/PlanActivity.kt index 76c5e81b..d8fe71b3 100644 --- a/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/PlanActivity.kt +++ b/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/PlanActivity.kt @@ -1,13 +1,89 @@ package org.sopt.pingle.presentation.ui.main.plan import android.os.Bundle +import androidx.activity.viewModels +import androidx.fragment.app.Fragment +import androidx.lifecycle.flowWithLifecycle +import androidx.lifecycle.lifecycleScope +import androidx.viewpager2.widget.ViewPager2 +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach import org.sopt.pingle.R import org.sopt.pingle.databinding.ActivityPlanBinding import org.sopt.pingle.util.base.BindingActivity class PlanActivity : BindingActivity(R.layout.activity_plan) { + private val planViewModel: PlanViewModel by viewModels() + private lateinit var fragmentList: ArrayList override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(R.layout.activity_plan) + + setPlanFragmentStateAdapter() + addListeners() + collectData() + } + + private fun setPlanFragmentStateAdapter() { + // TODO 차후에 나머지 개최 프로세스 fragment 추가 + fragmentList = ArrayList() + fragmentList.apply { + add(PlanTitleFragment()) + add(PlanDateTimeFragment()) + add(PlanOpenChattingFragment()) + } + + val adapter = PlanFragmentStateAdapter(fragmentList, this) + with(binding.vpPlan) { + this.adapter = adapter + isUserInputEnabled = false + registerOnPageChangeCallback(object : + ViewPager2.OnPageChangeCallback() { + override fun onPageSelected(position: Int) { + super.onPageSelected(position) + planViewModel.setCurrentPage(position) + } + }) + } + } + + private fun addListeners() { + binding.btnPlan.setOnClickListener { + when (binding.vpPlan.currentItem) { + // TODO 핑글 개최 api 연동 + fragmentList.size - 1 -> {} + else -> { + binding.vpPlan.currentItem++ + } + } + } + binding.toolbar.ivAllTopbarArrowWithTitleArrowLeft.setOnClickListener { + when (binding.vpPlan.currentItem) { + 0 -> { + // TODO 나가기 확인 모달 + } + + else -> { + binding.vpPlan.currentItem-- + } + } + } + binding.tvPlanClose.setOnClickListener { + // TODO 나가기 확인 모달 + } + } + + private fun collectData() { + planViewModel.currentPage.flowWithLifecycle(lifecycle).onEach { currentPage -> + when (currentPage) { + fragmentList.size - 1 -> { + binding.btnPlan.text = getString(R.string.plan_pingle) + } + + // TODO 다른 다음으로 스트링과 합치기 + else -> { + binding.btnPlan.text = getString(R.string.plan_next) + } + } + }.launchIn(lifecycleScope) } } diff --git a/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/PlanDateTimeFragment.kt b/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/PlanDateTimeFragment.kt new file mode 100644 index 00000000..e522a8a7 --- /dev/null +++ b/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/PlanDateTimeFragment.kt @@ -0,0 +1,13 @@ +package org.sopt.pingle.presentation.ui.main.plan + +import android.os.Bundle +import android.view.View +import org.sopt.pingle.R +import org.sopt.pingle.databinding.FragmentPlanDateTimeBinding +import org.sopt.pingle.util.base.BindingFragment + +class PlanDateTimeFragment : BindingFragment(R.layout.fragment_plan_date_time) { + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + } +} diff --git a/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/PlanFragmentStateAdapter.kt b/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/PlanFragmentStateAdapter.kt new file mode 100644 index 00000000..7a784ee4 --- /dev/null +++ b/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/PlanFragmentStateAdapter.kt @@ -0,0 +1,15 @@ +package org.sopt.pingle.presentation.ui.main.plan + +import androidx.fragment.app.Fragment +import androidx.fragment.app.FragmentActivity +import androidx.viewpager2.adapter.FragmentStateAdapter + +class PlanFragmentStateAdapter( + private val fragmentList: ArrayList, + fragmentActivity: FragmentActivity +) : FragmentStateAdapter(fragmentActivity) { + override fun getItemCount(): Int = fragmentList.size + override fun createFragment(position: Int): Fragment { + return fragmentList[position] + } +} diff --git a/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/PlanOpenChattingFragment.kt b/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/PlanOpenChattingFragment.kt new file mode 100644 index 00000000..53585426 --- /dev/null +++ b/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/PlanOpenChattingFragment.kt @@ -0,0 +1,13 @@ +package org.sopt.pingle.presentation.ui.main.plan + +import android.os.Bundle +import android.view.View +import org.sopt.pingle.R +import org.sopt.pingle.databinding.FragmentPlanOpenChattingBinding +import org.sopt.pingle.util.base.BindingFragment + +class PlanOpenChattingFragment : BindingFragment(R.layout.fragment_plan_open_chatting) { + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + } +} diff --git a/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/PlanTitleFragment.kt b/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/PlanTitleFragment.kt new file mode 100644 index 00000000..69fba4ba --- /dev/null +++ b/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/PlanTitleFragment.kt @@ -0,0 +1,13 @@ +package org.sopt.pingle.presentation.ui.main.plan + +import android.os.Bundle +import android.view.View +import org.sopt.pingle.R +import org.sopt.pingle.databinding.FragmentPlanTitleBinding +import org.sopt.pingle.util.base.BindingFragment + +class PlanTitleFragment : BindingFragment(R.layout.fragment_plan_title) { + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + } +} diff --git a/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/PlanViewModel.kt b/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/PlanViewModel.kt new file mode 100644 index 00000000..e3d14475 --- /dev/null +++ b/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/PlanViewModel.kt @@ -0,0 +1,18 @@ +package org.sopt.pingle.presentation.ui.main.plan + +import androidx.lifecycle.ViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow + +class PlanViewModel : ViewModel() { + private val _currentPage = MutableStateFlow(FIRST_PAGE_POSITION) + val currentPage get() = _currentPage.asStateFlow() + + fun setCurrentPage(position: Int) { + _currentPage.value = position + } + + companion object { + const val FIRST_PAGE_POSITION = 0 + } +} diff --git a/app/src/main/java/org/sopt/pingle/util/component/PingleChip.kt b/app/src/main/java/org/sopt/pingle/util/component/PingleChip.kt index 773c1893..3f2353ed 100644 --- a/app/src/main/java/org/sopt/pingle/util/component/PingleChip.kt +++ b/app/src/main/java/org/sopt/pingle/util/component/PingleChip.kt @@ -16,6 +16,8 @@ class PingleChip @JvmOverloads constructor( attrs: AttributeSet? = null, defStyleAttr: Int = R.style.Theme_Pingle_Chip_All ) : Chip(context, attrs, defStyleAttr) { + private lateinit var _categoryType: CategoryType + val categoryType get() = _categoryType private fun setColorStateList( context: Context, @@ -34,7 +36,9 @@ class PingleChip @JvmOverloads constructor( ) fun setChipCategoryType(categoryType: CategoryType) { - val inactivatedOutlinedColor = R.color.g_03 + this@PingleChip._categoryType = categoryType + + val inactivatedOutlinedColor = R.color.g_09 val inactivatedTextColor = R.color.g_03 val inactivatedChipColor = R.color.g_11 diff --git a/app/src/main/res/drawable/ic_map_location_overlay.xml b/app/src/main/res/drawable/ic_map_location_overlay.xml new file mode 100644 index 00000000..fd5c7ecc --- /dev/null +++ b/app/src/main/res/drawable/ic_map_location_overlay.xml @@ -0,0 +1,13 @@ + + + + diff --git a/app/src/main/res/drawable/ic_map_marker_multi_small.xml b/app/src/main/res/drawable/ic_map_marker_multi_small.xml new file mode 100644 index 00000000..0653bbf5 --- /dev/null +++ b/app/src/main/res/drawable/ic_map_marker_multi_small.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_map_marker_other_small.xml b/app/src/main/res/drawable/ic_map_marker_other_small.xml new file mode 100644 index 00000000..9772fec0 --- /dev/null +++ b/app/src/main/res/drawable/ic_map_marker_other_small.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_map_marker_play_small.xml b/app/src/main/res/drawable/ic_map_marker_play_small.xml new file mode 100644 index 00000000..51c12aa4 --- /dev/null +++ b/app/src/main/res/drawable/ic_map_marker_play_small.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_map_marker_study_small.xml b/app/src/main/res/drawable/ic_map_marker_study_small.xml new file mode 100644 index 00000000..4ce2370b --- /dev/null +++ b/app/src/main/res/drawable/ic_map_marker_study_small.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/activity_join_group_success.xml b/app/src/main/res/layout/activity_join_group_success.xml new file mode 100644 index 00000000..08200ab8 --- /dev/null +++ b/app/src/main/res/layout/activity_join_group_success.xml @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_plan.xml b/app/src/main/res/layout/activity_plan.xml index fc16e19f..e25ae8f8 100644 --- a/app/src/main/res/layout/activity_plan.xml +++ b/app/src/main/res/layout/activity_plan.xml @@ -9,19 +9,77 @@ + android:layout_height="match_parent"> - + + + + + + + + + + + app:layout_constraintEnd_toEndOf="@id/gl_end" + app:layout_constraintStart_toStartOf="@id/gl_start"> + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_map.xml b/app/src/main/res/layout/fragment_map.xml index 8f9f93d5..1a378bc8 100644 --- a/app/src/main/res/layout/fragment_map.xml +++ b/app/src/main/res/layout/fragment_map.xml @@ -12,16 +12,78 @@ android:layout_height="match_parent" tools:context=".presentation.ui.main.home.map.MapFragment"> - + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_plan_date_time.xml b/app/src/main/res/layout/fragment_plan_date_time.xml new file mode 100644 index 00000000..67ed5d4c --- /dev/null +++ b/app/src/main/res/layout/fragment_plan_date_time.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_plan_open_chatting.xml b/app/src/main/res/layout/fragment_plan_open_chatting.xml new file mode 100644 index 00000000..67ed5d4c --- /dev/null +++ b/app/src/main/res/layout/fragment_plan_open_chatting.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_plan_title.xml b/app/src/main/res/layout/fragment_plan_title.xml new file mode 100644 index 00000000..67ed5d4c --- /dev/null +++ b/app/src/main/res/layout/fragment_plan_title.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index a1daf7c5..920bb21f 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -28,12 +28,25 @@ 34dp 36dp - + + 16dp + + 60dp + + 56dp 42dp 42dp - + 10dp + + + 50dp + + + 4dp + + 24dp 24dp \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1a8770d2..a7b931e2 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -14,11 +14,23 @@ 마이핑글 설정 - + 핑글에 오신걸\n환영합니다! 기존 단체\n입장하기 신규 단체\n개설하기 + + 입장하기 + 단체 입장\n완료! + %s에서 + 핑글 여정을 함께해보세요! + + + 나중에 만드시겠어요? + 나가기 + 다음으로 + 핑글 개최하기 + 참여하기 diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index 32360682..3198761a 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -19,19 +19,19 @@ @@ -49,12 +49,26 @@ + + + + + \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 6eea7139..50ce45ee 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -36,6 +36,8 @@ retrofit = "2.9.0" retrofit-kotlin-serialization-converter = "1.0.0" kotlin-serialization-json = "1.5.1" sentry = "4.1.1" +naver-maps = "3.17.0" +play-services-location = "21.0.1" [libraries] # AndroidX @@ -73,6 +75,8 @@ okhttp-logging-interceptor = { group = "com.squareup.okhttp3", name = "logging-i retrofit = { group = "com.squareup.retrofit2", name = "retrofit", version.ref = "retrofit" } retrofit-kotlin-serialization-converter = { group = "com.jakewharton.retrofit", name = "retrofit2-kotlinx-serialization-converter", version.ref = "retrofit-kotlin-serialization-converter" } kotlin-serialization-json = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-json", version.ref = "kotlin-serialization-json" } +naver-maps = { group = "com.naver.maps", name = "map-sdk", version.ref = "naver-maps" } +play-services-location = { group = "com.google.android.gms", name = "play-services-location", version.ref = "play-services-location" } [plugins] android-application = { id = "com.android.application", version.ref = "agp" } diff --git a/settings.gradle.kts b/settings.gradle.kts index 336fb641..19c4ebfe 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -10,6 +10,7 @@ dependencyResolutionManagement { repositories { google() mavenCentral() + maven { setUrl("https://naver.jfrog.io/artifactory/maven/") } } }