Android/Kotlin

<정리> 메모 앱 만들기 3일차

re트 2023. 12. 19. 19:43
728x90

오늘은 뭐 많이 만지지는 않았다.

 

1. 툴바 레이아웃 수정

툴바 타이틀을 나는 레이아웃 상에서 만들었고 그 타이틀의 의미는 카테고리였다. 그래서 카테고리를 변경할 수 있는 이미지 뷰(버튼)를 추가했다. 사용할 이미지는 기본적으로 제공하는 위,아래 화살표를 가져왔다.

<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    android:background="@color/white"
    app:titleTextColor="@color/black">
    <!-- Toolbar 내용은 대부분 코드 상에서 채움 -->

    <LinearLayout
        android:id="@+id/linearlayout_toolbar_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_vertical"
        android:orientation="horizontal">

        <TextView
            android:id="@+id/tv_category_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="전체"
            android:textColor="@color/black"
            android:textSize="20sp" />

        <ImageView
            android:id="@+id/iv_btn_arrow"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginHorizontal="15dp"
            android:src="@drawable/ic_arrow_down" />
    </LinearLayout>

    <EditText
        android:id="@+id/edit_toolbar_search"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@android:color/transparent"
        android:hint="메모 검색"
        android:visibility="gone" />
</androidx.appcompat.widget.Toolbar>

 

2. 메인 레이아웃 수정

여기도 약간 수정이 들어갔는데 그 이유는 툴바 아래에 카테고리 목록을 띄우기 위한 공간을 만들기 위해서였다.

하지만 생각이 잘 나지 않더라

지금 레이아웃에서는 숨겨놨다가 보이는 걸로 하면 공간을 차지해서 안 될 거고  bottomsheet를 수정해서 하는 것도 원하는 방식은 아니었다. 팝업도 마찬가지고...

그러다가 튜터님께 갔는데 바로 가능성이 보이는 방법을 제시해주시더라

바로 레이아웃을 ConstraintLayout으로 변경하는 거였다.

이렇게 하면 위로 덮을 수 있겠구나...!

바로 깨달음을 얻어서 감사합니다 박고 돌아와서 진행시켰다.

기본 visibility는 gone으로 해놓고 코드상에서 변경시키도록 했다.

튜터님이 마지막에 'RelativeLayout은 쓰지 마세요~'라고 하셨는데 아직 이유는 잘 모르겠지만 쓰고 있던 RelativeLayout이 보여 이것도 수정했다.

<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/white"
    android:fitsSystemWindows="true"
    tools:context=".MainActivity">

    <!-- 메인 화면 -->
    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <!-- Toolbar 레이아웃 가져오기 -->
        <include
            android:id="@+id/toolbar_main"
            layout="@layout/toolbar_layout"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <!-- 수평 경계선 -->
        <View
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:background="#979797"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/toolbar_main" />

        <LinearLayout
            android:id="@+id/linearlayout_category_select"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:background="@color/white"
            android:gravity="center_vertical"
            android:orientation="horizontal"
            android:visibility="gone"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/toolbar_main">

            <Button
                android:id="@+id/btn_category_all"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginHorizontal="15dp"
                android:text="전체" />

            <Button
                android:id="@+id/btn_category_favorite"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginHorizontal="15dp"
                android:text="좋아요" />
        </LinearLayout>
    </androidx.constraintlayout.widget.ConstraintLayout>
    
    <!-- 네비게이션 드로어 -->
    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/navigation_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:background="@color/white"
        android:fitsSystemWindows="true"
        android:orientation="vertical">

        <include
            android:id="@+id/drawer_header"
            layout="@layout/drawer_header_layout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <include
            layout="@layout/drawer_body_layout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/drawer_header"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/drawer_header" />

        <include
            android:id="@+id/include"
            layout="@layout/drawer_footer_layout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</androidx.drawerlayout.widget.DrawerLayout>

 

3. 메인 액티비티 코드 추가

여기서 추가한 건 레이아웃에서 추가한 뷰에 대한 이벤트다.

카테고리 목록 표시 및 버튼 이벤트, 뷰 텍스트 갱신 정도로 그렇게 많이 하지는 않았다.

하면서 뷰 객체들을 모두 by lazy로 변경했고 onClickListener의 내용이 겹치는 것들은 묶었다.

이외에도 중복되는 코드들은 함수로 최대한 묶었다.

그리고 editToolbarSearch 객체는 visibility 속성을 썼었는데 isVisible로 변경했다. 그렇게 변경함으로써 다른 뷰 객체들과 같은 Boolean 값을 공유할 수 있게 되어 간결해졌다.

class MainActivity : AppCompatActivity() {

    // DrawerLayout 변수
    private val drawerLayout: DrawerLayout by lazy { findViewById(R.id.drawer_layout) }

    // Toolbar 변수
    private val toolbar: Toolbar by lazy { findViewById(R.id.toolbar_main) }

    // 툴바 레이아웃 변수
    private val linearLayoutToolbarTitle: LinearLayout by lazy { findViewById(R.id.linearlayout_toolbar_title) }

    // 검색창 입력창 변수
    private val editToolbarSearch: EditText by lazy { findViewById(R.id.edit_toolbar_search) }

    // 카테고리 목록 표시 버튼 변수
    private val ivBtnArrow: ImageView by lazy { findViewById(R.id.iv_btn_arrow) }

    // 카테고리 목록 레이아웃 변수
    private val linearLayoutCategorySelect: LinearLayout by lazy { findViewById(R.id.linearlayout_category_select) }

    // 현재 카테고리 변수
    private val tvCategoryName: TextView by lazy { findViewById(R.id.tv_category_name) }

    // 전체 카테고리 버튼 변수
    private val btnCategoryAll: Button by lazy { findViewById(R.id.btn_category_all) }

    // 좋아요 카테고리 버튼 변수
    private val btnCategoryFavorite: Button by lazy { findViewById(R.id.btn_category_favorite) }

    // 클릭 확인용 변수
    var isClicked = false

    // 뒤로가기 버튼 콜백 함수
    private val callback = object : OnBackPressedCallback(true) {
        override fun handleOnBackPressed() {
            // 네비게이션뷰가 열려있다면
            if (drawerLayout.isDrawerOpen(GravityCompat.START)) {
                drawerLayout.closeDrawer(GravityCompat.START)
            } else if (isClicked) {
                checkSearchClick(false, R.drawable.ic_menu)
            } else {
                finish()
            }
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        initView()
    }

    private fun setCategoryButtonOnClickListener(button: Button) {
        button.setOnClickListener {
            if (tvCategoryName.text.toString() != button.text.toString()) {
                tvCategoryName.text = button.text.toString()
            }
            setCategoryMenu()
        }
    }

    private fun setShowCategoryListOnClickListener(view: View) {
        view.setOnClickListener {
            setCategoryMenu()
        }
    }

    private fun setCategoryMenu() {
        with(linearLayoutCategorySelect) {
            if (!isVisible) {
                ivBtnArrow.setImageResource(R.drawable.ic_arrow_up)
            } else {
                ivBtnArrow.setImageResource(R.drawable.ic_arrow_down)
            }
            linearLayoutCategorySelect.isVisible = !linearLayoutCategorySelect.isVisible
        }
    }

    private fun initView() {
        // 액션바에 Toolbar 세팅
        setSupportActionBar(toolbar)
        supportActionBar?.setDisplayShowTitleEnabled(false)
        // 상태바의 아이콘과 배경색 변경
        window.apply {
            statusBarColor = Color.WHITE
            WindowInsetsControllerCompat(this, this.decorView).isAppearanceLightStatusBars = true
        }

        // 액션바에 뒤로가기 버튼을 네비게이션 메뉴를 위한 이미지로 변경
        supportActionBar?.setDisplayHomeAsUpEnabled(true)
        supportActionBar?.setHomeAsUpIndicator(R.drawable.ic_menu)

        // 뒤로가기 버튼 콜백 함수 추가
        this.onBackPressedDispatcher.addCallback(this, callback)

        // 사용자 슬라이드 액션 막기
        drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_OPEN)
        drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)

        setShowCategoryListOnClickListener(ivBtnArrow)
        setShowCategoryListOnClickListener(linearLayoutToolbarTitle)

        setCategoryButtonOnClickListener(btnCategoryAll)
        setCategoryButtonOnClickListener(btnCategoryFavorite)
    }

    // 액션바 메뉴 생성
    override fun onCreateOptionsMenu(menu: Menu?): Boolean {
        menuInflater.inflate(R.menu.menu, menu)
        return true
    }

    override fun onPrepareOptionsMenu(menu: Menu?): Boolean {
        if (isClicked) {
            changeToolbarStatus(menu, false)
        } else {
            changeToolbarStatus(menu, true)
        }
        return super.onPrepareOptionsMenu(menu)
    }

    // 액션바 메뉴 선택시 호출
    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        when (item.itemId) {
            // 홈 버튼(내비게이션 메뉴 버튼)
            android.R.id.home -> {
                if (isClicked) {
                    checkSearchClick(false, R.drawable.ic_menu)
                } else {
                    drawerLayout.openDrawer(GravityCompat.START)
                }
            }
            // 검색 버튼
            R.id.btn_search -> {
                checkSearchClick(true, R.drawable.ic_btn_back)
            }
            // BottomSheet 버튼
            R.id.btn_more -> {
                val bottomSheet = BottomSheet()
                bottomSheet.show(supportFragmentManager, bottomSheet.tag)
            }
        }

        return super.onOptionsItemSelected(item)
    }

    fun checkSearchClick(flag: Boolean, btnImg: Int) {
        isClicked = flag
        supportActionBar?.setHomeAsUpIndicator(btnImg)
        invalidateOptionsMenu()
    }

    private fun changeToolbarStatus(menu: Menu?, flag: Boolean) {
        menu?.forEach {
            it.isVisible = flag
        }
        linearLayoutToolbarTitle.isVisible = flag
        editToolbarSearch.isVisible = !flag
    }
}

(주석은 나중에 달게요...ㅎㅎ)

 

<결과화면>

 

반응형