요약
1. 설빙, 디저트, 음료의 모든 메뉴 및 레시피 정보를 이미지화
2. 스크롤을 내려서 메뉴를 볼 때, 스크롤의 버벅임이 심하다는 문제 해결
3. .gitignore를 사용하여 레시피 정보가 담긴 이미지들은 GitHub에 Push되지 않도록 수정
본문
1. 레시피 정보 이미지화
메뉴도 많고 레시피도 많은데, 그대로 퍼와서 담기에는 불성실해보이기도 하고, 깔끔하지도 않아서 새로 제작하였다. 그래서 시간이 좀 걸렸다.
다만 아쉽게도 레시피의 내용은 보여줄 수 없기 때문에 글로만 작성한다.
2. 스크롤 버벅임 문제 해결
1. Recyclerview 사용
LinearLayout을 사용하여 모든 메뉴를 일일히 나열했기 때문에 스크롤 버벅임이 심하다고 생각했고, 따라서 Recyclerview를 사용하기로 하였다. 버튼을 나타내는 layout 하나만 구현한다면, 나머지는 Recyclerview에 데이터만 추가해주면 자동으로 메뉴들이 출력이 된다.
Recyclerview를 사용하기 위해, 버튼을 나타내는 layout을 구현하였다.
activity_sulbing.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:orientation="vertical"
tools:context=".SulbingActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="@drawable/menubar"
android:orientation="vertical">
<ImageView
android:id="@+id/sulbingTitle"
android:layout_width="72dp"
android:layout_height="wrap_content"
android:src="@drawable/sulbingtitle" />
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_sulbing"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/backgroundcolor1" />
</LinearLayout>
sulbing_recycler.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="200dp"
android:layout_height="200dp"
android:orientation="horizontal">
<ImageButton
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:id="@+id/sulbingbutton"
android:layout_width="200dp"
android:layout_height="175dp"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:adjustViewBounds="true"
android:backgroundTint="@android:color/transparent"
android:contentDescription="Injeolmi Toast"
android:padding="0dp"
android:scaleType="fitCenter"
android:src="@drawable/injeolmi" />
<TextView
android:id="@+id/sulbingindex"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1"
android:backgroundTint="@android:color/transparent" />
</LinearLayout>
그리고, 데이터의 형태를 정의하는 클래스를 생성해야 한다.
본인은 SulbingRecycler라는 이름으로 데이터 클래스를 정의해주었다.
SulbingRecycler.kt
package com.bodan.sulbingrecipe
data class SulbingRecycler(var sulbingbutton: Int, var sulbingindex: Int)
이제 어댑터를 생성한다. 어댑터는 ViewHolder를 정의하고, 데이터와 바인딩함으로써 ViewHolder를 특정 위치에 할당하는 역할을 한다.
본인은 ViewHolder를 CustomViewHolder라는 내부 클래스로 어댑터 안에 정의하였다.
어댑터는 다음과 같은 메소드로 구성되어 있다.
- onCreateViewHolder() : ViewHolder 객체 생성
- getItemCount() : itemView의 개수 return
- onBindViewHolder() : position에 해당하는 데이터를 ViewHolder의 itemView에 표시
onCreateViewHolder() 메소드를 재정의해, LayoutInflater를 이용하여 sulbing_recycler, 즉 아까 위에서 언급했던 Recyclerview를 통해 나타낼 ImageButton을 실제 객체로 만든다.(inflate())
SulbingAdapter.kt
package com.bodan.sulbingrecipe
import android.content.Intent
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageButton
import android.widget.TextView
import android.widget.Toast
import androidx.core.content.ContextCompat
import androidx.core.content.ContextCompat.startActivity
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
class SulbingAdapter(val sulbingList: ArrayList<SulbingRecycler>): RecyclerView.Adapter<SulbingAdapter.CustomViewHolder>() {
var mPosition = 0
fun getPosition(): Int {
return mPosition
}
private fun setPosition(position: Int) {
mPosition = position
}
fun addItem(sulbingRecycler: SulbingRecycler) {
sulbingList.add(sulbingRecycler)
notifyDataSetChanged()
}
fun removeItem(position: Int) {
if (position > 0) {
sulbingList.removeAt(position)
notifyDataSetChanged()
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SulbingAdapter.CustomViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.sulbing_recycler, parent, false)
return CustomViewHolder(view)
}
override fun getItemCount(): Int {
return sulbingList.size
}
override fun onBindViewHolder(holder: SulbingAdapter.CustomViewHolder, position: Int) {
holder.bind(sulbingList[position])
holder.sulbingbutton.setOnClickListener {
val intent = Intent(holder.itemView?.context, SulbingrecipeActivity::class.java)
intent.putExtra("idText", holder.sulbingindex.text)
startActivity(holder.itemView.context, intent, null)
}
}
class CustomViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) {
val sulbingbutton = itemView.findViewById<ImageButton>(R.id.sulbingbutton)
val sulbingindex = itemView.findViewById<TextView>(R.id.sulbingindex)
init {
sulbingbutton.setOnClickListener {
}
}
}
}
마지막으로, sulbingList라는 ArrayList에 아까 정의한 데이터 클래스 SulbingRecycler를 통하여 데이터를 넣고, 어댑터를 이용하여 Recyclerview에 띄워주면 된다. 친구는 여기서 한 줄에 버튼을 2개씩 보이게 했으면 좋겠다는 언급을 하였고, 따라서 어댑터를 통해 데이터를 객체화시켜 나타내기 전에 GridLayoutManager를 이용하여 Recyclerview의 layout을 수정해주었다. Parameter 중에서 spanCount를 2로 지정하면 한 줄에 버튼이 2개씩 보인다.
SulbingActivity.kt
val sulbingList = arrayListOf(
SulbingRecycler(R.drawable.injeolmi, 1),
SulbingRecycler(R.drawable.patinjeolmi, 2),
// ...
SulbingRecycler(R.drawable.warrplainstrawberry, 25),
SulbingRecycler(R.drawable.chekschocostrawberry, 26)
)
rv_sulbing.layoutManager = GridLayoutManager(applicationContext, 2)
rv_sulbing.setHasFixedSize(true)
rv_sulbing.adapter = SulbingAdapter(sulbingList)
rv_sulbing.setNestedScrollingEnabled(false);
// ...
여기까지 하고 실행해 보았으나, 별 차이점이 없어서 다시 생각을 해 보았다.
2. Glide를 사용하여 이미지 불러오기
유의미한 차이가 나지 않는 이유가 바로 이미지를 불러오는 방식이라고 생각했다.
수소문 끝에 Glide라는 라이브러리를 알아냈고, Glide를 사용해본 결과 스크롤 속도가 확실히 빨라졌다.
비록 완전히 버벅임을 사라지게 하지는 못 했다고 할 수 있지만, 많이 완화시킨 것만으로도 의미있는 학습이었다.
본인은 이미지 URL을 추가해서 이미지를 불러오게 하는 방식을 사용하였고, 따라서 Recycler 클래스에서 ImageButton 데이터의 자료형을 String으로 변경하였다.
SulbingRecycler.kt
package com.bodan.sulbingrecipe
data class SulbingRecycler(var sulbingbutton: String, var sulbingindex: Int)
그리고 Adapter 클래스도 수정해주어야 했다. ViewHolder 내부 클래스에서 ImageButton에 사용할 이미지 파일을 Glide 라이브러리를 통하여 업로드해주었다.
SulbingAdapter.kt
import com.bumptech.glide.Glide
// ...
class CustomViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) {
val sulbingbutton = itemView.findViewById<ImageButton>(R.id.sulbingbutton)
val sulbingindex = itemView.findViewById<TextView>(R.id.sulbingindex)
fun bind(sulbingRecycler: SulbingRecycler) {
Glide.with(itemView).load(sulbingRecycler.sulbingbutton).centerInside().into(sulbingbutton)
sulbingindex.text = sulbingRecycler.sulbingindex.toString()
}
init {
sulbingbutton.setOnClickListener {
}
}
}
}
마지막으로 sulbingList는 이미지 파일의 URL과 인덱스 번호로 데이터가 이루어져 있는 arrayList로 구성해주었다.
SulbingActivity.kt
val sulbingList = arrayListOf(
SulbingRecycler("https://postfiles.pstatic.net/MjAyMjAzMjNfMjc4/MDAxNjQ4MDIzNjYyOTEy.3Hz4b7e-jjWtyVB0mMiGfO9OtCMrucCvnOCBXwUGvrIg.vRILB8oZkfrQDrCxdn-WRn_LzMxd5OFAPiAOGi3gycYg.PNG.littlesam95/injeolmi.png?type=w580", 1),
SulbingRecycler("https://postfiles.pstatic.net/MjAyMjAzMjNfODUg/MDAxNjQ4MDMwNjg2MTU5.qYTmBv0n1lMi2QbSPTe05cCCeOsqiiZ8tBwR2OGN53Ig.ppmWUV65hLdkqblOyJLUeRJdUPXrfOJfyyOHW58UcxAg.PNG.littlesam95/patinjeolmi.png?type=w580", 2),
// ...
SulbingRecycler("https://postfiles.pstatic.net/MjAyMjAzMjNfMTIx/MDAxNjQ4MDMwNjg2Nzcw.pUr_7GHSNpGBdioDUd8DUBL642xjd2q4TrlwyNhFpyQg.khjto7qXdufIqiIvTGpI7aPoAuS0aVgYWIAS-JGlsgwg.PNG.littlesam95/warrplainstrawberry.png?type=w580", 25),
SulbingRecycler("https://postfiles.pstatic.net/MjAyMjAzMjNfMTkg/MDAxNjQ4MDIzNjYxODkz.7mxep_by-ZzI6lsHiFAHboxcqylYk_cvDPm1e5cA-00g.1Gq-ILkZYLRfY5f2pTrD4q13ty5hfTYc74MtiWuC4GUg.PNG.littlesam95/chekschocostrawberry.png?type=w580", 26)
)
rv_sulbing.layoutManager = GridLayoutManager(applicationContext, 2)
rv_sulbing.setHasFixedSize(true)
rv_sulbing.adapter = SulbingAdapter(sulbingList)
rv_sulbing.setNestedScrollingEnabled(false);
// ...
디저트와 음료 부분도 마찬가지로 Glide를 사용해주었다.
실행 화면
3. .gitignore 사용
레시피의 정보를 공개하면 안 되므로, GitHub에 이미지 파일을 push하는 것을 막아야겠다고 생각하였다.
따라서, 디렉토리 최상단에 있는 .gitignore에 다음과 같은 코드를 추가하였다.
*.png
이제 확장자가 png인 이미지 파일들은 GitHub에 push를 진행해도 모두 무시된다.
즉, 레시피의 정보가 담긴 이미지 파일들이 공개되는 것을 막을 수 있다.
다음 할 일
이제 사용기한표를 만들고, 메인화면을 제외한 디자인을 수정하면 얼추 완성될 것이다.
GitHub
https://github.com/littlesam95/Sulbingrecipe
'개인 프로젝트 > 안드로이드' 카테고리의 다른 글
[메이플 캘린더] 메이플 캘린더라는 앱을 만들어보았다! 그런데...? (0) | 2024.01.16 |
---|---|
[개인 프로젝트] 설빙 레시피 앱 #3 (0) | 2022.03.31 |
[개인 프로젝트] 설빙 레시피 앱 #1 (0) | 2022.03.14 |
[개인 프로젝트] 메이플 브금 맞추기 앱 #8 (3) | 2022.03.11 |
[메이플 브금 맞추기] BGM 목록 (0) | 2022.03.11 |