대기업을 향한 디벨롭 블로그

팝업메뉴2장 팝업메뉴 꾸미기 커스텀 ContextThemeWrapper (상세설명) 본문

나는안드로이드개발자

팝업메뉴2장 팝업메뉴 꾸미기 커스텀 ContextThemeWrapper (상세설명)

MHY.PRO 2022. 6. 19. 16:11

팝업메뉴1장에서 팝업메뉴를 적용하기 , 클릭리스너까지 달아보았다. 

2장에서는 팝업메뉴를 커스텀해볼거다.

https://mhypro.tistory.com/44

 

팝업메뉴1 적용하기 , 메뉴 아이템 클릭리스너

팝업메뉴를 커스텀으로 한번 만들어보자. 먼저 버튼을 만들어주었다. 버튼을 클릭시 팝업메뉴가 나오도록 하겠다. 그리고 res폴더에 Android Resource Directory를 만들어주는데 type을 menu로 만들어 주

mhypro.tistory.com

1장에 이어서 할거다. 

 

먼저 

themes.xml 파일안에 밑에있는 style을 넣어주자

<style name="PopupStyle" parent="@style/Widget.AppCompat.PopupMenu">
    <item name="android:popupBackground">#5C000000</item>
</style>

추가하셈

설명하겠다 . style을 하나 만들어준건데 

name은 PopupStyle로 만들어줬고 , 변수이름이라고 생각하면된다 .

parent는 부모요소다. 부모요소는 PopupMenu로 지정한다. 우리는 PopupMenu를 커스텀하는거다. 그리고 이걸PopupMenu.Overflow이 속성도있는데 이건 누르면 누른버튼이 가려진다 한번 해봐라

style태그안에 item으로 name="android:popupBackground"를 적은게 바로 팝업의 배경을 바꿀 수 있다. 태그안에 색을 넣어주거나 @drawable파일을 첨부해도 된다. 

팝업메뉴 background에 적용할 새로만든 set_corner.xml

 

나는 drawable파일을 따로 만들어서 적용해보겠다. 

테두리에 곡선을 주는 속성을 넣어주고 배경색으로는 #F6E08D색상을 넣어주었다.  그리고 drawable파일을 만들었던

<style name="pops" parent="@style/Widget.AppCompat.PopupMenu">
    <item name="android:popupBackground">@drawable/set_corner</item>
</style>

위에코드 적용 themes.xml

이렇게 넣어주면 팝업배경의 속성을 설정해 준거다. 

style을 만들어줬으니 이제 적용을 해보자.  MainActivy로 돌아와

PopMenu를 생성할때 추가로 style을 추가해서 넘겨주면 적용이된다. 여기서 5개의 인자를 넘기는데 , 설명해주겠다. 

첫번째인자(context) context를 넘겨주는데 팝업메뉴가 실행될 컨테스트를 이용해 현재 테마와 , 리소스를 엑세스한다.

두번째인자(anchor) View를 넘겨준다 여기서 View는 it으로 넘겨주는데 it이 바로 optionBtn이다. 즉 버튼아래에 팝업을 나타낼거다 라는뜻이다. 

*세번재인자(gravity) 이 인자는 anchor인 View 즉 optionBtn과 팝업메뉴를 정렬하기 위한 값이다. 위에선 Gravity.CENTER를 넣어줬다.  https://developer.android.com/reference/android/view/Gravity.html?hl=en 

 

Gravity  |  Android Developers

android.net.wifi.hotspot2.omadm

developer.android.com

여기서 참고하여 값들을 넣어보면 팝업메뉴를 이리저리 배치할 수 있다.

네번째인자(popupStyleAttr) 팝업메뉴의 기본값을 제공하는 style을 참조한다. 기본값을 안쓰면 0으로 한다. 내생각에 custom으로 꾸며준다면 0으로 하는게 맞는거같다. 

다섯번째인자(popupStyleRes) 이곳에 바로 만들었던 style태그의 name을 넣어주면된다. 스타일리소스를 넣어서 적용시키는거다. 그리고 중요한건 네번째인자가 0이어야 사용할 수 있다. 이것또한 사용하지 않는다면 0으로 한다.

 

이렇게 인자 하나하나 설명해주었다. 그밑에는 팝업을 inflate해주어 R.menu.pop_menu가 XML이고 그뒤에 설정했던 popup.menu를 넣어 셋팅완료!

 

그리고 실행을 해보면 

짠 이렇게 둥근모서리와 노란배경색을 설정해주었다. 

 

하지만 여기서 끝난다면 아쉽다. 배경을 꾸며주었지만 , 글자색이나 폰트 등 바꾸고 싶은게 더 있다. 한번 바꿔보자.

나는 옵션메뉴의 context를 새롭게 만들어서 적용해주는 방식을 사용했다.

 

먼저 또 하나의 style을 만들어주자 이건 이제 메뉴안에있는 텍스트의 속성을 변경시킬거다. 

themes.xml 추가함 텍스트컬러와 폰트(폰트는다운받음)

이름이 custom_theme인 style을 만들어 주었다. 이 속성들을 멕일거다. 

MainActivty로 돌아와서 ->

val themeWrapper = ContextThemeWrapper(this, R.style.custom_theme)

MainActivity.kt

PopupMenu를 만들때 첫번째 인자로 context를 넣어주는데 ContextThemeWrapper를 이용하여 내가 지정한테마를 적용하여 새 컨텍스트를 만들어낸거다.

ContextThemeWrapper()메서드는 테마와 기본 컨텍스트가 없는 새 컨텍스트를 만들어준다. 첫번째 인자base로 this를 넣어주고 , 두번째 인자로 themeResId인 내가 만든 style 리소스를 넣어주면된다.

 

그리고 PopupMenu로 인스턴스할때 첫번째 인자로 새로만든 컨테스트를 넣어주면 끝! 

 

완성 

 

그리고 배경을 설정해준 R.style.pops에 폰트와 글자색 속성을 넣어 합쳐서 새로운컨텍스트를 만들때 테마로 넣어준다.

밑에 최종코드를 올리겠다.

 

class MainActivity : AppCompatActivity() {
    private val binding by lazy{
        ActivityMainBinding.inflate(layoutInflater)
    }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(binding.root)

        binding.optionBtn.setOnClickListener {
//            R.style.pops를 테마로 새컨텍스트 생성
            //*변경된코드 기존에있던 custom_theme안에있는 코드를 pops에 넣어 통합시킴
            val newTheme = ContextThemeWrapper(this , R.style.pops)
            val popup = PopupMenu(newTheme , it, Gravity.CENTER , 0, R.style.pops)
            popup.menuInflater.inflate(R.menu.pop_menu,popup.menu)

            popup.menu.add(0,1,3,"add생성 option 추가됨1")
            popup.menu.add(0,2,2,"add생성 option 추가됨2")
            popup.menu.add(0,3,1,"add생성 option 추가됨3")
            popup.show()
            popup.setOnMenuItemClickListener{
                Toast.makeText(this , "${it} 클릭됨" , Toast.LENGTH_SHORT).show()
                true
            }
        }
    }

}

액티비티

<!-- 변경된 내용 pops에다가 폰트와 컬러를 넣어 합쳐주었다. -->
    <style name="pops" parent="@style/Widget.AppCompat.PopupMenu">
        <item name="android:popupBackground">@drawable/set_corner</item>
        <item name="android:textColor">#0F00FF</item>
        <item name="android:fontFamily">@font/wake</item>
<!--        <item name="android:overlapAnchor">true</item> 버튼과 팝업창이 겹치는지 true Or false-->
    </style>

엑스엠엘

 

여기까지 팝업메뉴 커스텀해봤습니다.

제일많이 참고한거는 android delvelopers를 제일많이 참고하였습니다.