Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

お気に入り画面の新着タブのRecyclerViewとCoordinatorLayout実装 #20

Merged
merged 26 commits into from
Oct 16, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
c3bc24f
FavoriteFragmentにCoordinatorLayoutを適用
nemo-855 Oct 11, 2021
a4db18f
FavoriteNewItemViewModelを作成
nemo-855 Oct 11, 2021
f6f4786
FavoriteNewItemFragmentのView用のEntity作成
nemo-855 Oct 11, 2021
fa095a0
FavoriteNewItemFragment用のBindableItemを継承したViewEntity作成
nemo-855 Oct 11, 2021
05c60ed
favorite_new_item_no_brand_registered作成
nemo-855 Oct 11, 2021
e9ebee1
favorite_new_item_now_popular作成
nemo-855 Oct 11, 2021
24f01fd
favorite_new_item_item_cell作成
nemo-855 Oct 11, 2021
00303bd
FavoriteNewItemFragmentにリストを表示するロジック実装
nemo-855 Oct 11, 2021
d082054
favorite_new_item_item_cell微調整
nemo-855 Oct 11, 2021
7493d3d
FavoriteNewItemFragmentのRecyclerViewにdividerをつけた
nemo-855 Oct 11, 2021
78db7bc
FavoriteNewItemFragmentのRecyclerViewのエッジエフェクト無効
nemo-855 Oct 11, 2021
6597b49
Merge branch 'main' of https://github.com/iroha-168/AndroidUITrain in…
nemo-855 Oct 11, 2021
e63e0ea
FavoriteFragmentにswipeRefreshLayoutを適用
nemo-855 Oct 13, 2021
734af97
CoordinatorLayout部分数字指定で完成
nemo-855 Oct 15, 2021
48f3363
ViewModelに書くべきでない処理をGroupieCustomAdapterに移行
nemo-855 Oct 15, 2021
931691d
FavoriteNewItemFragmentで無駄にbindingをFragmentのメンバ関数にしていた部分を修正した
nemo-855 Oct 15, 2021
bf47b07
merge main into apply_coordinator_layout_favorite_fragment
nemo-855 Oct 15, 2021
d71ff43
ブランドのリスト周りのロジックをAPIを叩いて持ってきた想定に書き換えた
nemo-855 Oct 16, 2021
7cf2ab4
FavoriteItemCellの引数名を修正した
nemo-855 Oct 16, 2021
4075645
BrandItem変数名修正
nemo-855 Oct 16, 2021
b47e41a
fragment_favorite_new_itemの内部をRecyclerViewのみにした
nemo-855 Oct 16, 2021
80eeef9
fragment_favoriteの不要なlayout_behavior削除
nemo-855 Oct 16, 2021
102c9c7
fragment_favorite coordinatorLayout周りの高さ修正
nemo-855 Oct 16, 2021
1ecb962
favorite_new_item_item_cellの不要なmargin削除
nemo-855 Oct 16, 2021
1d7b4bf
FavoriteItemCellで動的に左右のmarginをつけるようにした
nemo-855 Oct 16, 2021
76c399e
favorite_new_item_item_cell margin修正
nemo-855 Oct 16, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,7 @@ dependencies {

// Coil
implementation("io.coil-kt:coil:1.4.0")

//swiperefreshlayout
implementation ("androidx.swiperefreshlayout:swiperefreshlayout:1.2.0-alpha01")
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import androidx.viewpager2.adapter.FragmentStateAdapter
import com.google.android.material.tabs.TabLayoutMediator
import com.nemo.androiduitraining.R
import com.nemo.androiduitraining.databinding.FragmentFavoriteBinding
import dagger.hilt.android.AndroidEntryPoint

@AndroidEntryPoint
class FavoriteFragment : Fragment(R.layout.fragment_favorite) {
private var _binding: FragmentFavoriteBinding? = null
private val binding: FragmentFavoriteBinding
Expand Down
Original file line number Diff line number Diff line change
@@ -1,29 +1,83 @@
package com.nemo.androiduitraining.view.fragment.favorite

import android.content.res.Resources
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.viewbinding.ViewBinding
import com.nemo.androiduitraining.R
import com.nemo.androiduitraining.databinding.FragmentFavoriteNewItemBinding
import com.nemo.androiduitraining.view.fragment.favorite.entity.FavoriteItemCell
import com.nemo.androiduitraining.view.fragment.favorite.entity.FavoriteNoBrandRegistered
import com.nemo.androiduitraining.view.fragment.favorite.entity.FavoriteNowPopular
import com.nemo.androiduitraining.viewModel.favorite.FavoriteNewItemViewModel
import com.xwray.groupie.GroupieAdapter
import com.xwray.groupie.viewbinding.BindableItem
import dagger.hilt.android.AndroidEntryPoint

@AndroidEntryPoint
class FavoriteNewItemFragment : Fragment(R.layout.fragment_favorite_new_item) {
companion object {
fun newInstance() = FavoriteNewItemFragment()
}

private var _binding: FragmentFavoriteNewItemBinding? = null
private val binding: FragmentFavoriteNewItemBinding
get() = _binding!!
private val viewModel: FavoriteNewItemViewModel by viewModels()

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
_binding = FragmentFavoriteNewItemBinding.bind(view)
val binding = FragmentFavoriteNewItemBinding.bind(view)

val adapter = GroupieCustomAdapter()
setupRecycler(binding, adapter)
fetchBrandsItemAndUpdateList(adapter)
}

private fun setupRecycler(binding: FragmentFavoriteNewItemBinding, adapter: GroupieCustomAdapter) {
val layoutManager = LinearLayoutManager(requireContext())
Naoki-Hidaka marked this conversation as resolved.
Show resolved Hide resolved

binding.favoriteNewItemRecycler.also {
it.layoutManager = layoutManager
it.addItemDecoration(createRecyclerDiver(layoutManager))
it.adapter = adapter
}
}

private fun createRecyclerDiver(layoutManager: LinearLayoutManager): DividerItemDecoration {
val dividerDrawable = ContextCompat.getDrawable(requireContext(), R.drawable.fragment_favorite_new_item_divider)
return DividerItemDecoration(requireContext(), layoutManager.orientation).apply {
if (dividerDrawable != null) {
this.setDrawable(dividerDrawable)
}
}
}

private fun fetchBrandsItemAndUpdateList(adapter: GroupieCustomAdapter) {
viewModel.brandLD.observe(viewLifecycleOwner) { brands ->
adapter.updateList(brands)
}
viewModel.fetchBrandItems()
}

override fun onDestroyView() {
super.onDestroyView()
_binding = null
private class GroupieCustomAdapter : GroupieAdapter() {
private var itemList: List<BindableItem<out ViewBinding>> = listOf()

private val defaultViewList = mutableListOf(
FavoriteNoBrandRegistered(),
FavoriteNowPopular()
)

fun updateList(brandsList: List<FavoriteNewItemViewModel.BrandItem>) {
this.itemList = defaultViewList + brandsList.map {
FavoriteItemCell(
brandName = it.name,
brandNameJapanese = it.nameJapanese
)
}
update(this.itemList)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.nemo.androiduitraining.view.fragment.favorite.entity

import android.content.res.Resources
import android.view.View
import android.view.ViewGroup
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import com.nemo.androiduitraining.R
import com.nemo.androiduitraining.databinding.FavoriteNewItemItemCellBinding
import com.xwray.groupie.viewbinding.BindableItem

class FavoriteItemCell(
private val brandName: String,
private val brandNameJapanese: String
) : BindableItem<FavoriteNewItemItemCellBinding>() {
override fun bind(viewBinding: FavoriteNewItemItemCellBinding, position: Int) {
viewBinding.itemNameTv.text = brandName
viewBinding.brandTv.text = brandNameJapanese
}

override fun getLayout() = R.layout.favorite_new_item_item_cell

override fun initializeViewBinding(view: View): FavoriteNewItemItemCellBinding {
return FavoriteNewItemItemCellBinding.bind(view)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.nemo.androiduitraining.view.fragment.favorite.entity

import android.view.View
import com.nemo.androiduitraining.R
import com.nemo.androiduitraining.databinding.FavoriteNewItemNoBrandRegisteredBinding
import com.xwray.groupie.viewbinding.BindableItem

class FavoriteNoBrandRegistered : BindableItem<FavoriteNewItemNoBrandRegisteredBinding>(){
override fun bind(viewBinding: FavoriteNewItemNoBrandRegisteredBinding, position: Int) {

}

override fun getLayout() = R.layout.favorite_new_item_no_brand_registered

override fun initializeViewBinding(view: View): FavoriteNewItemNoBrandRegisteredBinding {
return FavoriteNewItemNoBrandRegisteredBinding.bind(view)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.nemo.androiduitraining.view.fragment.favorite.entity

import android.view.View
import com.nemo.androiduitraining.R
import com.nemo.androiduitraining.databinding.FavoriteNewItemNowPopularBinding
import com.xwray.groupie.viewbinding.BindableItem

class FavoriteNowPopular : BindableItem<FavoriteNewItemNowPopularBinding>() {
override fun bind(viewBinding: FavoriteNewItemNowPopularBinding, position: Int) {

}

override fun getLayout() = R.layout.favorite_new_item_now_popular

override fun initializeViewBinding(view: View): FavoriteNewItemNowPopularBinding {
return FavoriteNewItemNowPopularBinding.bind(view)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.nemo.androiduitraining.viewModel.favorite

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.viewbinding.ViewBinding
import com.nemo.androiduitraining.view.fragment.favorite.entity.FavoriteItemCell
import com.nemo.androiduitraining.view.fragment.favorite.entity.FavoriteNoBrandRegistered
import com.nemo.androiduitraining.view.fragment.favorite.entity.FavoriteNowPopular
import com.xwray.groupie.viewbinding.BindableItem
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject

@HiltViewModel
class FavoriteNewItemViewModel @Inject constructor() : ViewModel() {
private val _brandsLD = MutableLiveData<List<BrandItem>>()
val brandLD: LiveData<List<BrandItem>>
get() = _brandsLD

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

せっかくなのでAPIから返ってきた想定でデータはこっちで持っておきましょうか

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

あと多分お気に入りのブランドがあるかないかで表示が結構変わるのでそこも実装してもらえると 🙏

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

APIからでーた持ってきた前提に修正しました!!

お気に入りのブランドがあるところはまた長くなりそうなので別のプルリクであげます!

fun fetchBrandItems() {
val brandsList = mutableListOf<BrandItem>()
for (i in 0..29) {
brandsList.add(
BrandItem("ほげほげ", "フガフガ")
)
}
_brandsLD.postValue(brandsList)
}

data class BrandItem(
val name: String,
val nameJapanese: String
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<size android:height="2dp" />
<solid android:color="@color/light_gray" />
</shape>
10 changes: 10 additions & 0 deletions app/src/main/res/drawable/ic_baseline_favorite_24.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M12,21.35l-1.45,-1.32C5.4,15.36 2,12.28 2,8.5 2,5.42 4.42,3 7.5,3c1.74,0 3.41,0.81 4.5,2.09C13.09,3.81 14.76,3 16.5,3 19.58,3 22,5.42 22,8.5c0,3.78 -3.4,6.86 -8.55,11.54L12,21.35z"/>
</vector>
11 changes: 11 additions & 0 deletions app/src/main/res/drawable/ic_baseline_keyboard_arrow_right_24.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal"
android:autoMirrored="true">
<path
android:fillColor="@android:color/white"
android:pathData="M8.59,16.59L13.17,12 8.59,7.41 10,6l6,6 -6,6 -1.41,-1.41z"/>
</vector>
83 changes: 83 additions & 0 deletions app/src/main/res/layout/favorite_new_item_item_cell.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/side_margin_16"
android:layout_marginEnd="@dimen/side_margin_16"
xmlns:app="http://schemas.android.com/apk/res-auto">

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="h,5:1">

<androidx.constraintlayout.widget.Guideline
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MaterialDesign的には左右16dpのmarginなんですが、16dpだと大きかったですか?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

純粋に見逃してました!🙏

コンポーネントに直接marginつけるのよくないかもと思い直したので、FavoriteItemCell内部でbindのタイミングで動的に左右に16dpのmarginをセットするようにしました!

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

コンポーネントに直接marginつけるのよくないかもと思い直したので

お?これはどんな理由があります?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

純粋に同じレイアウト再利用するときに画面によってマージンが変わるかもしれないからです!ただ今回はそこまで入らない気がしますが笑

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

基本的には左右16dpのマージンは変わらないのと、もしマージンが違うデザインだった場合、もはやそれは違うitemなんじゃないかなとは思いますね

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

確かにそれもそうですね!修正しときます!ありがとうございます🙏

android:id="@+id/guideline_vertical1"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintGuide_percent="0.1"
android:orientation="vertical"/>

<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline_vertical2"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintGuide_percent="0.9"
android:orientation="vertical"/>

<ImageView
android:id="@+id/favorite_image"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@id/guideline_vertical1"
android:src="@drawable/ic_baseline_favorite_24"
android:layout_margin="8dp"
app:tint="@color/text_gray"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintHorizontal_bias="1"
android:contentDescription="@string/image"/>

<TextView
android:id="@+id/item_name_tv"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintStart_toStartOf="@id/guideline_vertical1"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="@id/guideline_vertical2"
app:layout_constraintBottom_toTopOf="@id/brand_tv"
android:gravity="start|bottom"
android:textColor="@color/black"
app:layout_constraintHorizontal_bias="1"/>
<TextView
android:id="@+id/brand_tv"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintStart_toStartOf="@id/guideline_vertical1"
app:layout_constraintTop_toBottomOf="@id/item_name_tv"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@id/guideline_vertical2"
android:gravity="start|top"
android:textColor="@color/text_gray"
app:layout_constraintHorizontal_bias="1"/>

<ImageView
android:id="@+id/arrow_image"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintStart_toStartOf="@id/guideline_vertical2"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

startなしで、endの制約をguideline_vertical2にすればこのImageViewのmarginはいらないのでは?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

コンポーネントに直接marginつけるのよくないかもと思い直したので、FavoriteItemCell内部でbindのタイミングで動的に左右に16dpのmarginをセットするようにしました!

app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:src="@drawable/ic_baseline_keyboard_arrow_right_24"
app:tint="@color/text_gray"
app:layout_constraintHorizontal_weight="1"
android:contentDescription="@string/image" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
57 changes: 57 additions & 0 deletions app/src/main/res/layout/favorite_new_item_no_brand_registered.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?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"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="h,5:3"
android:background="@color/light_gray">

<ImageView
android:id="@+id/no_brand_image"
android:layout_width="0dp"
android:layout_height="0dp"
android:src="@drawable/ic_android_black_24dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toTopOf="@id/no_brand_tv_main"
android:contentDescription="@string/image"/>
<TextView
android:id="@+id/no_brand_tv_main"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/no_brand_image"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toTopOf="@id/no_brand_tv_sub"
android:text="@string/no_favorite_brand"
android:gravity="center"
android:textColor="@color/black"
android:textStyle="bold"
android:textSize="16sp"
android:layout_marginBottom="16dp"/>

<TextView
android:id="@+id/no_brand_tv_sub"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/no_brand_tv_main"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:text="@string/no_brand_sub_text"
android:gravity="center"
android:textColor="@color/black"
android:layout_marginBottom="32dp"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>