Android/StoreInfo

<정리> 심화 개인과제 5

re트 2024. 1. 31. 20:35
728x90

이제 오늘 지나면 제출일이다.

오늘 한 것은... 챌린지반 복습하느라 그렇게 많지 않다.

보완과 약간의 기능 추가 정도?

 

1. 뷰모델로 옮긴 함수

이전에 검색 결과 페이지에 있던 데이터 요청 함수를 뷰모델로 옮겼다.

이로인해 뷰모델로 현재 EditText의 텍스트값만 넘겨주면 됐고 업데이트는 옵저버를 통해 할 수 있게 되었다.

아래는 첫번째로 검색할 때에 대한 내용이고 스크롤을 최하단으로 내렸을 때 데이터를 받아오는 것도 아래 코드처럼 작성했다.

btnSearch.setOnClickListener {
    viewModel.processFirstSearch(etSearch.text.toString())
    goToFirstState()
}

===============================================================

fun processFirstSearch(word: String) {
    if (word == "") return

    page = 1
    updateLastWord(word)
    type.value?.let { communicationNetwork(word, page++, it) }
}

 

2. 키보드 검색버튼

처음에는 키보드에 검색버튼이 없고 다음 줄로 가는 버튼이 있었다.

나는 당연히 EditText에 포커스를 주면 검색버튼이 생기는 줄 알았는데 이것도 세팅해야한다는 걸 오늘 처음 알았다.

android:inputType="text"
android:maxLines="1"
android:imeOptions="actionSearch"

해당 3가지 속성을 줘서 키보드에 검색버튼이 뜨고 한줄만 입력되도록 했다.

 

그리고 키보드 검색 버튼을 누른걸 감지하는 리스너는 다음과 같이 사용했다.

etSearch.setOnEditorActionListener { _, actionId, _ ->
    if (actionId == EditorInfo.IME_ACTION_SEARCH) {
        viewModel.processFirstSearch(etSearch.text.toString())
        goToFirstState()
    }

    false
}

 

3. 간단한 필터링 기능

필터링을 다양하게 하려니까 머리가 너무 아팠다...

그래서 정말 간단하게 이미지와 비디오 모두, 이미지만, 비디오만 검색결과로 보여주는 필터링을 진행했다.

이걸 위해 BottomSheet와 MaterialButtonToggleGroup을 사용했다.

BottomSheet는 부족한 공간을 얻어내기 위해 사용했고 MaterialButtonToggleGroup은 직접 만들기에는 디자인적인 아이디어가 떠오르지 않는 상황에 유용하게 쓰고 또한 그룹이라서 한개씩만 선택기능이 있어 사용했다.

BottomSheet에서는 많은 걸 하지는 않는다.

취소 버튼, 버튼 세팅, 버튼 그룹 체크 리스너 정도가 들어가있다.

class SearchBottomSheet: BottomSheetDialogFragment() {

    private var _binding: FragmentBottomSheetBinding? = null
    private val binding get() = _binding!!

    // 공유 뷰모델 선언
    private val viewModel: MainViewModel by activityViewModels()

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        _binding = FragmentBottomSheetBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        binding.imgBottomSheetClearBtn.setOnClickListener {
            dismiss()
        }

        binding.toggleGroupFilterType.check(
            when (viewModel.type.value) {
                0 -> R.id.btn_type_1
                1 -> R.id.btn_type_2
                else -> R.id.btn_type_3
            }
        )

        binding.toggleGroupFilterType.addOnButtonCheckedListener { group, checkedId, isChecked ->
            if (isChecked) {
                when (checkedId) {
                    R.id.btn_type_1 -> {
                        viewModel.setType(0)
                    }
                    R.id.btn_type_2 -> {
                        viewModel.setType(1)
                    }
                    R.id.btn_type_3 -> {
                        viewModel.setType(2)
                    }
                }
            }
        }
    }
}

 

필터 타입 라이브 데이터를 설정하고 0으로 세팅했다.

그랬더니 그냥 바로 검색을 해버리더라

처음에 0으로 세팅한다는 거 자체가 옵저빙이 되어서 그런듯 했다.

그래서 처음에는 영향을 받지 않도록하기위해, 검색 결과가 아직 서버로부터 오지 않은 상태에서는 영향을 받지 않게 하기 위해 검색 결과 라이브데이터가 비어있지 않은지 확인하고 필터에 맞춰 검색을 진행하도록 했다.

fun filter(word: String) {
    if (word == "" || searchUiState.value?.searchResult.isNullOrEmpty()) return

    page = 1
    communicationNetwork(lastWord.value.toString(), page++)
}

 

필터에 맞춰 진행하기 위해 네트워크 통신 함수에는 type 변수에 대한 when까지 추가되었다.

when (type.value) {
    0 -> response.addAll(
        NetworkClient.searchNetwork.searchImage(param).imageDocuments.orEmpty() +
                NetworkClient.searchNetwork.searchVideo(param).videoDocuments.orEmpty()
    )

    1 -> response.addAll(
        NetworkClient.searchNetwork.searchImage(param).imageDocuments.orEmpty()
    )

    2 -> response.addAll(
        NetworkClient.searchNetwork.searchVideo(param).videoDocuments.orEmpty()
    )
}

 

4. 클립보드 저장 기능

뭔가 롱클릭을 했을 때에 기능이 하나더 있으면 좋겠다고 생각을 했는데 이게 딱 떠올랐다.

물론 데이터가 가지고 있는 정보가 그리 많지 않아서 그래도 유용한 사이트 URL을 저장하기로 했다.

어댑터에 있는 인터페이스 안에 롱클릭 리스너를 추가하고 바인딩해줬다.

처음에 한가지 뷰타입에만 해서 안 될 때 매우 당황했고 고친 다음에는 반응이 없어서 매우 당황했다.

앞에는 그냥 추가하는 걸로 해결했지만 뒤에는 setOnLongClickListener가 아니라 setOnClickListener에 붙여서 생긴 일이었다.ㅎㅎ

ClipboardManager를 사용했고 데이터 클래스에 따라 다른 변수값이 들어가도록 했다.

그리고 저장된 후에 토스트 메세지를 통해 저장되었음을 알려줬다.

override fun onLongClick(selectedDocument: Document) {
    val clipboardManager = requireContext().getSystemService(AppCompatActivity.CLIPBOARD_SERVICE) as ClipboardManager
    val clipData = ClipData.newPlainText(
        "url",
        when (selectedDocument) {
            is Document.ImageDocument -> {
                selectedDocument.docUrl
            }
            is Document.VideoDocument -> {
                selectedDocument.url
            }
        })
    clipboardManager.setPrimaryClip(clipData)
    Toast.makeText(requireContext(), "해당 데이터의 URL이 클립보드에 저장되었습니다.", Toast.LENGTH_SHORT).show()
}
반응형

'Android > StoreInfo' 카테고리의 다른 글

<정리> 챌린지반 과제2 - 5  (0) 2024.02.02
<정리> 챌린지반 과제2 - 4  (2) 2024.02.01
<정리> 심화 개인과제 4  (1) 2024.01.30
<정리> 심화 개인과제 3  (1) 2024.01.29
<정리> 심화 개인과제 2  (1) 2024.01.25