<23/01/11>
앞에서 해결 못했던 문제들은 계속 찾아보고 있다.
우선, 이번주차에는 홈화면을 구현하기로 했다.
사진을 보면 BottomNavigationView를 사용하고 각 화면들은 Fragment로 구현해야 한다.
BottomNavigationView 사용방법이 잘 기억나지 않아 찾아보았다.
BottomNavigationView 사용법
- res폴더 Resource type을 Menu로 선택하고 bottom_nav_menu.xml 파일 만들기
- bottom_nav_menu.xml 파일에 실제로 표시될 항목들 정의
- 하나의 아이템이 하나의 버튼 역할
- android:id는 해당 버튼의 ID라고 생각하면 됨
- android:icon 은 해당 버튼의 아이콘이라고 생각하면 됨
- android:title 은 해당 버튼을 나타내는 Text 부분
- 하나의 아이템이 하나의 버튼 역할
- activity_main.xml 파일에 보여질 화면인 FrameLayout 작성하고 아래에 BottomNavigationView 작성
- 아이템이 4개 이상이면 텍스트는 보이지 않고 이미지만 보임. 텍스트도 보여주려면 BottomNavigationView안에 app:labelVisibilityMode="labeled" 적어줘야 함
- 각 아이템들을 눌렀을 때 보여질 Fragment 파일들 생성
- MainActivity에서 코드 작성
// MainActivity 코드
class MainActivity : AppCompatActivity() {
private val fl: FrameLayout by lazy {
findViewById(R.id.main_frm)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val main_bnv = findViewById<BottomNavigationView>(R.id.main_bnv)
//supportFragmentManager.beginTransaction().add(R.id.fl_con, NaviHomeFragment()).commit()
main_bnv.setOnItemSelectedListener { item ->
changeFragment(
when (item.itemId) {
R.id.navigation_home -> {
main_bnv.itemIconTintList = ContextCompat.getColorStateList(this, R.color.purple_200)
main_bnv.itemTextColor = ContextCompat.getColorStateList(this, R.color.purple_200)
NaviHomeFragment()
// Respond to navigation item 1 click
}
R.id.navigation_question -> {
main_bnv.itemIconTintList = ContextCompat.getColorStateList(this, R.color.purple_200)
main_bnv.itemTextColor = ContextCompat.getColorStateList(this, R.color.purple_200)
NaviQuestionFragment()
// Respond to navigation item 2 click
}
R.id.navigation_walk -> {
main_bnv.itemIconTintList = ContextCompat.getColorStateList(this, R.color.purple_200)
main_bnv.itemTextColor = ContextCompat.getColorStateList(this, R.color.purple_200)
NaviWalkFragment()
// Respond to navigation item 3 click
}
R.id.navigation_sale -> {
main_bnv.itemIconTintList = ContextCompat.getColorStateList(this, R.color.purple_200)
main_bnv.itemTextColor = ContextCompat.getColorStateList(this, R.color.purple_200)
NaviSaleFragment()
// Respond to navigation item 3 click
}
else -> {
main_bnv.itemIconTintList = ContextCompat.getColorStateList(this, R.color.purple_200)
main_bnv.itemTextColor = ContextCompat.getColorStateList(this, R.color.purple_200)
NaviMypageFragment()
}
}
)
true
}
main_bnv.selectedItemId = R.id.navigation_home
}
private fun changeFragment(fragment: Fragment) {
supportFragmentManager
.beginTransaction()
.replace(R.id.main_frm, fragment)
.commit()
}
}
<23/01/12>
이전 포스트에서 Edittext에 값이 있고 Spinner 3개가 모두 선택되었을 때 다음페이지로 넘어가는 버튼을 활성화하는 문제를 해결하지 못했었는데 오늘 해결하였다.
if(validEditText==true&&validSpinner1==true&&validSpinner2==true&&validSpinner3==true) {
next_page_btn.isEnabled
next_page_btn.isClickable
next_page_btn.setBackgroundResource(R.drawable.start_button)
}
기존에는 변수 4개를 상단에 false로 선언하고 Edittext의 경우 텍스트가 입력되면 true로, Spinner의 경우 리스트의 아이템이 선택되었을 때 true로 설정해 위의 코드를 통해 버튼 활성화하고자하였으나 실패하였다.
로그 찍으면 값이 잘 나오는데 왜 안되는지는 모르겠다.
위의 코드를 onCreate() 하단에 작성하였었는데 이번에는 함수를 따로 밖에 적어주었다.
private fun checkValid(v1:Boolean, v2:Boolean, v3:Boolean, v4:Boolean){
Log.d("Valid", (v1 && v2 && v3 && v4).toString())
if(v1 && v2 && v3 && v4){
next_page_btn.isEnabled = true
next_page_btn.isClickable = true
next_page_btn.setBackgroundResource(R.drawable.start_button)
} else {
next_page_btn.isEnabled = false
next_page_btn.isClickable = false
next_page_btn.setBackgroundResource(R.drawable.disabled_button)
}
제일 하단에 다음과 같이 valid를 체크하는 checkValid 함수를 만들고 체크 항목이 4개이므로 v1~v4로 변수를 주었다.
변수 타입은 Boolean이고 v1~v4가 모두 true이면 버튼을 활성화&클릭 가능하게하고 버튼 색상을 바꿔주었다.
else문을 통해 하나라도 false이면 버튼을 비활성화&클릭 불가능하게하고 버튼 색상을 불가능한 버튼 색상으로 설정하였다.
그리고 위의 checkValid 함수를 각각의 함수 안에 다 선언해주었다.
editText의 경우 TextWatcher 내의 afterTextChanged 함수 안에 checkValid 함수를 작성하고 validEditText 값을 editText가 비어있지 않을 때 true로 설정해주었다.
스피너의 경우 onItemSelected 함수 안에 적어주었는데 position == 0인 아이템은 힌트 아이템이므로 position == 0 일 때는 validSpinner = false로, else 일 때 true로 설정해주고 checkValid 함수를 작성하였다.
onNothingSelected는 아무것도 선택되지 않은 경우이므로 validSpinner = false로 두었다.
viewBinding.dogNameEdtText.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(editable: Editable) {
validEditText = editable.isNotEmpty()
checkValid(validEditText, validSpinner1, validSpinner2, validSpinner3)
}
viewBinding.breedSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(parent: AdapterView<*>, view: View, position: Int, id: Long) {
when(position) {
0 -> {
validSpinner1 = false
}
else -> {
validSpinner1 = true
Log.d("스피너1", "$validSpinner1")
}
}
checkValid(validEditText, validSpinner1, validSpinner2, validSpinner3)
}
override fun onNothingSelected(p0: AdapterView<*>?) {
validSpinner1 = false
}
}
viewBinding.dogGenderSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(parent: AdapterView<*>, view: View, position: Int, id: Long) {
when(position) {
0 -> {
validSpinner2 = false
}
else -> {
validSpinner2 = true
Log.d("스피너2", "$validSpinner2")
}
}
checkValid(validEditText, validSpinner1, validSpinner2, validSpinner3)
}
override fun onNothingSelected(p0: AdapterView<*>?) {
validSpinner2 = false
}
}
viewBinding.dogAgeSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(parent: AdapterView<*>, view: View, position: Int, id: Long) {
when (position) {
0 -> {
validSpinner3 = false
}
else -> {
validSpinner3 = true
Log.d("스피너3", "$validSpinner3")
}
}
checkValid(validEditText, validSpinner1, validSpinner2, validSpinner3)
}
override fun onNothingSelected(p0: AdapterView<*>?) {
validSpinner3 = false
}
}
이렇게 함수를 정의하니까 원하던대로 모든 조건이 충족되었을 때 버튼이 활성화되었다.
기존이랑 뭐가 다른지는 아직 잘 모르겠어서 공부가 더 필요할 것 같다.