From c27ef328bced2f8c76a77a60f2eb32aa4a67f97a Mon Sep 17 00:00:00 2001 From: banjjak2 Date: Thu, 7 Apr 2022 21:11:26 +0900 Subject: [PATCH 01/25] =?UTF-8?q?[Android]=20=ED=9E=88=EC=8A=A4=ED=86=A0?= =?UTF-8?q?=EB=A6=AC=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84=20-=20View?= =?UTF-8?q?=20(#31)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * style: 폰트 변경 Noto Sans KR 폰트를 TextView에서 전역으로 사용할 수 있도록 수정 * style: Todo 및 History 스타일 설정 피그마에 있는대로 Todo 및 History 스타일 정의 * feat: 히스토리 목록 리사이클러 뷰 item 레이아웃 구현 * feat: UI 변경 및 Color 값 분리 * feat: 피드백 적용 및 drawer에서 X버튼 클릭 시 close 구현 피드백: binding을 이용해 뷰를 사용하도록 수정 * chore: XML id 미작성된 부분 수정 및 유저 이미지 표시 변경 * feat: 바인딩어댑터를 이용한 리사이클러 뷰 구현 --- Android/app/build.gradle | 1 + .../com/example/todo_list/MainActivity.kt | 38 ++++----- .../todo_list/history/BindingAdapters.kt | 76 ++++++++++++++++++ .../todo_list/history/HistoryAdapter.kt | 47 +++++++++++ .../{model => history}/HistoryReceive.kt | 7 +- .../{model => history/data}/HistoryCard.kt | 16 +--- .../history/data/HistoryRepository.kt | 3 +- .../app/src/main/res/drawable/ic_close.xml | 5 ++ .../app/src/main/res/drawable/user_img.png | Bin 0 -> 2620 bytes .../main/res/layout-sw720dp/activity_main.xml | 46 ++++++----- .../main/res/layout-sw720dp/history_item.xml | 72 +++++++++++++++++ .../app/src/main/res/layout/activity_main.xml | 59 ++++++-------- .../app/src/main/res/layout/history_item.xml | 55 +++++++++++++ Android/app/src/main/res/values/colors.xml | 3 + Android/app/src/main/res/values/strings.xml | 7 +- 15 files changed, 338 insertions(+), 97 deletions(-) create mode 100644 Android/app/src/main/java/com/example/todo_list/history/BindingAdapters.kt create mode 100644 Android/app/src/main/java/com/example/todo_list/history/HistoryAdapter.kt rename Android/app/src/main/java/com/example/todo_list/{model => history}/HistoryReceive.kt (81%) rename Android/app/src/main/java/com/example/todo_list/{model => history/data}/HistoryCard.kt (62%) create mode 100644 Android/app/src/main/res/drawable/ic_close.xml create mode 100644 Android/app/src/main/res/drawable/user_img.png create mode 100644 Android/app/src/main/res/layout-sw720dp/history_item.xml create mode 100644 Android/app/src/main/res/layout/history_item.xml diff --git a/Android/app/build.gradle b/Android/app/build.gradle index cc5fc4306..b912f35c1 100644 --- a/Android/app/build.gradle +++ b/Android/app/build.gradle @@ -1,6 +1,7 @@ plugins { id 'com.android.application' id 'org.jetbrains.kotlin.android' + id 'kotlin-kapt' } android { diff --git a/Android/app/src/main/java/com/example/todo_list/MainActivity.kt b/Android/app/src/main/java/com/example/todo_list/MainActivity.kt index f7aec4341..dd99c5397 100644 --- a/Android/app/src/main/java/com/example/todo_list/MainActivity.kt +++ b/Android/app/src/main/java/com/example/todo_list/MainActivity.kt @@ -1,48 +1,38 @@ package com.example.todo_list -import androidx.appcompat.app.AppCompatActivity import android.os.Bundle -import android.util.Log import android.view.MenuItem -import android.widget.ImageButton +import androidx.appcompat.app.AppCompatActivity import androidx.core.view.GravityCompat import androidx.databinding.DataBindingUtil -import androidx.drawerlayout.widget.DrawerLayout +import androidx.recyclerview.widget.LinearLayoutManager import com.example.todo_list.databinding.ActivityMainBinding +import com.example.todo_list.history.HistoryAdapter import com.example.todo_list.history.data.HistoryRepository -import com.example.todo_list.model.HistoryCard -import com.example.todo_list.model.HistoryReceive -import com.example.todo_list.model.Todos import com.google.android.material.navigation.NavigationView -import com.google.gson.JsonArray -import kotlinx.coroutines.CoroutineScope -import retrofit2.Call -import retrofit2.Callback -import retrofit2.Response class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener { - lateinit var navigationView: NavigationView - lateinit var drawerLayout: DrawerLayout - private lateinit var binding: ActivityMainBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = DataBindingUtil.setContentView(this, R.layout.activity_main) - drawerLayout = findViewById(R.id.main_layout) - + val adapter = HistoryAdapter() + binding.recyclerviewHistory.adapter = adapter + binding.recyclerviewHistory.layoutManager = LinearLayoutManager(this) binding.btnMenu.setOnClickListener { - drawerLayout.openDrawer(GravityCompat.END) + binding.mainLayout.openDrawer(GravityCompat.END) } + binding.btnClose.setOnClickListener { binding.mainLayout.closeDrawer(GravityCompat.END) } + binding.naviView.setNavigationItemSelectedListener(this) - navigationView = findViewById(R.id.navi_view) - navigationView.setNavigationItemSelectedListener(this) - - val str = HistoryRepository().getHistory() - str.observe(this) { - Log.d("LIVE", it.toString()) + val repository = HistoryRepository() + val history = repository.getHistory() + history.observe(this) { + adapter.submitList(it) } + repository.getHistory() } override fun onNavigationItemSelected(item: MenuItem): Boolean { diff --git a/Android/app/src/main/java/com/example/todo_list/history/BindingAdapters.kt b/Android/app/src/main/java/com/example/todo_list/history/BindingAdapters.kt new file mode 100644 index 000000000..5fb77a155 --- /dev/null +++ b/Android/app/src/main/java/com/example/todo_list/history/BindingAdapters.kt @@ -0,0 +1,76 @@ +package com.example.todo_list.history + +import android.text.format.DateUtils +import android.widget.TextView +import androidx.core.text.HtmlCompat +import androidx.core.text.HtmlCompat.FROM_HTML_MODE_LEGACY +import androidx.databinding.BindingAdapter +import com.example.todo_list.R +import com.example.todo_list.history.data.HistoryCard +import java.text.SimpleDateFormat +import java.util.* + +private fun convertAction(action: String): String { + return when (action) { + "move" -> "이동" + "add" -> "추가" + "remove" -> "삭제" + else -> "갱신" + } +} + +private fun convertStatus(status: String): String { + return when (status) { + "todo" -> "해야할 일" + "doing" -> "하고 있는 일" + else -> "한 일" + } +} + +@BindingAdapter("setUsername") +fun setUsername(view: TextView, username: String) { + view.text = String.format("@%s", username) +} + +@BindingAdapter("setBody") +fun setBody(view: TextView, body: HistoryCard) { + view.text = when (body.action) { + "move" -> + HtmlCompat.fromHtml( + view.context.getString( + R.string.history_move_string, + body.todo.contents, + convertStatus(body.from_status), + convertStatus(body.to_status), + convertAction(body.action) + ), + FROM_HTML_MODE_LEGACY + ) + else -> + HtmlCompat.fromHtml( + view.context.getString( + R.string.history_default_string, + convertStatus(body.todo.status), + body.todo.contents, + convertAction(body.action) + ), + FROM_HTML_MODE_LEGACY + ) + } +} + +@BindingAdapter("setTimeStamp") +fun setTimeStamp(view: TextView, timestamp: String) { + val inputFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.KOREA) + val date: Date? = inputFormat.parse(timestamp) + + if (date == null) view.text = "알 수 없음" + else { + val ago = DateUtils.getRelativeTimeSpanString( + date.time, + Calendar.getInstance().timeInMillis, + DateUtils.MINUTE_IN_MILLIS + ) + view.text = ago.toString() + } +} diff --git a/Android/app/src/main/java/com/example/todo_list/history/HistoryAdapter.kt b/Android/app/src/main/java/com/example/todo_list/history/HistoryAdapter.kt new file mode 100644 index 000000000..85b539986 --- /dev/null +++ b/Android/app/src/main/java/com/example/todo_list/history/HistoryAdapter.kt @@ -0,0 +1,47 @@ +package com.example.todo_list.history + +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.databinding.DataBindingUtil +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.ListAdapter +import androidx.recyclerview.widget.RecyclerView +import com.example.todo_list.R +import com.example.todo_list.databinding.HistoryItemBinding +import com.example.todo_list.history.data.HistoryCard + +class HistoryAdapter : ListAdapter(diffUtil) { + + inner class HistoryViewHolder(private val binding: HistoryItemBinding) : + RecyclerView.ViewHolder(binding.root) { + + fun bind(card: HistoryCard) { + binding.historyCard = card + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = + DataBindingUtil.inflate( + LayoutInflater.from(parent.context), + R.layout.history_item, + parent, + false + ).let { HistoryViewHolder(it) } + + + override fun onBindViewHolder(holder: HistoryViewHolder, position: Int) { + val item = getItem(position) + holder.bind(item) + } +} + +private val diffUtil = object : DiffUtil.ItemCallback() { + override fun areItemsTheSame(oldItem: HistoryCard, newItem: HistoryCard): Boolean { + return oldItem.id == newItem.id + } + + override fun areContentsTheSame(oldItem: HistoryCard, newItem: HistoryCard): Boolean { + return oldItem == newItem + } + +} \ No newline at end of file diff --git a/Android/app/src/main/java/com/example/todo_list/model/HistoryReceive.kt b/Android/app/src/main/java/com/example/todo_list/history/HistoryReceive.kt similarity index 81% rename from Android/app/src/main/java/com/example/todo_list/model/HistoryReceive.kt rename to Android/app/src/main/java/com/example/todo_list/history/HistoryReceive.kt index 17dcb7bab..86d0a478b 100644 --- a/Android/app/src/main/java/com/example/todo_list/model/HistoryReceive.kt +++ b/Android/app/src/main/java/com/example/todo_list/history/HistoryReceive.kt @@ -1,7 +1,7 @@ -package com.example.todo_list.model +package com.example.todo_list.history +import com.example.todo_list.history.data.HistoryCard import retrofit2.Call -import retrofit2.Response import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory import retrofit2.http.GET @@ -21,7 +21,4 @@ class HistoryReceive { interface HistoryApi { @GET("api/{todos}") // 어노테이션 fun getHistory(@Path("todos") variable: String): Call> - - @GET("api/{todos}") - fun getTodos(@Path("todos") variable: String): Call> } \ No newline at end of file diff --git a/Android/app/src/main/java/com/example/todo_list/model/HistoryCard.kt b/Android/app/src/main/java/com/example/todo_list/history/data/HistoryCard.kt similarity index 62% rename from Android/app/src/main/java/com/example/todo_list/model/HistoryCard.kt rename to Android/app/src/main/java/com/example/todo_list/history/data/HistoryCard.kt index ee170866d..a4d3b2416 100644 --- a/Android/app/src/main/java/com/example/todo_list/model/HistoryCard.kt +++ b/Android/app/src/main/java/com/example/todo_list/history/data/HistoryCard.kt @@ -1,10 +1,10 @@ -package com.example.todo_list.model +package com.example.todo_list.history.data import com.google.gson.annotations.SerializedName data class HistoryCard( val id: Int, - val todo: todo, + val todo: Todo, val action: String, @SerializedName("from status") @@ -14,7 +14,7 @@ data class HistoryCard( val createdDateTime: String ) -data class todo( +data class Todo( val id: Int, val title: String, val contents: String, @@ -23,13 +23,3 @@ data class todo( val createdDateTime: String, val updatedDateTime: String ) - -data class Todos( - val id: Int, - val title: String, - val contents: String, - val user: String, - val status: String, - val createdDateTime: String, - val updatedDateTime: String -) \ No newline at end of file diff --git a/Android/app/src/main/java/com/example/todo_list/history/data/HistoryRepository.kt b/Android/app/src/main/java/com/example/todo_list/history/data/HistoryRepository.kt index 79ffa369d..b920dfc43 100644 --- a/Android/app/src/main/java/com/example/todo_list/history/data/HistoryRepository.kt +++ b/Android/app/src/main/java/com/example/todo_list/history/data/HistoryRepository.kt @@ -3,8 +3,7 @@ package com.example.todo_list.history.data import android.util.Log import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData -import com.example.todo_list.model.HistoryCard -import com.example.todo_list.model.HistoryReceive +import com.example.todo_list.history.HistoryReceive import retrofit2.Call import retrofit2.Callback import retrofit2.Response diff --git a/Android/app/src/main/res/drawable/ic_close.xml b/Android/app/src/main/res/drawable/ic_close.xml new file mode 100644 index 000000000..96a3d6abc --- /dev/null +++ b/Android/app/src/main/res/drawable/ic_close.xml @@ -0,0 +1,5 @@ + + + diff --git a/Android/app/src/main/res/drawable/user_img.png b/Android/app/src/main/res/drawable/user_img.png new file mode 100644 index 0000000000000000000000000000000000000000..4e6764e789d50bc2bd7182cd08815d65f2c3c589 GIT binary patch literal 2620 zcmV-C3d8k@P)(oqO-zyPJJv^L_#nRuWCc$WuWDMuSY4Qma$YPPOXPsYA<*^+5-x+H@E}imjdM z_!t#b#7b;YL_jN}B|0h~Lm>e|5)zUS$$QBr`?$~3@7`St(_w+|NB`oRIeT{RJ@=g7 z`F-E_JKtU4vR$^zHg@Cl4g_CV-u2c^xA!gIbjRK@4zP2L>#F;S$J}|>X5+JEccdGW z&T4D9bTQ-3IqCA7cdq(uT|OcV!PR?|yd;(mL7aTVcML^{^k=Gjxd_DJXd&i~^lkKUkZY`r2SR&RN_Y9r2L z=iJ3c&+xa;4k#GnCTe5(;&`uX=9;PAnMLzv|6%p+s-_w48{Xe~>w~>n!Pfg@Zh;AY zZ=R>LyP7Lz(Yu@&3e(vj&aeMyG?t!_QtVEok-Mx5vbP?Q_C!N+BR*$2iskq z%$hgg!Jh+ueB;i=?HOCJa{fxVD+$oJUlRZ0Q%-QvOw=Hxo;ES`dOhO1o8iB2Dgrl= z=eyp5d1$BE*TL5nKN5ce4%ZhpG2IPw(vsp=2E_$`S44ayOIVt-0Z-n#3i8yS0ws47 z7MVtAsixC%)N|F2K&QE@vfx`Z5$;JI8cQJ?oB|HhNSk!6EZelF;doP9`j+?}; zSG!-cT+K!C`0+jT!0a&rwC$bB$K$tL)kB#&pLRcl!BY`z-`s$f#$LomDef4<#2*x3 z*|UowNUpO0692^5`X_hb=)RNS7KbN8LZ~ty3-7EXZOsO9Cc!(>TM`Z%s+3_2r6($l z)zv|q-=ZAJy*fA(* zD*&g348;YPL@^{$tVt}{6N^q0SZX$I%N&8Sduk@R+o0Y^_7+K!aax6}YTyHd7(U!) ztlX-Uy!_Q@-??z4b+KF4W^tL(S{zKJjI`nejsVd$DAcZH0mT)D;kb^j9u+zf zI(~8nxjf@6kicM96dkQGxLpjTc{2QN7i}~JHU*yRahSA5p2w_6ha)XO-Qrocmn@P6 z!K8$+m@~0PF01>rABWpixD`&GWrz{}6@QwHtX$c7cBogyGb>u)BaP;^XDM+j%RE?8 zolAtX|8AD+DupMvRVz4VfVO8$gC$)-vBL-J!-s}3Lb)20Ehm2MVvExvmdWTGN`LC51;`B+HpqPzZC@0K z0!?(l7RUk~yL%kPAPvf-YXOoMy5?wdD(76Z;EX9AC+09hlTfj-s4^4iCoN787}?fL zlfYRNA|hgOYcL%SA>9qt5IS^<8G~5iRGm;zQcDew>nSZ3lCCEfU^TkWI(0vuZ`p)B=9c>!?yR4Ju`uWf=KU)++D+~<>2x#bWD^OWBQE_{!MiEnu})e%ByEIG+8%yM@b%ZIu*D`kwQrU4=qM|2>ax)&tnIm;5304TUb+! z#Sc_s-_Zo#dAk#qT|?Mo?Po}u>^ZokBYrA@_G}TM_{rmHhSFm;_j<>~;G8el{!!Dl z;^pqAu_$939c2dTph{(*t$&oQLJFK+ZLyR{+bkxiSZx_am};SdP#HS9axkRl6O#tf za~x6G#A!;B2nJEmwik8MJr(}G)((PlY)k;Vy8FM#$WZPzg$`@jqvbQwGcS?gVo{=< zCr=84GR2Zo0F$pxn|3m++k73$%a-DBQxN|+%AgWx7Rp8_D~h~u6oIIUt%ZJMqYY)J zqom=wZ+`*So(so$-^8+Rt;^h1`QTkHckJarp@KkAb`E`+#9DCKZgwXNS0PnRljx2R z;P>i*T_2C4lw4Yv?Z(iE48bl-M$rVF*kMQ?rqeU~Ma~i4;vyNLB8Gy1K^m$d zp_;^=fmp-_r}N%0o*f=7cx+0!F$3DjdPX}~^=|WajFrL0dCPpheD51>2y;D|-kQLx zPkoCz2>ZVD-YYS6mD?|rxV;iwHj^&f)yz4UolLg41K89}Xe3iA0Srf^wt*2m^1}(S zZKwtBeDRuKJgVKEh>Lrxo;q?k9gehFeEQT$s{wYsgw;jg(yqTP zG|09XmqG_kit8=d}=={_O8#{6p!o eUAD`13HBdfcShY@j + android:background="@color/background"> + android:textAppearance="@style/app_logo" /> @@ -50,20 +50,30 @@ - + + + android:layout_marginTop="80dp" + android:layout_marginBottom="80dp" + tools:listitem="@layout/history_item" /> diff --git a/Android/app/src/main/res/layout-sw720dp/history_item.xml b/Android/app/src/main/res/layout-sw720dp/history_item.xml new file mode 100644 index 000000000..78e1150ad --- /dev/null +++ b/Android/app/src/main/res/layout-sw720dp/history_item.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Android/app/src/main/res/layout/activity_main.xml b/Android/app/src/main/res/layout/activity_main.xml index f12f29aa0..52b01d271 100644 --- a/Android/app/src/main/res/layout/activity_main.xml +++ b/Android/app/src/main/res/layout/activity_main.xml @@ -1,12 +1,12 @@ + android:background="@color/background"> + android:textAppearance="@style/app_logo" /> @@ -50,36 +49,30 @@ - - -