Skip to content
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

feat: add toolbar & bottom navigation bar #71

Merged
merged 17 commits into from
Jan 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/mobile/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,9 @@ dependencies {
//CircleImageView
implementation ("de.hdodenhof:circleimageview:3.1.0")


//lottie Animation
implementation("com.airbnb.android:lottie:6.0.0")

//bottom navigation bar
implementation ("me.majiajie:pager-bottom-tab-strip:2.4.0")
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,18 @@ package com.smilegate.Easel

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.MenuItem
import android.view.MotionEvent
import android.widget.Toolbar
import androidx.activity.OnBackPressedCallback
import androidx.core.content.ContextCompat
import androidx.core.view.WindowInsetsControllerCompat
import androidx.navigation.NavController
import androidx.navigation.findNavController
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.AppBarConfiguration
import com.google.android.material.bottomnavigation.LabelVisibilityMode
import com.google.android.material.navigation.NavigationBarView
import com.smilegate.Easel.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {
Expand All @@ -15,6 +23,8 @@ class MainActivity : AppCompatActivity() {
ActivityMainBinding.inflate(layoutInflater)
}

private var lastSelectedIconId: Int? = null

override fun onCreate(savedInstanceState: Bundle?) {

super.onCreate(savedInstanceState)
Expand All @@ -30,5 +40,91 @@ class MainActivity : AppCompatActivity() {
isAppearanceLightStatusBars = true
isAppearanceLightNavigationBars = true
}

window.decorView.setBackgroundColor(ContextCompat.getColor(this, android.R.color.white))

val toolbar = findViewById<androidx.appcompat.widget.Toolbar>(R.id.toolbar_container)
setSupportActionBar(toolbar)

// 타이틀을 비워서 보이지 않도록 설정
supportActionBar?.title = ""
toolbar.setBackgroundColor(ContextCompat.getColor(this, R.color.white))

// 앱 초기 실행 시 홈화면으로 설정
if (savedInstanceState == null) {
binding.navView.selectedItemId = R.id.timelineFragment
lastSelectedIconId = R.id.navigation_home
updateIcon(R.id.navigation_home, R.drawable.ic_solid_home)
}

binding.navView.labelVisibilityMode = NavigationBarView.LABEL_VISIBILITY_UNLABELED

binding.navView.setOnNavigationItemSelectedListener { item ->
onNavigationItemSelected(item)
}
}

private fun updateIcon(itemId: Int, iconResId: Int) {
val item = binding.navView.menu.findItem(itemId)
// 현재 아이콘과 변경하려는 아이콘이 같지 않을 때만 변경
if (item?.icon?.constantState != ContextCompat.getDrawable(this, iconResId)?.constantState) {
item?.setIcon(iconResId)
}
}

fun onNavigationItemSelected(item: MenuItem): Boolean {
val currentIconId = item.itemId

val selectedIcon = getSelectedIcon(currentIconId)
item.setIcon(selectedIcon)

// 이전에 선택된 아이콘 원래 아이콘으로 변경
if (lastSelectedIconId != null && lastSelectedIconId != currentIconId) {
val lastSelectedItem = binding.navView.menu.findItem(lastSelectedIconId!!)
lastSelectedItem?.setIcon(getOriginalIcon(lastSelectedIconId!!))
}

// 이전에 선택된 아이콘 ID 업데이트
lastSelectedIconId = currentIconId

when (currentIconId) {
R.id.navigation_home -> {
findNavController(R.id.nav_host_fragment).navigate(R.id.timelineFragment)
return true
}
R.id.navigation_search -> {
findNavController(R.id.nav_host_fragment).navigate(R.id.searchFragment)
return true
}
R.id.navigation_notice -> {
findNavController(R.id.nav_host_fragment).navigate(R.id.noticeFragment)
return true
}
R.id.navigation_message -> {
findNavController(R.id.nav_host_fragment).navigate(R.id.messageFragment)
return true
}
}
return false
}

private fun getSelectedIcon(itemId: Int): Int {
return when (itemId) {
R.id.navigation_home -> R.drawable.ic_solid_home
R.id.navigation_search -> R.drawable.ic_selected_search
R.id.navigation_notice -> R.drawable.ic_solid_bell
R.id.navigation_message -> R.drawable.ic_solid_mail
else -> throw IllegalArgumentException("Invalid item ID")
}
}

private fun getOriginalIcon(itemId: Int): Int {
return when (itemId) {
R.id.navigation_home -> R.drawable.ic_home
R.id.navigation_search -> R.drawable.ic_search
R.id.navigation_notice -> R.drawable.ic_bell
R.id.navigation_message -> R.drawable.ic_mail
else -> throw IllegalArgumentException("Invalid item ID")
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package com.smilegate.Easel.domain

import android.os.Handler
import android.os.Looper
import android.view.KeyEvent
import android.view.inputmethod.EditorInfo
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.FragmentActivity

fun isDoneAction(actionId: Int, event: KeyEvent?): Boolean {
return actionId == EditorInfo.IME_ACTION_DONE ||
Expand All @@ -12,3 +16,19 @@ fun isDoneAction(actionId: Int, event: KeyEvent?): Boolean {
fun containsSpaceOrNewline(s: CharSequence?): Boolean {
return s?.contains(" ") == true || s?.contains("\n") == true
}


fun handleBackPressed(activity: AppCompatActivity, doubleBackPressed: Boolean): Boolean {
var doubleBackPressedVar = doubleBackPressed

if (doubleBackPressedVar) {
// 두 번째 눌림
activity.finish()
} else {
// 2초 내에 두 번 누르지 않으면 초기화
Handler(Looper.getMainLooper()).postDelayed({
doubleBackPressedVar = false
}, 2000)
}
return true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package com.smilegate.Easel.presentation.view.Timeline

import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.view.KeyEvent
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.Toast
import androidx.activity.addCallback
import androidx.navigation.NavController
import androidx.navigation.fragment.findNavController
import com.google.android.material.bottomnavigation.BottomNavigationView
import com.smilegate.Easel.R
import com.smilegate.Easel.databinding.FragmentStartBinding
import com.smilegate.Easel.databinding.FragmentTimelineBinding

class TimelineFragment : Fragment() {
private lateinit var binding: FragmentTimelineBinding

private lateinit var navController: NavController

private var doubleBackPressed = false

override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = FragmentTimelineBinding.inflate(inflater, container, false)

val toolbar = requireActivity().findViewById<androidx.appcompat.widget.Toolbar>(R.id.toolbar_container)
val backButton = toolbar.findViewById<ImageView>(R.id.back_btn)
backButton.visibility = View.GONE

val settingButton = toolbar.findViewById<ImageView>(R.id.else_btn)
settingButton.setImageResource(R.drawable.ic_setting)
settingButton.visibility = View.VISIBLE

navController = findNavController()

// 바텀 네비게이션바 보이기
val bottomNavigation = activity?.findViewById<BottomNavigationView>(R.id.nav_view)
bottomNavigation?.visibility = View.VISIBLE

return binding.root
}

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

// 바텀 네비게이션바 보이기
val bottomNavigation = activity?.findViewById<BottomNavigationView>(R.id.nav_view)
bottomNavigation?.visibility = View.VISIBLE

// 뒤로가기 버튼을 처리하는 부분
view.isFocusableInTouchMode = true
view.requestFocus()
view.setOnKeyListener { _, keyCode, _ ->
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (isCurrentFragment()) {
// 현재 프래그먼트에서 뒤로가기 버튼 처리
if (doubleBackPressed) {
// 두 번째 눌림
requireActivity().finish()
} else {
// 첫 번째 눌림
doubleBackPressed = true
// 2초 내에 두 번 누르지 않으면 초기화
Handler(Looper.getMainLooper()).postDelayed({
doubleBackPressed = false
}, 2000)
Comment on lines +72 to +74
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

디테일 너무 좋습니다 💯 👍

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

두 번 터치 시 종료되는 액션은 추후 반영해보겠습니다....🥹

}
return@setOnKeyListener true
}
}
false
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

별건 아닌데 개행이 빠진 것 같아요!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

수정 완료했습니다~


private fun isCurrentFragment(): Boolean {
return true
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.smilegate.Easel.presentation.view.join

import android.content.Context
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
Expand All @@ -9,8 +10,10 @@ import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.InputMethodManager
import android.widget.Button
import android.widget.EditText
import android.widget.ImageView
import androidx.core.content.ContextCompat
import androidx.navigation.NavController
import androidx.navigation.fragment.findNavController
Expand All @@ -32,13 +35,29 @@ class AskNameFragment : Fragment() {

navController = findNavController()

binding.askNameFragmentJoinBtn.setOnClickListener {
navController.navigate(R.id.action_askNameFragment_to_timelineFragment)
hideKeyboard()
}

return binding.root
}

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

val toolbar = requireActivity().findViewById<androidx.appcompat.widget.Toolbar>(R.id.toolbar_container)
val backButton = toolbar.findViewById<ImageView>(R.id.back_btn)
backButton.visibility = View.VISIBLE

backButton.setOnClickListener {
findNavController().navigateUp()
}

val settingButton = toolbar.findViewById<ImageView>(R.id.else_btn)
settingButton.setImageResource(R.drawable.ic_setting)
settingButton.visibility = View.GONE

binding.askNameFragmentIdField.addTextChangedListener(object : TextWatcher {
// 텍스트 변경 전에 호출되는 메소드
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
Expand Down Expand Up @@ -78,4 +97,15 @@ class AskNameFragment : Fragment() {
nextButton?.setTextColor(textColor)
}
}

private fun hideKeyboard() {
val inputMethodManager =
requireActivity().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager

// 현재 포커스된 뷰에서 키패드를 감춥니다.
val focusedView = requireActivity().currentFocus
focusedView?.let {
inputMethodManager.hideSoftInputFromWindow(it.windowToken, 0)
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.smilegate.Easel.presentation.view.join

import android.graphics.Color
import android.graphics.PorterDuff
import android.os.Bundle
import android.text.Editable
import android.text.SpannableString
Expand All @@ -11,9 +12,13 @@ import android.text.style.ClickableSpan
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.View.GONE
import android.view.ViewGroup
import android.view.inputmethod.EditorInfo
import android.widget.ImageView
import android.widget.Toast
import android.widget.Toolbar
import androidx.appcompat.widget.AppCompatImageView
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
Expand Down Expand Up @@ -62,6 +67,15 @@ class CreateAccountFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

val toolbar = requireActivity().findViewById<androidx.appcompat.widget.Toolbar>(R.id.toolbar_container)
val backButton = toolbar.findViewById<ImageView>(R.id.back_btn)
backButton.visibility = View.VISIBLE

backButton.setOnClickListener {
findNavController().navigateUp()
backButton.visibility = GONE
}

binding.createAccountInfoField.setOnFocusChangeListener { _, hasFocus ->
if (!hasFocus) {
validateEmail()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import android.view.ViewGroup
import android.view.inputmethod.EditorInfo
import android.widget.Button
import android.widget.EditText
import android.widget.ImageView
import android.widget.Toast
import androidx.core.content.ContextCompat
import androidx.navigation.NavController
Expand Down Expand Up @@ -50,6 +51,14 @@ class NeedPasswordFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

val toolbar = requireActivity().findViewById<androidx.appcompat.widget.Toolbar>(R.id.toolbar_container)
val backButton = toolbar.findViewById<ImageView>(R.id.back_btn)
backButton.visibility = View.VISIBLE

backButton.setOnClickListener {
findNavController().navigateUp()
}

binding.needPasswordFragmentPwShowBtn.setOnClickListener {
passwordVisibility()
}
Expand Down Expand Up @@ -125,7 +134,7 @@ class NeedPasswordFragment : Fragment() {
private fun validatePassword() {
val password = binding.needPasswordFragmentPwField.text.toString()

if (password.length < 8) {
if (password.length < maxPasswordLength) {
// 비밀번호가 8자 미만인 경우
val pwColorResourceId = ContextCompat.getColor(requireContext(), R.color.Red_200)
binding.needPasswordFragmentPwField.setTextColor(pwColorResourceId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,13 @@ class ProfileImageFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

val toolbar = requireActivity().findViewById<androidx.appcompat.widget.Toolbar>(R.id.toolbar_container)
val backButton = toolbar.findViewById<ImageView>(R.id.back_btn)
backButton.visibility = View.VISIBLE

backButton.setOnClickListener {
findNavController().navigateUp()
}
}

// override fun onDestroyView() {
Expand Down
Loading