iT邦幫忙

2021 iThome 鐵人賽

DAY 13
0

今天我們要做的就是,當使用者一進到我們的App時,就可以看到除了自己上架的其他訊息!

先上圖
https://ithelp.ithome.com.tw/upload/images/20210928/20138017fJ8zxf2tZk.png

1.建立RecyclerView

我們這次做的RecylcerView跟上次做出小小的區別,我們這次做的比較有質感一點

我們首先要建立Adapter,而基本上跟上一次的HomeAdapter一樣,要注意的是我們在onCreateViewHolder的地方有換寫法,可以讓我們Recyclerview的item可以調間距。

class DashboardAdapter(private val fragment: DashboardFragment): ListAdapter<Invitation, DashboardAdapter.DashboardViewHolder>(DiffCallback){

	
    class DashboardViewHolder(val binding: DashboardInvitationItemListBinding): RecyclerView.ViewHolder(binding.root){
        fun bind(item: Invitation){
            binding.invitation = item
            binding.executePendingBindings()
            Constant.loadPetImage(item.pet_image,binding.ivDashboardInvitationItemListImage)

        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DashboardViewHolder {
        val binding: DashboardInvitationItemListBinding = DataBindingUtil.inflate(LayoutInflater.from(parent.context),
            R.layout.dashboard_invitation_item_list,parent,false)
        return DashboardViewHolder(binding)
    }

    override fun onBindViewHolder(holder: DashboardViewHolder, position: Int) {

            val model = getItem(position)
            holder.bind(model)
						//這邊一樣設定OnClick事件,並把我們選擇的item傳到viewModel
            holder.itemView.setOnClickListener{
                fragment.addSelectedInvitationToViewModel(model)
            }
    }

		//會幫我們判斷list是否一樣
    companion object DiffCallback: DiffUtil.ItemCallback<Invitation>(){
        override fun areItemsTheSame(oldItem: Invitation, newItem: Invitation): Boolean {
            return oldItem === newItem

        }

        override fun areContentsTheSame(oldItem: Invitation, newItem: Invitation): Boolean {
            return oldItem.id == oldItem.id
        }
    }

}

這時候我們可以看到紅字,也就是我們傳進DashboardFragment裡面的funtion!

所以我們就要在Fragment裡面新增以下

原則上這邊就跟我們在HomeFragment裡面做的點擊事件一樣,把我們的livedata資料更新,讓我們在InvitationDetailFragment觀測Livedata

fun addSelectedInvitationToViewModel(invitation: Invitation) {
    matchingViewModel.addSelectedInvitationToLiveData(invitation)
    nav.navigate(R.id.action_navigation_dashboard_to_invitationDetailFragment)

  }

★別忘了要在navigation裡面連連看喔,不然我們沒辦法透過id來導航。
接下來來實例化我們的Adapter,並且在我們的onCreateView呼叫

private fun setAdapter() {
//指定我們的layoutManager為GridLayoutManager,第一個參數 context,第二個則是一行幾個item 
	  binding.rvDashboardFragment.layoutManager =   GridLayoutManager(requireContext(), 2)
    dashboardAdapter = DashboardAdapter(this)
//讓我們item有新增或減少時,item的size不會改變,讓RecyclerView不用重新計算大小
    binding.rvDashboardFragment.setHasFixedSize(true)
    binding.rvDashboardFragment.adapter = dashboardAdapter

  }

LayoutManager,我們可以用以下方是來調整排版

  • LinearLayoutManager,就是水平或是垂直排版
  • GridLayoutManager,格狀,也就是我們這次要用的效果,可以自訂一行幾個item
  • StaggeredGridLayoutManager,瀑布,適合各種不同size的item

★ 對於時做有興趣的小夥伴們可以參考這篇文章

https://givemepass.blogspot.com/2016/09/recyclerview-layoutmanager.html

在過來就是我們的Layout啦!

別忘了我們的recyclerview要有兩個layout

  • 本身在UI層(Activity,Fragment),要新增RecyclerView所佔的範圍
  • ItemView的layout

所以我們先在fragment_dashboard_xml 新增以下,讓它範圍佔好占滿

<androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rv_dashboard_fragment"
        android:layout_width="match_parent"
				android:layout_marginTop="20dp"
        android:layout_height="match_parent">

    </androidx.recyclerview.widget.RecyclerView>

因為我們這次會需要用到CardView,顧名思義它就是類似卡片的效果,看起來會比較立體
我們要先去gradle新增

implementation "androidx.cardview:cardview:1.0.0"

主要用法就是把它包在view外面,可以直接在cardView設定以下

  • cardBackgroundColor 設定cardview的背景色
  • cardCornerRadius 設定cardview的圓角大小
  • cardElevation 設定cardview陰影的大小,你要看起來越立體,就調越高
  • cardMaxElevation 設定cardview陰影的最大高度

★ 參考文章:https://ithelp.ithome.com.tw/articles/10249805

dimen

	<dimen name="dashboard_cardView_radius">8dp</dimen>
    <dimen name="dashboard_cardView_margin">8dp</dimen>
    <dimen name="dashboard_image_height">100dp</dimen>

color

    <color name="item_background">#ebf6f8</color>

新增dashboard_invitation_item_list.xml

<?xml version="1.0" encoding="utf-8"?>


<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

		//一樣我們在這邊設定databinding,讓我們在Adapter綁定
    <data>
        <variable
            name="invitation"
            type="com.example.petsmatchingapp.model.Invitation" />
    </data>

    <androidx.cardview.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:cardBackgroundColor="@color/item_background"
        android:layout_margin="@dimen/dashboard_cardView_margin"
        app:cardCornerRadius="@dimen/dashboard_cardView_radius">




<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">



    <ImageView
        android:id="@+id/iv_dashboard_invitation_item_list_image"
        android:layout_width="match_parent"
        android:layout_height="@dimen/dashboard_image_height"
        android:scaleType="center">

    </ImageView>



        <com.example.petsmatchingapp.utils.JFTextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{@string/home_fragment_pet_type(invitation.pet_type,invitation.pet_type_description)}"/>


        <com.example.petsmatchingapp.utils.JFTextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@{@string/home_fragment_pet_place(invitation.area,invitation.date_place)}"/>

        <com.example.petsmatchingapp.utils.JFTextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{@string/home_fragment_pet_time(invitation.date_time)}"/>


</LinearLayout>

    </androidx.cardview.widget.CardView>

</layout>

2.從FireStore拿到所有的邀約

來到 MatchingViewModel新增,一樣透過新增到livedata的方式讓我們UI層可以觀察
我們希望我們的DashboardFragment裡面的資料不要看到自己PO出來的資料,這樣才不會導致自己約自己的荒謬行為!


//設定我們的livedata讓我們好觀察
private val _allInvitationList =  MutableLiveData<List<Invitation>>()
val allInvitationList: LiveData<List<Invitation>>
get() = _allInvitationList



fun getAllInvitation(userID: String,fragment: DashboardFragment){
        Firebase.firestore.collection(Constant.INVITATION)
	        //我們直接用get拿到所有資料,之後再來篩
            .get()
            .addOnSuccessListener {
                val list = mutableListOf<Invitation>()
                for (i in it.documents){
                    val model = i.toObject(Invitation::class.java)
//我們這時候要確認我們的model的user_id跟我們currentUserId是不一致的			
                    if (model != null && model.user_id != userID){
                        list.add(model)
                    }
                }
                _allInvitationList.postValue(list)
            }
            .addOnFailureListener {
                fragment.getAllInvitationFail(it.toString())
            }
    }

一樣我們可以看到幾個紅字,也就是我們要新增我們的get失敗,回到我們的Fragment

fun getAllInvitationFail(e: String) {
    showSnackBar(e, true)
  }

並且在onCreateView呼叫它,在最初的時候我們就先呼叫!

accountViewModel.getCurrentUID()?.let { matchingViewModel.getAllInvitation(it,this) }

最後在觀測我們的allInvitationList,如果有變更的時候,就把list丟進我們的adapter

matchingViewModel.allI![https://ithelp.ithome.com.tw/upload/images/20210928/201380171J3BZgpzoE.png](https://ithelp.ithome.com.tw/upload/images/20210928/201380171J3BZgpzoE.png)nvitationList.observe(viewLifecycleOwner, Observer {
      dashboardAdapter.submitList(it)
    })

別忘了我們先在如果點進InvitationDetailFragment的時候會把ActionBar跟bottomNavigation隱藏,所以我們要在onResume呼叫。

if (requireActivity().findViewById<BottomNavigationView>(R.id.nav_view).visibility == View.GONE) {
      requireActivity().findViewById<BottomNavigationView>(R.id.nav_view).visibility =
        View.VISIBLE
    }

★切記不能在onCreateView裡面呼叫喔! 因為在onCreateView是在Fragment初次創建時調用。但此刻Activity還沒有創建完成,因為我們的Fragment也是Activity創建的一部分。所以無法獲取Activity的一些資源

Fragment生命週期對應Activity
https://ithelp.ithome.com.tw/upload/images/20210928/20138017o7VRYVIHwl.png

參考文章&圖片來源:https://www.aiwalls.com/android軟體開發教學/08/23989.html

今天就先這樣啦! 明天會新增一些篩選的選單,讓我們當今天資料比較多的時候,可以讓user去快速找到想要的約散!

成品!!
day13.finish


上一篇
【day12】InvitationDetailFragment
下一篇
【day14】 Fab X 跳頁Animation
系列文
30天建立寵物約散App-Android新手篇30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言