今天要來補一個大坑(`▽´)

之前曾做過一篇講述RecycleView的文章

如果還不會RecycleView或者是還不熟悉RecycleView用法的人可以參考這篇喔~

2020更新:

至今本網誌已寫五篇關於RecyclerView的文章,歡迎參考

碼農日常-『Android studio』基本RecyclerView用法

碼農日常-『Android studio』基本RecyclerView 用法-2 基本版下拉更新以及點擊事件

碼農日常-『Android studio』基本RecyclerView 用法-3 RecyclerView上下滑動排序與側滑刪除(RecyclerView Swipe)

碼農日常-『Android studio』基本RecyclerView 用法-4 左滑顯示Button Menu

碼農日常-『Android studio』進階RecyclerView 用法-5 RecyclerView item混合介面

上篇中講述了RecycleView的架構以及基本用法

今天就要來講述RecycleView的另外兩項常用功能

1.點擊事件

2.下拉更新

OK,先上範例

然後一樣是GitHub:

https://github.com/thumbb13555/SimpleRecycleViewExample

功能描述:

1.點擊物件後,以Toast顯示該項目之平均分

2.到頂時,往下拉則再跑一次(更新)分數計算

OK本文開始


RecycleView跟ListVIew不一樣的是,RecycleView的點擊事件並非如同ListView可直接以外部覆寫的方法操作

RecycleView必須得先在ViewHolder內宣告一個View,然後再從onBindViewHolder內做事件點擊

好啦廢話太多也沒什麼意義,直接上程式

public class mainActivity extends Appcompatactivity{ 
.
.
.


private class MyListAdapter extends RecyclerView.Adapter<MyListAdapter.ViewHolder>{


        class ViewHolder extends RecyclerView.ViewHolder{
            private TextView tvId,tvSub1,tvSub2,tvAvg;
            private View mView;

            public ViewHolder(@NonNull View itemView) {
                super(itemView);
                tvId = itemView.findViewById(R.id.textView_Id);
                tvSub1 = itemView.findViewById(R.id.textView_sub1);
                tvSub2 = itemView.findViewById(R.id.textView_sub2);
                tvAvg  = itemView.findViewById(R.id.textView_avg);
                mView  = itemView;
            }
        }
        @NonNull
        @Override
        public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            View view = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.recycle_item,parent,false);
            return new ViewHolder(view);
        }

        @Override
        public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
            int avgS = Integer.parseInt(arrayList.get(position).get("Avg"));
            if (avgS>=80){
                holder.tvId.setBackgroundColor(getColor(R.color.green_TOKIWA));
            }else if (avgS<80 &&avgS>=60){
                holder.tvId.setBackgroundColor(getColor(R.color.blue_RURI));
            }else if(avgS<60 &&avgS>=40){
                holder.tvId.setBackgroundColor(getColor(R.color.yellow_YAMABUKI));
            }else {
                holder.tvId.setBackgroundColor(getColor(R.color.red_GINSYU));
            }
            holder.tvId.setText(arrayList.get(position).get("Id"));
            holder.tvSub1.setText(arrayList.get(position).get("Sub1"));
            holder.tvSub2.setText(arrayList.get(position).get("Sub2"));
            holder.tvAvg.setText(arrayList.get(position).get("Avg"));

            holder.mView.setOnClickListener((v)->{
                Toast.makeText(getBaseContext(),holder.tvAvg.getText(),Toast.LENGTH_SHORT).show();
            });

        }

        @Override
        public int getItemCount() {
            return arrayList.size();
        }
    }
}

範例中紅字的部分就是這次點擊事件的範例中新增的部分

可以看見就是簡單的三步驟

1.在class ViewHolder extends RecyclerView.ViewHolder{...底下命一個變數,資料型態為View

2.把這個View跟底下ViewHolder的View綁再一起

3.在onBindViewHolder內宣告setOnClickListener點擊事件

4.完成(・ω・)b

 

不知解釋至此,有理解了嗎XDDD

好啦既然這麼簡單就趕快實作ㄅ (⌐■_■)


OK接下來是下拉事件

下拉事件實際上直接就有現成的可以用了(・ω・`)………..

只要你不要太挑惕...基本上也很夠用

這個套件叫做SwipeRefreshLayout

效果如同上面的那個Gif...非常地陽春

此外我之前在找資料時,發現一位大大直接全部手寫

https://juejin.im/post/5a22af7a6fb9a0450e75ee61

有機會我也會試試看的C≡(・。・C≡)≡≡≡

OK回歸正題,關於這個SwipeRefreshLayout我們來看看官方範例

https://developer.android.com/training/swipe

以及官方文檔

https://developer.android.com/reference/android/support/v4/widget/SwipeRefreshLayout

其實直接參照官方範例就可以了...XD

OK從範例中可以看到步驟有二

1.在Layout中加入SwipeRefreshLayout

2.在程式碼中呼叫 .setOnRefreshListener

範例在此

https://developer.android.com/training/swipe/respond-refresh-request#RespondRefresh

好實作開始。


首先我們要在Layout中加入SwipeRefreshLayout元件

樹狀結構長這樣

基本上大重點就是只要把它包在RecycleView的外圍即可

看一下Xml Code

<?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"
    android:background="#4B5A6D"
    tools:context=".MainActivity">

    <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/refreshLayout"

        >
        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recycleview"
            android:layout_width="0dp"
            android:layout_height="0dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

    </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>


</androidx.constraintlayout.widget.ConstraintLayout>

網路上有些資料是用Androidx以前的套件寫的,2019的現在用Androidx套件的話直接打

<androidx.swiperefreshlayout.widget.SwipeRefreshLayout

即可。

 

這時候可以執行看看,當你下拉列表時就會有反應囉(●・ω・)b

只是他的轉圈圈不會消失而已XD

要消滅轉圈圈,就得呼叫這個方法

swipeRefreshLayout.setRefreshing(false);

 

OK,接下來回到Code

先PO一下全部

package com.example.simplerecycleviewexample;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;

import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Random;

public class MainActivity extends AppCompatActivity {
    String TAG = "mExample";
    RecyclerView mRecyclerView;
    MyListAdapter myListAdapter;
    SwipeRefreshLayout swipeRefreshLayout;
    ArrayList<HashMap<String,String>> arrayList = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //製造資料
        makeData();

        //設置RecycleView
        mRecyclerView = findViewById(R.id.recycleview);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
        mRecyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
        myListAdapter = new MyListAdapter();
        mRecyclerView.setAdapter(myListAdapter);
        //下拉刷新
        swipeRefreshLayout = findViewById(R.id.refreshLayout);
        swipeRefreshLayout.setColorSchemeColors(getResources().getColor(R.color.blue_RURI));
        swipeRefreshLayout.setOnRefreshListener(()->{
            arrayList.clear();
            makeData();
            myListAdapter.notifyDataSetChanged();
            swipeRefreshLayout.setRefreshing(false);

        });
    }//onCreate

    private void makeData() {
        for (int i = 0;i<30;i++){
            HashMap<String,String> hashMap = new HashMap<>();
            hashMap.put("Id","座號:"+String.format("%02d",i+1));
            hashMap.put("Sub1",String.valueOf(new Random().nextInt(80) + 20));
            hashMap.put("Sub2",String.valueOf(new Random().nextInt(80) + 20));
            hashMap.put("Avg",String.valueOf(
                    (Integer.parseInt(hashMap.get("Sub1"))
                    +Integer.parseInt(hashMap.get("Sub2")))/2));

            arrayList.add(hashMap);
        }
    }

    private class MyListAdapter extends RecyclerView.Adapter<MyListAdapter.ViewHolder>{


        class ViewHolder extends RecyclerView.ViewHolder{
            private TextView tvId,tvSub1,tvSub2,tvAvg;
            private View mView;

            public ViewHolder(@NonNull View itemView) {
                super(itemView);
                tvId = itemView.findViewById(R.id.textView_Id);
                tvSub1 = itemView.findViewById(R.id.textView_sub1);
                tvSub2 = itemView.findViewById(R.id.textView_sub2);
                tvAvg  = itemView.findViewById(R.id.textView_avg);
                mView  = itemView;
            }
        }
        @NonNull
        @Override
        public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            View view = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.recycle_item,parent,false);
            return new ViewHolder(view);
        }

        @Override
        public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
            int avgS = Integer.parseInt(arrayList.get(position).get("Avg"));
            if (avgS>=80){
                holder.tvId.setBackgroundColor(getColor(R.color.green_TOKIWA));
            }else if (avgS<80 &&avgS>=60){
                holder.tvId.setBackgroundColor(getColor(R.color.blue_RURI));
            }else if(avgS<60 &&avgS>=40){
                holder.tvId.setBackgroundColor(getColor(R.color.yellow_YAMABUKI));
            }else {
                holder.tvId.setBackgroundColor(getColor(R.color.red_GINSYU));
            }
            holder.tvId.setText(arrayList.get(position).get("Id"));
            holder.tvSub1.setText(arrayList.get(position).get("Sub1"));
            holder.tvSub2.setText(arrayList.get(position).get("Sub2"));
            holder.tvAvg.setText(arrayList.get(position).get("Avg"));

            holder.mView.setOnClickListener((v)->{
                Toast.makeText(getBaseContext(),holder.tvAvg.getText(),Toast.LENGTH_SHORT).show();
            });

        }

        @Override
        public int getItemCount() {
            return arrayList.size();
        }
    }


}

來看一下下拉刷新的部分

也就是紅字部分

swipeRefreshLayout = findViewById(R.id.refreshLayout);
swipeRefreshLayout.setColorSchemeColors(getResources().getColor(R.color.blue_RURI))

swipeRefreshLayout方法內,setColorSchemeColors可以設定圈圈的顏色喔~

接下來來看刷新的部分

swipeRefreshLayout.setOnRefreshListener(()->{
            arrayList.clear();
            makeData();
            myListAdapter.notifyDataSetChanged();
            swipeRefreshLayout.setRefreshing(false);

        });

因為我們的目的是要更新列表

但是說穿了不過就是重置罷了XD

因此我們把輸出資料的源頭整理成一個副程式

也就是粉字的makeData()的部分

再來,按照步驟處理:

1.清除表單資料:arrayList.clear();

2.載入資料:makeData();

3.通知Adapter資料有被改變:myListAdapter.notifyDataSetChanged();

4.清除轉圈圈:swipeRefreshLayout.setRefreshing(false);

 

最後補充一下

myListAdapter的資料情別是所定義class的名稱

也就是

private class MyListAdapter extends RecyclerView.Adapter<MyListAdapter.ViewHolder>{...}

的部分

前面有在全域變數中宣告過

MyListAdapter myListAdapter;

別搞錯囉~(´・д・`)

會特別提醒是因為之前在網路爬文資料更新時

keyPoint打上:notifydatasetchanged not work

還蠻多人有疑問的

像這樣的問題

https://kgnotezone.blogspot.com/2018/01/android-notifydatasetchanged.html

https://stackoverflow.com/questions/15422120/notifydatasetchange-not-working-from-custom-adapter

這兩問題的大意就是忘記改變arrayList的內容..

還有之前也遇過一個蠢(其實還好)問題

淦...為什麼我打上arrayList.  沒有出現notifydatasetchanged啊囧

後來才發現...喔淦那是適配器(Adapter)的方法拉...

...

..

.

今天補完了RecycleView的下拉更新方法,不知道有沒有幫助呢?

程式碼在這兒,可以多多點進去看哦~

https://github.com/thumbb13555/SimpleRecycleViewExample

掰逼~(´-`)ノ

arrow
arrow

    碼農日常 發表在 痞客邦 留言(0) 人氣()