플로팅버튼(btn_floating)을 눌렀을 때 사진을 가져올 수 있도록 만들기 위해서, findViewById로 UI와 연결해주었다. 이번에도 by lazy를 사용하여 지연초기화 되도록 해주었다.
사진이 잘 가져오는지 확인하기 위해서 SelectImageActivity를 따로 만들어주었다. 플로팅버튼을 누르면 SelectImageActivity로 넘어가도록 명시적인텐트를 사용하였다.
SelectImageActivity에는 액티비티종료(뒤로가기역할)을 할수있도록 btn_back과 이미지선택할 때 사용할 btn_img_upload, 고른 이미지가 저장될 iv_upload를 findViewById로 UI와 연결해주고, ActivityResultLauncher를 사용할 수 있도록 imageLauncher도 선언해주었다.
3.1 imageLauncher에 registerForActivityResult를 사용하여 콜백등록을 해준다. result.data로 전달된 URI를 img_URI변수에 담아 iv_upload.setImageURI(img_URI)로 iv_upload에 저장될 수 있도록 해주었다.
3.2 암시적인텐트를 사용하기위해서, btn_img_upload에 setOnClickListener를 걸어 그 안에 intent를 선언해주고, Intent(Intent.ACTION_PICK)을 저장하였다. 여기서 ACTION_PICK은 데이터를 받아올 때 사용하는 액션으로, 데이터의 실제주소(URI)를 사용한다. +참고로 ACTION_GET_CONTENT는 데이터유형(mimeType)사용한다.
3.3 그 밑에 intent.setType("image/*")을 걸어서 이미지를 가져오도록 범위를 확실히 정해준다. 마지막으로, imageLauncher.launch(intent)를 사용하여 인텐트를 실행한다.
SelectImageActivity와 연결된 activity_select_image는 당근마켓..과 상관없이 내가 임의로 만들었다. 암시적 인텐트를 사용하는 것에 초점을 두었기 때문이다. 똑같이 ConstraintLayout을 큰틀로 사용하고 있으며, 상단바역할을 하는 LinearLayout 밑에는 선택한 사진을 받을 ImageView와 구색을.. 갖추기 위한 상세설명을 등록할 EditText를 두었다.
4.1 상단바는 activity_search에서 사용하던것을 재활용했는데, btn_back버튼은 그대로두고, 검색을 위한 EditText를 일반 TextView로 바꿔서 페이지제목을 작성해주었다. 그리고 상단바 맨 오른쪽에는 암시적인텐트가 연결될 수 있는 이미지 등록 버튼을 만들어주었다. UI 클론 코딩 2에서 사용한 것들을 재활용해서 패딩과 마진 등을 사용하여 위치만 조정해주었다.
4.2 그 밑에 ImageView는 ConstraintLayout의 기능으로 상단바 밑에 위치를 시켰다. 크기는 그냥 보이는 화면에 맞춰서 적절한 크기로 나타날 수 있게 고정해주었다. 사진을 넣었을 때, 크기가.. 남긴하지만 오늘은 암시적인텐트에 목적이 있어서 그냥 두었다.
4.3 EditText창도 ConstraintLayout의 기능으로 부모레이아웃 바닥에 닿도록 위치 시켰다. 마찬가지로 보이는 화면에 맞춰서 적절한 크기로 고정해주었다.
사진을 불러오러면, 기기에 사진이 있어야하니까 에뮬레이터에 사진을 넣어야되는데.. 드로그앤드롭을해도, View> Tool Windows> Device File Explorer에서 Storage를 찾아 그 안의 Pictures 폴더를 찾아서 직접 사진을 넣어줘도 갤러리에서 확인이 되지 않았다.
일단 에뮬레이터의 카메라로 사진을 찍어보니 그 사진은 갤러리에 잘 들어와 있어서, 구글링해보니까 에뮬레이터의 다운로드폴더가 아니고, Storage에서 햄버거모양을 누르면 사이드바 밑에 sdk______x86_64라고 적힌(SDCARD위에 보통 존재한다.) 곳에 사진이 저장되어 있어서 갤러리에 뜨지 않았던 것이었다.
=> 사진이 있는 sdk______x86_64에 들어가서 갤러리에 넣고 싶은 사진을 선택한 후, 옵션메뉴에 있는 MoveTo를 통해 Download폴더로 move 하고 나니까 갤러리에서도 확인이 가능해졌다.
한..2018?년도에 업로드된 유튜브 영상을 보면서.. 갤러리로 연결되는 인텐트를 작성하고 있었는데, 영상에서 StartActivityForResult( )로 intent를 연결하고 있었다. 아무생각없이 따라쳤더니 Deprecated되었다고 줄이 쫙쳐져있길래 보니까 어디서 많이 본 모양... 개인과제에서 썼던 registerForActivityResult의 ActivityResultContracts.StartActivityForResult()에서 그 StartActivityForResult( )인가 보다.
=> 그래서 개인과제 떄 썼던 ActivityResultLauncher<Intent>를 찾아서 변수명만 적절하게 바꿔주고 똑같이 연결했다.
+연결과정에서 intent.setType을 안해줬더니 이미지를 고르는 액티비티로 넘어가지 않았다. 무슨 구글계정을 최소 한개이상 연결해야한다는 오류?만 떴다. setType을 까먹지 말자!ㅎㅎ
이번에는 액티비티..를 넘어간다기보단 이미지를 불러와야하니까 StartActivityForResult( )가 아니고 다른 걸 써줘야한다고 생각했는데, 동영상도 튜터님도 다 StartActivityForResult( )를 사용하셔서 나도 그대로 사용했더니 잘 되긴 잘 되었다. 사실 다른거 붙여봤다가 빨간줄만 보고 삭제했다. 다른 것을 쓸 일이 있으려나? 싶다.
registerForActivityResult(ActivityResultContracts.StartActivityForResult()){ } 여기 콜백을 등록해줘야하는 부분에서. 그 URI를 사용한다는 것 까지는 어지쩌지 주워듣고 알겠는데.. val img_URI = result.data?.get??? 이 get에 올수 있는게 없었다. 자동완성추천을 봐도 영.. 감이 안잡혀서..ㅎㅎ 튜터님이 올려주신 코드를 참고했다. 참고.. 라고 하고싶다. 여튼 근데 보는데 궁금한 점이 스코프함수 apply를 사용하셔서 setImageURI를 적용하신부분이.. 내 머리론 이해가 안간다. 그냥.. 그냥.. set하면되잖아... ?.(safecall)을 쓰신거 보면 그냥 안정적인 처리를 위해서? 인것 같기도하고.. 지금은 튜터님이 안계셔서 내일 꼭.. 물어보러.. 가야겟다!
그냥 set했더니 빨간줄이 나왔다. 확인해보니까 @SuppressLint("SuspiciousIndentation")를 걸어주라고 권장하길래 걸어주고 빨간줄을 지웠다. @SuppressLint는 minSdkVersion 버젼 이후에 나온 API를 사용할때 warning을 없애고 사용할 수 있게 합니다. 라는 설명을 찾았는데 SuspiciousIndentation이거는.. 들여쓰기.?에 관한 얘기같은데 여기서 굳이 나온 이유를 잘 모르겠다. 린트가 뭔지 앞으로 배우..려나? 이것도 내일 물어봐야겠다.
=>질문에 대한 답변은 '[TIL] Android 앱 개발 입문 : UI 클론 코딩 및 자기소개 앱에 대한 보완'에서 '📖 UI 클론 코딩'참고