# 사진 넣기

1. 어댑터 클래스에서 뷰 홀더를 bind 해줄 때 어댑터 position을 이용한다

override fun onBindViewHolder(holder: MovieViewHolder, position: Int) {
        when (position) {
            0 -> {
                holder.itemBinding.ivPhoto.setImageResource(R.drawable.movie01)
            }
            1 -> {
                holder.itemBinding.ivPhoto.setImageResource(R.drawable.movie02)
            }
            2 -> {
                holder.itemBinding.ivPhoto.setImageResource(R.drawable.movie03)
            }
            3 -> {
                holder.itemBinding.ivPhoto.setImageResource(R.drawable.movie04)
            }
            4 -> {
                holder.itemBinding.ivPhoto.setImageResource(R.drawable.movie05)
            }
            5 -> {
                holder.itemBinding.ivPhoto.setImageResource(R.drawable.movie06)
            }
        }
        if (position > 5) {
            holder.itemBinding.ivPhoto.setImageResource(R.drawable.ic_launcher_foreground)
        }
        ...

 

- 더 효율적으로 작성하려면?

val imageResources = arrayOf(
        R.drawable.movie01,
        R.drawable.movie02,
        R.drawable.movie03,
        R.drawable.movie04,
        R.drawable.movie05,
        R.drawable.movie06
    )
if (position < imageResources.size) {
            holder.itemBinding.ivPhoto.setImageResource(imageResources[position])
        } else {
            // Set a default image for positions outside the range of the array
            holder.itemBinding.ivPhoto.setImageResource(R.drawable.ic_launcher_foreground)
        }

 

2. update activity에 사진 넣기

- 위와 같이 이미지 배열 사용

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(updateBinding.root)

        val dto = intent.getSerializableExtra("dto") as MovieDto
		...

        if (dto.id in 1..imageResources.size) {
            updateBinding.ivUpdatePhoto.setImageResource(imageResources[dto.id - 1])
        } else {
            updateBinding.ivUpdatePhoto.setImageResource(R.drawable.ic_launcher_foreground)
        }
        ...

 

# 검색 기능 만들기

1. 검색 레이아웃과 메뉴칸을 추가한다

- 레이아웃

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/textView5"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="영화 제목 검색하기"
        android:textSize="25sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <EditText
        android:id="@+id/etSearch"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:ems="10"
        android:hint="검색어 입력"
        android:inputType="text"
        android:textSize="20sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.497"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView5" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rvSearch"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginTop="20dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/btnSearchCancel"
        app:layout_constraintVertical_bias="0.0" />

    <Button
        android:id="@+id/btnSearchCancel"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:text="뒤로가기"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/etSearch" />

</androidx.constraintlayout.widget.ConstraintLayout>

 

- 메뉴칸 추가

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/menuItem01"
        android:title="영화 추가" />
    <item
        android:id="@+id/menuItem02"
        android:title="개발자 정보" />
    <item
        android:id="@+id/menuItem03"
        android:title="영화 정보 검색" />
    <item
        android:id="@+id/menuItem04"
        android:title="앱 종료"/>
</menu>

 

 

2. 검색 기능을 위한 어댑터를 새로 생성한다

- 기존 어댑터와 유사하지만 다른 점은 onBindHolder에서 item을 바인딩할 때 전체 리스트가 아닌 검색한 리스트를 바인딩한다.

override fun onBindViewHolder(holder: SearchViewHolder, position: Int) {
        if (position < imageResources.size) {
            holder.itemBinding.ivPhoto.setImageResource(imageResources[position])
        } else {
            // Set a default image for positions outside the range of the array
            holder.itemBinding.ivPhoto.setImageResource(R.drawable.ic_launcher_foreground)
        }
        holder.itemBinding.tvMovie.text = filteredList[position].movie
        holder.itemBinding.tvRate.text = filteredList[position].rate
        holder.itemBinding.tvDirector.text = filteredList[position].director
    }

 

- getFilter 함수를 구현한다

override fun getFilter(): Filter {
        return object : Filter() {
            override fun performFiltering(input: CharSequence?): FilterResults {
                val userInput = input.toString().lowercase() // 사용자가 입력한 값

                filteredList = if (userInput.isEmpty()) {
                    unFilteredList
                } else {
                    val filteringList = ArrayList<MovieDto>()
                    for (movie in unFilteredList) {
                        if (movie.movie.lowercase().contains(userInput) || movie.director.lowercase().contains(userInput)) {
                            filteringList.add(movie)
                        }
                    }
                    filteringList
                }

                val filterResults = FilterResults()
                filterResults.values = filteredList

                return filterResults
            }

            @SuppressLint("NotifyDataSetChanged")
            override fun publishResults(p0: CharSequence?, results: FilterResults?) {
                filteredList = results?.values as List<MovieDto>
                notifyDataSetChanged() // 필터링 된 결과가 갱신 되었음을 알려준다.
            }
        }
    }

 

- 전체 코드는 다음과 같다

더보기
package ddwu.com.mobile.finalreport

import android.annotation.SuppressLint
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Filter
import android.widget.Filterable
import androidx.recyclerview.widget.RecyclerView
import ddwu.com.mobile.finalreport.data.MovieDto
import ddwu.com.mobile.finalreport.databinding.ListItemBinding

class SearchAdapter(val movies: ArrayList<MovieDto>)
    : RecyclerView.Adapter<SearchAdapter.SearchViewHolder>(), Filterable {
    val imageResources = arrayOf(
        R.drawable.movie01,
        R.drawable.movie02,
        R.drawable.movie03,
        R.drawable.movie04,
        R.drawable.movie05,
        R.drawable.movie06
    )
    private var filteredList: List<MovieDto> = movies
    private val unFilteredList: List<MovieDto> = movies

    override fun getItemCount(): Int = filteredList.size

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SearchViewHolder {
        val itemBinding = ListItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
        return SearchViewHolder(itemBinding)
    }

     override fun onBindViewHolder(holder: SearchViewHolder, position: Int) {
        if (position < imageResources.size) {
            holder.itemBinding.ivPhoto.setImageResource(imageResources[position])
        } else {
            // Set a default image for positions outside the range of the array
            holder.itemBinding.ivPhoto.setImageResource(R.drawable.ic_launcher_foreground)
        }
        holder.itemBinding.tvMovie.text = filteredList[position].movie
        holder.itemBinding.tvRate.text = filteredList[position].rate
        holder.itemBinding.tvDirector.text = filteredList[position].director
    }

    inner class SearchViewHolder(val itemBinding: ListItemBinding)
        : RecyclerView.ViewHolder(itemBinding.root) {

    }

    override fun getFilter(): Filter {
        return object : Filter() {
            override fun performFiltering(input: CharSequence?): FilterResults {
                val userInput = input.toString().lowercase() // 사용자가 입력한 값

                filteredList = if (userInput.isEmpty()) {
                    unFilteredList
                } else {
                    val filteringList = ArrayList<MovieDto>()
                    for (movie in unFilteredList) {
                        if (movie.movie.lowercase().contains(userInput) || movie.director.lowercase().contains(userInput)) {
                            filteringList.add(movie)
                        }
                    }
                    filteringList
                }

                val filterResults = FilterResults()
                filterResults.values = filteredList

                return filterResults
            }

            @SuppressLint("NotifyDataSetChanged")
            override fun publishResults(p0: CharSequence?, results: FilterResults?) {
                filteredList = results?.values as List<MovieDto>
                notifyDataSetChanged() // 필터링 된 결과가 갱신 되었음을 알려준다.
            }
        }
    }
}

 

3. SearchActivity 구현하기

- SearchAdapter를 활용하여 액티비티를 완성한다.

package ddwu.com.mobile.finalreport

import android.annotation.SuppressLint
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import ddwu.com.mobile.finalreport.data.MovieDao
import ddwu.com.mobile.finalreport.data.MovieDto
import ddwu.com.mobile.finalreport.databinding.ActivitySearchBinding

class SearchActivity : AppCompatActivity() {
    val searchBinding by lazy {
        ActivitySearchBinding.inflate(layoutInflater)
    }
    lateinit var movies: ArrayList<MovieDto> // 데이터
    val movieDao by lazy {
        MovieDao(this)
    }

    @SuppressLint("Range")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(searchBinding.root)

        // Fetch all movies from the database
        movies = movieDao.getAllMovies()

        // Setup RecyclerView
        val adapter = SearchAdapter(movies)
        searchBinding.rvSearch.layoutManager = LinearLayoutManager(this)
        searchBinding.rvSearch.adapter = adapter

        // Add TextWatcher to filter movies based on user input
        searchBinding.etSearch.addTextChangedListener(object : TextWatcher {
            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                adapter.filter.filter(s)
            }

            override fun afterTextChanged(s: Editable?) {}
        })

        // Cancel button click listener
        searchBinding.btnSearchCancel.setOnClickListener {
            finish()
        }
    }
}

 

4. 메인에서 메뉴 클릭 시 액티비티 전환 구현

R.id.menuItem03 -> {
                val intent = Intent(this@MainActivity, SearchActivity::class.java)
                startActivity(intent)
            }

 

5. 오류

- 검색 시 이미지가 filteredList의 position에 걸리는 것이 아닌 dto의 id에 영향을 받아야 제대로 이미지가 나온다

when (filteredList[position].id) {
            1 -> {
                holder.itemBinding.ivPhoto.setImageResource(R.drawable.movie01)
            }
            2 -> {
                holder.itemBinding.ivPhoto.setImageResource(R.drawable.movie02)
            }
            3 -> {
                holder.itemBinding.ivPhoto.setImageResource(R.drawable.movie03)
            }
            4 -> {
                holder.itemBinding.ivPhoto.setImageResource(R.drawable.movie04)
            }
            5 -> {
                holder.itemBinding.ivPhoto.setImageResource(R.drawable.movie05)
            }
            6 -> {
                holder.itemBinding.ivPhoto.setImageResource(R.drawable.movie06)
            }
        }
        if (filteredList[position].id > 6) {
            holder.itemBinding.ivPhoto.setImageResource(R.drawable.ic_launcher_foreground)
        }

 

 

동영상 서비스가 종료되어 해당 콘텐츠를 재생할 수 없습니다.

 

+ Recent posts