그중에서 이미지검색 API를 가져와보려고 한다.
위 링크를 들어가서 보면

//gson, retrofit
implementation ("com.google.code.gson:gson:2.10.1")
implementation ("com.squareup.retrofit2:retrofit:2.9.0")
implementation ("com.squareup.retrofit2:converter-gson:2.9.0")
implementation ("com.squareup.okhttp3:okhttp:4.10.0")
implementation ("com.squareup.okhttp3:logging-interceptor:4.10.0")
//
<uses-permission android:name="android.permission.INTERNET"/>
이렇게 기본정보가 나와있다. search앞 /를 기준으로
https://dapi.kakao.com/v2/ 와 search/image로 나눠서 저장해준다.
다음으로 내 어플리케이션에 들어가 앱을 추가하고 REST API 키를 저장해둔다.
공식문서에서 조금 아래로 내려보면 요청값에 헤더와 쿼리 파라미터가 있다. 이 값들을 이용해서 인터페이스를 만들어준다. 여기서 @GET()괄호 안에는 위에서 저장해둔 키값인 search/image를 넣어주면된다.
interface NetWorkInterface {
@GET(Contract.REQUEST_ADDRESS)
suspend fun getImage(
@Header("Authorization") authHeader: String,
@QueryMap param: HashMap<String, String>
): SearchResponse
}
공식문서를 더 내려보면 응답 부분에 이렇게 있다. 이 값들을 이용해서 json파일을 gson으로 받아와준다. 이중에서 thumbnail_url, display_sitename, datetime 3가지 데이터를 가져와서 사용할 예정이다.
data class SearchResponse(
@SerializedName("meta")
val searchMeta: SearchMeta,
@SerializedName("documents")
val searchDocument: MutableList<SearchDocument>?
)
data class SearchMeta(
val is_end: Boolean,
val pageable_count: Int,
val total_count: Int
)
data class SearchDocument(
val collection: String,
val datetime: String,
val display_sitename: String,
val doc_url: String,
val height: Int,
val image_url: String,
val thumbnail_url: String,
val width: Int
)
네트워크 클라이언트를 object로 만들어준다. 여기서 baseUrl에는 미리저장해둔 키인 https://dapi.kakao.com/v2/ 를 넣어주면 된다.
object NetWorkClient {
private fun createOkHttpClient(): OkHttpClient {
val interceptor = HttpLoggingInterceptor()
if (BuildConfig.DEBUG)
interceptor.level = HttpLoggingInterceptor.Level.BODY
else
interceptor.level = HttpLoggingInterceptor.Level.NONE
return OkHttpClient.Builder()
.connectTimeout(20, TimeUnit.SECONDS)
.readTimeout(20, TimeUnit.SECONDS)
.writeTimeout(20, TimeUnit.SECONDS)
.addNetworkInterceptor(interceptor)
.build()
}
private val imageRetrofit = Retrofit.Builder()
.baseUrl(Contract.SERVICE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(createOkHttpClient())
.build()
val imageNetWork: NetWorkInterface = imageRetrofit.create(NetWorkInterface::class.java)
}
이 값들을 프레그먼트에서 받아와야한다.
private fun communicateNetWork(param: HashMap<String, String>) = lifecycleScope.launch() {
val authKey = "KakaoAK ${Contract.API_KEY}"
val responseData = NetWorkClient.imageNetWork.getImage(authKey, param)
items = responseData.searchDocument ?: mutableListOf()
val adapter = SearchAdapter(items)
adapter.itemClick = object : SearchAdapter.ItemClick{
override fun onClick(item: SearchDocument, position: Int) {
handleSelectedItem(item)
}
}
binding.searchRecyclerView.adapter = adapter
binding.searchRecyclerView.layoutManager = GridLayoutManager(context, 2)
}
...
private fun setUpImageParameter(input: String): HashMap<String, String> {
val authKey = "KakaoAK ${Contract.API_KEY}" //REST API 키 넣어주기
return hashMapOf(
"Authorization" to authKey,
"query" to input,
"sort" to "recency",
"page" to "1",
"size" to "80"
)
}
위 함수들을 프레그먼트 안에서 사용해줄건데, edittext에 검색어를 입력하고, 확인버튼을 누르면 검색어를 가지고와서 리사이클러뷰에 띄워주기 위해서 버튼 클릭시에 선언해줬다.
searchImage.setOnClickListener {
val searchEdit = searchEdit.text.toString()
if (searchEdit.isNotBlank()) {
val searchParam = setUpImageParameter(searchEdit)
communicateNetWork(searchParam)
}
}
kakaoAPI,kakaoapi,이미지검색
뷰페이저2 + 텝레이아웃을 같이 적용시키는 방법
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@+id/tab_layout"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.tabs.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
사용할 화면에 하단에 템레이아웃을, 화면전체에 뷰페이저를 만들어줬다.
이동할 프레그먼트를 hi,hihi라고 이름을 짓는다면, 그 안에서 companion object를 이용해서 newInstance를 만들어준다.
//프래그먼트1
companion object {
fun newInstance() = hiFragment()
}
//프래그먼트2
companion object {
fun newInstance() = hihiFragment()
}
메인탭 데이터클래스를 만들어준다.
data class MainTab(
val fragment:Fragment,
@StringRes val title:Int
)
어뎁터를 만들어서 연결해준다. 리스트로 MainTab에 추가할 프래그먼트를 관리해주면 프래그먼트를 추가할때도 관리가 편해져서 이렇게 사용한다.
class MainViewPagerAdapter(
fragmentActivity: FragmentActivity
) : FragmentStateAdapter(fragmentActivity) {
private val fragments= listOf(
MainTab(
fragment = ImageSearchFragment.newInstance(),
title = R.string.main_tab_search
),
MainTab(
fragment = KeepFragment.newInstance(),
title = R.string.main_tab_keep
)
)
override fun getItemCount(): Int = fragments.size
override fun createFragment(position: Int): Fragment = fragments[position].fragment
fun getTitle(position: Int): Int = fragments[position].title
}
먼저 뷰페이저를 선언해준다.
private val viewPagerAdapter by lazy {
MainViewPagerAdapter(this@MainActivity)
}
그리고 어뎁터를 연결해준다.
private fun initView() = with(binding) {
viewPager.adapter = viewPagerAdapter
TabLayoutMediator(tabLayout, viewPager){ tab, position ->
tab.setText(viewPagerAdapter.getTitle(position))
}.attach()
}
이렇게 사용하면 화면에 viewPager와 TabLayout을 적용시킬 수 있다.
ViewPager, viewpager, viewPager, TabLayout, tablayout
private fun View.hideKeyboardInput() {
val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(windowToken, 0)
}
위 함수를 원하는곳에서 불러주면 된다. 그냥부를때 -> hideKeyboardInput() 프래그먼트에서 부를때 -> binding.root.hideKeyboardInput()
키보드숨김처리,키보드숨김,키보드