TIL 0709~0714

오리너구리·2024년 7월 15일
0

TIL

목록 보기
46/48
post-thumbnail

안드로이드 숙련주차 제공 강의 학습

  • 데이터 바인딩 공부하기< 실무 필수적으로 쓰지는 않아서

1. View binding

  • find VIew By Id를 대체하는 코드

  • 모듈에서 viewBinding을 설정하면 각 모듈에 있는 xml 레이아웃 파일의 결합 클래스를 생성함

  • binding 클래스의 인스턴스에는 상응하는 레이아웃에 ID가 있는 모든 뷰의 직접 참조가 포함된다.

findViewById와의 차이점

  1. Null safety
    • 뷰바인딩은 직접 참조를 생성하므로 유효하지 않은 view ID로 인한 null예외가 발생하지 않는다.
  2. Type safety
    • 타입이 맞지 않아 발생하는 오류를 방지할 수 있음

사용법

  1. build 모듈 파일에 buildFeatures 안에 viewBinding = true 적어줌
  2. 전역 변수로 binding 지연초기화로 만들어주고
  3. onCreate 안에서 binding 초기화 해줌
private lateinit var binding : ActivityMainBinding

override fun onCreate(savedInstanceState : Bundle?) {
		super.onCreate(savedInstanceState)
		binding = ActivityMainBinding.inflate(layoutInflater)
		val view = binding.root
		setContentView(view)
}
  1. binding.가져올애아이디 로 접근해서 사용가능

*주의사항

ViewBinding은 자동으로 결합 클래스를 생성하는데, 해당 객체의 이름은 레이아웃 이름에 Binding을 붙여서 만들어짐

Ex) activity_main.xml → ActivityMainBinding

fragment_home.xml → FragmentHomeBinding

궁금한 점

  1. findViewById 보다 안정성이 높고 간단한 코드인데 처음부터 뷰바인딩을 안하고 처음에는 findViewById 방식을 먼저 배우는 이유?

    그냥 원래 findViewById 방식이 원래 있던 방식이고ViewBinding이 비교적 최신? 기술이라서 그 .. 코딩 역사..?인 이유로 전부 이해해야하기때문인지?

    아니면 findViewById 방식을 사용해보면서 먼저 내가 가져오려는 객체가 어떤타입인지 인지하고 가져다 쓰는 연습을 위한거였는지?

    아니면 따로 내가 생각하지 못한 이유가 있는지!?

    → 튜터님 답변 : 뷰 바인딩이 최신 기술이라서 혼자서 구글링하면서 다른 사람 코드를 참고할 때findViewById를 사용한 방식의 코드를 봐야할 수 도 있는데, 그 때 이해를 할 수 있어야하기 때문에 그렇다!

    둘 다 익숙하게 하기위해서 처음에는 옛날방식인 findViewById를 배워서 사용해봤고, 이제부터는 ViewBinding를 사용할것~

  2. Type safety

    이미지 뷰(ImageView)에 텍스트를 설정하려고 하면 오류가 발생할 텐데, 뷰 바인딩을 사용하면 이런 실수를 할 가능성이 없어집니다. 즉, 이미지 뷰는 이미지 뷰로, 텍스트 뷰는 텍스트 뷰로만 사용되게 하여, 잘못된 타입 사용으로 인한 오류가 발생하지 않도록 보장합니다.

    이 부분이 이해가 안댄다!

    어차피 findViewById를 사용해도 <>안에 타입 잘못 쓰면 오류로 안가져와지는게 아닌가!?

    아니면 imageView에 . 찍고 텍스트뷰의 속성 적어도 안뜨지 않았나!?!?!?!

    → 튜터님 답변 : 안드로이드 스튜디오 업데이트로 이제는 타입 잘못적을 때 빨간줄이 뜨지만 옛날에는 안떴다!

    그래도 코드가 복잡해지다보면 휴먼에러가 발생할수도 있기때문에 타입 세이프티는 뷰 바인딩의 장점이 될 수 있을듯!

2. Adapter View

ViewGroup을 상속하는 추상클래스.

여러개의 항목을 나열하고 선택할 수 있는 기능을 제공하는 뷰

대용량의 데이터 세트를 효율적으로 표시할 수 있게 하는 것이 주 목적

ListVIew(수직 나열)와 GridView(격자 형태 나열), Spinner(드롭다운리스트?) 등이있음

Adapter View를 사용하기 위해 필요한 요소 3가지

  1. Data (빔프로젝터안에 넣은 영화 폴더)
  2. Adapter (빔프로젝터)
  3. AdapterView (빔 프로젝트 스크린?)

Adapter

  • 데이터를 관리하며 데이터 원본과 어댑터 뷰 사이의 중계 역할을하는 인터페이스
  • AdapterView 에서 Adapter의 getCount() 메서드를 통해서 어댑터가 관리하는 데이터 항목의 총 개수 반환
  • AdapterView 에서 Adapter의 getView() 메서드를 통해서 화면에 실제로 표시할 항목 뷰를 얻고, 표시함

어댑터 인터페이스를 상속하는 어댑터 클래스들.

Adapter 종류

  1. BaseAdapter
  2. ArrayAdapter
    • List
  3. CursorAdapter
    • Data Base
  4. SimpleAdapter

ArrayAdapter 객체 생성하는 방법

  • ArrayAdapter(context : Context , resource : Int, textViewResourceId : Int, objects : T<>)
  • → ArrayAdapter(컨텍스트,

ListView

  • AdapterView의 대표 위젯
  • 여러 항목을 수직으로 나열하여 표시

GridView

  • AdapterView의 대표 위젯 2
  • 여러 항목을 2차원 스크롤 가능한 그리드에 표시

궁금한점

  1. ListView 만들어보니까 알아서 스크롤이 가능한데 스크롤뷰를 상속받고있는지 알아보기 , 스크롤외의 뭐 어떻게 구성되어있는데 이렇게 되는건지 궁금함

    → ListView는 AdapterView 의 하위클래스, ScrollView는 ViewGroup의 하위클래스. 따로 연관이 있지는 않은듯.

  2. ListView는 LinearLayout 또는 다른 레이아웃의 자식뷰로 들어가야하는지

    → 꼭 그럴필요 없다.

  3. ArrayAdapter 생성할 때 리소스 ID는 완전 정해져있는건지? 커스텀(가능한지)

  4. android.R.layout.simple_list_item_3 하면 세개의 텍스트 뷰로 구성된 레이아웃 이 되는건지?

    → 얘네가 그 안드로이드 SDK에서 제공하는 기본적인 레이아웃리소스? 인데 얘네 종류가 얼마나되는지 뭐 어떤식으로 구성되어있는지를 문서에서 찾을 수가 없음 어떻게 찾아야될지 여쭤보기

    → 태영님이 찾아주셔서 공부완료

  5. ArrayAdapter(Context context, int resource, int textViewResourceId, T[] objects) 에서는 컨텍스트, 리소스, 텍스트뷰리소스아이디, 데이터배열 이렇게 4개 같은데 생성 예제보면 왜 컨텍스트, 리소스아이디, 데이터배열 세개만 들어가지?!

    → 공식문서 들어가서 확인해보니까 여러가지 생성자를 제공함

더 알아볼 부분

  1. 그리드 뷰 속성 각각 어떻게 적용하는지 다 이해하기

    1. columnWidth
    2. numcolumns
    3. VerticalSpacing
    4. stretchMode
  2. position의 정확한 정의?

    → item의 인덱스?

    → 그럼 왜 굳이 index라고 안하고 position이라고 부름?

  3. layoutParams 가 뭔지 찾아보기

오늘 할일

  • 코드카타 56번
  • 숙련주차 강의 끝까지 듣기

코드카타

잘 풀었다

chunked라는 함수를 배웠당


숙련주차 강의

Fragment

액티비티 위에서 동작하는 모듈화된 UI

Framgment 생명주기

액티비티의 생명주기와 비슷한데 액티비티와 연결 관련된 생명주기가 더 추가된 느낌

  1. onAttach()
  2. onCreate()
  3. onCreateView()
  4. onActivityCreated()
  5. onStart()
  6. onResume()
  7. onPause()
  8. onStop()
  9. onDestroyView()
  10. onDestroy()
  11. onDetach()

Fragment를 액티비티에 추가하는 방법

  1. 액티비티 xml 파일에 태그 만들어주고 크기, 배치 지정, android:name 사용해서 인스턴스화할 Fragment 클래스 지정
  2. 액티비티 kt 파일에서 supportFragmentManager 사용해서 프래그먼트 추가
  • supportFragmentManager
    supportFragmentManager.commit {
                replace(R.id.frameLayout, frag)
                setReorderingAllowed(true)
                addToBackStack("")
            }
    • supportFragmentManager : 사용자 상호작용에 응답해 Fragment를 추가하거나 삭제하는 등의 작업을 하게 해주는 도구
    • replace : 어느 프레임 레이아웃에 띄울 것인지, 어떤 프래그먼트인지 지정
    • setReorderingAllowed : 애니메이션 전환이 올바르게 작동하도록 트랜잭션과 관련된 fragment의 상태 변경을 최적화
    • addToBackStack : 뒤로가기 버튼 클릭 시 다음 액션

Fragment의 데이터전달

  1. Activity 에서 Fragment로 데이터 전달

    1. Fragment : newInstance()메서드로 받을 데이터 정의하기
    2. Activity : newInstance() 호출해서 전달할 데이터 넣어주기
    3. Fragment : 받은 데이터 사용하기
  2. Fragment 에서 Fragment로 데이터 전달

    1. 받는 Fragment : newInstance() 메서드에 받을 데이터 정의하기
    2. 보내는 Fragment : 데이터 보내는 event 시 받는 Fragment의 newInstance()호출해서 전달할 데이터 넣어주기
  3. Fragment 에서 Activity로 데이터 전달

    꼭 인터페이스를 정의해서 전달해야함. 그냥은 안됨

    1. Interface로 FragmentDataListenter를 정의
    2. Activity : 정의한 인터페이스를 상속받아서 구현함 (데이터 받아서 할 행동 정의)
    3. Fragment : 데이터 전달받을 Activity에서 인터페이스를 구현했는지 확인 후 리스너에서 인터페이스의 함수(데이터전달) 를 호출해서 전달할 데이터를 넣어줌

알아볼 것 :

Bundle 이무엇인가

requireActivity()는 무엇인가

다이얼로그

사용자에게 결정을 내리거나, 추가정보를 입력하라는 메세지를 띄우는 작은 창

화면을 가득 채우지 않음

보통 사용자가 다음으로 진행하기 전에 조치를 취해야하는 모달 이벤트에서 사용

Alert Dialog 다이얼로그 기본 구조

  1. 제목
    • 선택사항. 컨텐츠 영역에 상세한 메세지, 목록 또는 맞춤 레이아웃이 채워져 있는 경우에 사용
    • 단순한 메세지, 질문을 나타내는 경우 제목은 없어도 ㄱㅊ
  2. 컨텐츠 영역
    • 메세지, 목록 또는 다른 맞춤 레이아웃을 표시
  3. 작업 버튼
    • 대화 상자 하나에 작업 버튼이 세개를 초과하면 안됨

알림

앱의UI와 별도로 사용자에게 앱과 관련한 정보를 보여주는 기능

알림을 터치하면 해당 앱을 열 수 있음

플로팅 버튼 이용해서 스크롤 조절

구현해야할 기능들

  • 스크롤을 최상단으로 이동시키는 플로팅 버튼 기능 추가
  • 플로팅 버튼은 스크롤을 아래로 내릴 때 나타나며, 스크롤이 최상단일때 사라집니다.
  • 플로팅 버튼을 누르면 스크롤을 최상단으로 이동시킵니다.
  • 플로팅 버튼은 나타나고 사라질때 fade 효과가 있습니다.
  • 플로팅 버튼을 클릭하면(pressed) 아이콘 색이 변경됩니다.

플로팅 버튼 디자인

  1. 예제랑 최대한 비슷하게 만들기 위해서 일단 일러스트로 아이콘 하나 그려줌

  2. xml에 플로팅액션버튼을 추가해주고 디자인을 비슷하게 만들어줌

    • 기본 모양 바꾸기 내가 적용한 테마에서는 버튼이 기본 모양이 원형이아니고 모서리 둥근 네모 처럼 생김
      1. drawable에 shape_floatbtn 이라는 파일 하나 만들어서 원 모양 xml을 하나 만들어줌

        <?xml version="1.0" encoding="utf-8"?>
        <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
            <solid android:color="@color/white"/>
        </shape>
      2. floatingButton의 background와 shapeAppearance에 1번에서 만든 xml파일을 적용해줌

        둘 중 하나 속성을 없애면 바로 네모가 되어버림 ;; 테마에 기본 적용된 모양이 네모라서 그런 것 같은데 테마에서 스타일을 변경해주는게 더 좋은 방법일 수도 있을듯

        android:background="@drawable/shape_floatbtn"
        app:shapeAppearance="@drawable/shape_floatbtn"
    • 클릭시 색상 변경해주기
      1. res 폴더에 color 폴더 하나 만들어주고 selector로 android : state_pressed 에 true/false 값 줘서 만들어줌!

        <selector xmlns:android="http://schemas.android.com/apk/res/android">
            <item android:color="@color/white" android:state_pressed="false"/> // 버튼 안누른 상태 일때 색 지정
            <item android:color="#D3D3D3" android:state_pressed="true"/> //버튼 누른 상태 일 때 색 지정
        </selector>
      2. backgroundTint 속성에 정의해준 xml파일 넣어주기

        android:backgroundTint="@color/selector_floating_btn_color"
    • 기본적으로 들어가는 클릭시 색상 애니메이션? 제거 기본적으로 버튼을 누르면 연한 보라색으로 색상 애니메이션이 나오는데 개 열받음 찾아보니 ripple color 라고 함. rippleColor를 투명으로 바꿔줌
      app:rippleColor="@android:color/transparent"

플로팅 버튼 기능

  • 리사이클러 뷰의 스크롤을 내렸을 때 플로팅 버튼이 나오고, 제일 상단에 있을 때는 사라지게 하는데 fadeIn, fadeout 으로 만들기
    1. 일단 사용하기 쉽게 플로팅 버튼을 변수에 담아주고,

      fadeIn과 fadeOut효과는 AlphaAnimation을 사용해서 정의해 줌 (float 형식의 숫자를 넣어주면되고, 첫번째 인자로 시작시의 투명도 두번째 인자로 끝날때의 투명도)

      val floatingBtn = binding.floatingBtn
      val fadeIn = AlphaAnimation(0f, 1f).apply { duration = 300 }
      val fadeOut = AlphaAnimation(1f, 0f).apply { duration = 300 }
      var isTop = true
    2. recyclerView에 addOnScrollListener를 달아줌

      binding.recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener(){
      		override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
      		    super.onScrollStateChanged(recyclerView, newState)
              if (!binding.recyclerView.canScrollVertically(-1)&& newState == RecyclerView.SCROLL_STATE_IDLE) {
                  binding.floatingBtn.startAnimation(fadeOut)
                  binding.floatingBtn.visibility = View.GONE
                  isTop = true
              }else if(isTop){
                  floatingBtn.visibility = View.VISIBLE
                  floatingBtn.startAnimation(fadeIn)
                  isTop = false
              }
         }
      })

      ScrollListener로 스크롤이 변경되는 걸 감지?하게 만들어주고,

      recyclerView가 -1방향 즉 위로 스크롤이 안되고, 현재 상태가 정지한 상태이면,

      플로팅 버튼이 서서히 사라지게 만들어줌.

      그렇지 않을 때에는 플로팅 버튼이 서서히 나타나게 만들어줌!

  • 플로팅 버튼을 클릭하면 스크롤을 맨 위로 이동 시킴
    floatingBtn.setOnClickListener {
    		binding.recyclerView.smoothScrollToPosition(0)
    }
    플로팅 버튼을 클릭했을 때 smoothScrollToPosition 값을 0으로 줘서 최 상단으로 이동하게 해줌!
    • 리사이클러뷰의 스크롤 위치를 변경하는 다양한 메서드들
      • scrollToPosition 주어진 위치로 즉시 스크롤 ( 애니메이션 x)
        recyclerView.scrollToPosition(position)
      • scrollBy 지정된 픽셀 수 만큼 스크롤 (수직 수평 스크롤 모두 가능)
        recyclerView.scrollBy(x,y)
      • smoothScrollBy 지정된 픽셀 수 만큼 부드럽게 스크롤(수직 수평 스크롤 모두 가능)
        recyclerView.smoothScollBy(dx,dy)
      • LinearLayoutManager.scrollToPositionWithOffset 특정 위치에 오프셋을 적용하여 스크롤 (특정 항목을 리스트의 상단 혹은 중단에 배치)
        val layoutManager = recyclerView.layoutManager as LinearLayoutManager
        layoutManager.scrollToPositionWithOffset(position,offset)
      • layoutManager.startSmoothScroll 사용자 정의 스크롤 동작을 구현, 세밀한 제어 가능
        val layoutManager = recyclerView.layoutManager as LinearLayoutManager
        val scroller = object : LinearSmoothScroller(recyclerView.context) {
        		override fun getVerticalSnapPreference() : Int {
        				return SNAP_TO_START
        		}
        }
        scroller.targetPosition = position
        layoutManager.startSmoothScroll(scroller)
profile
오리너구리입니다

0개의 댓글