iT邦幫忙

2023 iThome 鐵人賽

DAY 19
0
Mobile Development

Android Studio開發過程和介紹系列 第 19

【DAY 19】 RecyclerView結合Intent

  • 分享至 

  • xImage
  •  

前言

這次要結合的地方是RecyclerView的點擊事件,當點擊了RecyclerView中的某一個項目後就執行跳轉頁面,將資料跟著傳入到目的地頁面,再將傳入的資訊顯示出來,這次實作預計會結合前幾篇講到的Api資料,將資料丟進RecyclerView顯示點擊某個選項後,就跳到下個頁面將所有資訊顯示出來。

Dependecies

    implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
    implementation 'com.squareup.retrofit2:retrofit:2.9.0'
    //Retrofit

    implementation 'com.squareup.retrofit2:adapter-rxjava3:2.9.0'
    implementation 'io.reactivex.rxjava3:rxjava:3.1.6'
    implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'
    //RxJava

manifests

    <uses-permission android:name="android.permission.INTERNET" />

布局設定

這次的實作除了原本的主畫面外,還有新增一個給Intent跳轉的頁面

  • activity_main

<?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"
    tools:context=".MainActivity"
    android:orientation="vertical">

    <Space
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="0.2" />

    <Button
        android:id="@+id/search"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="0.1"
        android:text="搜尋"
        android:textSize="30sp"
        android:textStyle="bold" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="0.7"
        android:paddingTop="15dp"
        tools:listitem="@layout/recycleritem"/>
</LinearLayout>

主畫面設定了一個搜尋按鈕,按下後就會將資料填入下方的RecyclerView。

  • recycleritem

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="150dp"
    android:background="@drawable/border"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:orientation="horizontal">

        <TextView
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="0.2"
            android:gravity="center"
            android:textSize="20sp"
            android:textColor="@color/black"
            android:textStyle="bold"
            android:text="Name :" />

        <TextView
            android:id="@+id/tv_name"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="0.8"
            android:gravity="center_vertical"
            android:textSize="20sp"
            android:textColor="@color/black"
            android:text="TextView" />
    </LinearLayout>

    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="@color/black" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:orientation="horizontal">

        <TextView
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="0.2"
            android:gravity="center"
            android:textSize="20sp"
            android:textColor="@color/black"
            android:textStyle="bold"
            android:text="Email :" />

        <TextView
            android:id="@+id/tv_email"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="0.8"
            android:gravity="center_vertical"
            android:textSize="20sp"
            android:textColor="@color/black"
            android:text="TextView" />
    </LinearLayout>

</LinearLayout>

item的設計也很簡單,就是把每一筆資料附的name跟email顯示出來。

  • activity_main2

<?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"
    tools:context=".MainActivity2">

    <TextView
        android:id="@+id/result"
        android:layout_width="374dp"
        android:layout_height="496dp"
        android:layout_marginStart="19dp"
        android:layout_marginTop="132dp"
        android:layout_marginEnd="18dp"
        android:layout_marginBottom="103dp"
        android:background="@drawable/border"
        android:gravity="center"
        android:text="TextView"
        android:textColor="@color/black"
        android:textSize="20sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/back"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="17dp"
        android:layout_marginTop="55dp"
        android:layout_marginEnd="304dp"
        android:layout_marginBottom="30dp"
        android:text="返回"
        android:textSize="20sp"
        app:layout_constraintBottom_toTopOf="@+id/result"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

這個介面我新增了一個TextView將接收到的資料顯示出來,並且增加了一個按鈕,用來將現在這個介面返回到前一頁。

  • border

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape>
            <stroke android:width="3dp"
                    android:color="#2EA9DF"/>
        </shape>
    </item>
</selector>

設定API

這個部分跟之前的寫法一樣,這邊就跳過不重講一次,詳情可以看之前的文章Day15

MainActivity

這次我在要取資料用了比較不一樣的方式將資料加進我的ArrayList,因此這裡就單獨將這個部分拉出來講

  • searchCommentData
private void searchCommentData() {
        getApi.getCommentData()
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(AndroidSchedulers.mainThread())
                .subscribe(new DisposableObserver<List<DataResponse>>() {
                    @Override
                    public void onNext(@NonNull List<DataResponse> dataResponses) {
                        for (DataResponse data : dataResponses){
                            HashMap hashMap = new HashMap();
                            hashMap.put("postId",data.postId);
                            hashMap.put("id",data.id);
                            hashMap.put("name",data.name);
                            hashMap.put("email",data.email);
                            hashMap.put("body",data.body);
                            mArrayList.add(hashMap);
                        }
                        setRecyclerView(mArrayList);
                    }
                    @Override
                    public void onError(@NonNull Throwable e) {}
                    @Override
                    public void onComplete() {}
                });
    }

onNext的部分我使用了for迴圈走訪抓下來的資料,然後再將資料給丟進我建立好的ArrayList裡面,最後再將資料傳進我的RecyclerView裡面

        for (DataResponse data : dataResponses){
            HashMap hashMap = new HashMap();
            hashMap.put("postId",data.postId);
            hashMap.put("id",data.id);
            hashMap.put("name",data.name);
            hashMap.put("email",data.email);
            hashMap.put("body",data.body);
            mArrayList.add(hashMap);
        }
        setRecyclerView(mArrayList);

首先我設定了一個DataResponse的變數data,這樣我的data就會代表DataResponse裡面的元素,這麼做最大的原因是因為得到的資料也是屬於DataResponse的元素,這麼做就可以順利地走訪得到的資料,接著下面在將每次的資料用HashMap存起來,在放進ArrayList裡面。
最後在設定RecyclerView,像這樣將程式的先後順序用呼叫函式的方法分開,不讓他一次執行,就可以降低讓程式報錯的機率。

整體程式碼

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.os.Bundle;
import android.util.Log;
import android.widget.Button;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.annotations.NonNull;
import io.reactivex.rxjava3.observers.DisposableObserver;
import io.reactivex.rxjava3.schedulers.Schedulers;

public class MainActivity extends AppCompatActivity {
    private ArrayList<HashMap<String,String>> mArrayList;
    private MyListAdapter myListAdapter;
    private RecyclerView recyclerView;
    private Button search;
    private ApiClient apiClient;
    private GetApi getApi;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        search = findViewById(R.id.search);
        recyclerView = findViewById(R.id.recyclerView);
        apiClient = new ApiClient();
        getApi = apiClient.getCommentApi().create(GetApi.class);
        mArrayList = new ArrayList<>();

        search.setOnClickListener(view -> searchCommentData());
    }

    private void searchCommentData() {
        getApi.getCommentData()
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(AndroidSchedulers.mainThread())
                .subscribe(new DisposableObserver<List<DataResponse>>() {
                    @Override
                    public void onNext(@NonNull List<DataResponse> dataResponses) {
                        for (DataResponse data : dataResponses){
                            HashMap hashMap = new HashMap();
                            hashMap.put("postId",data.postId);
                            hashMap.put("id",data.id);
                            hashMap.put("name",data.name);
                            hashMap.put("email",data.email);
                            hashMap.put("body",data.body);
                            mArrayList.add(hashMap);
                        }
                        setRecyclerView(mArrayList);
                    }
                    @Override
                    public void onError(@NonNull Throwable e) {}
                    @Override
                    public void onComplete() {}
                });
    }
    private void setRecyclerView(ArrayList<HashMap<String, String>> mArrayList) {
        myListAdapter = new MyListAdapter(mArrayList);
        recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
        recyclerView.setAdapter(myListAdapter);
    }
}

MyListAdapter

基本設定的部分這邊一樣也跳過,詳細可以看之前的文章Day8
這邊會講解怎麼設定RecyclerView的點擊事件,以及怎麼跟Intent跳轉頁面做結合

    @Override
    public void onBindViewHolder(@NonNull MyListAdapter.ViewHolder holder, int position) {
        holder.name.setText(mArrayList.get(position).get("name"));
        holder.email.setText(mArrayList.get(position).get("email"));

        holder.itemView.setOnClickListener(view -> {
            HashMap data = mArrayList.get(position);
            Intent intent = new Intent();
            intent.putExtra("data",data);
            intent.setClass(view.getContext(), MainActivity2.class);
            view.getContext().startActivity(intent);
        });
    }

RecyclerView點擊事件要用到itemView裡面的點擊事件,並且設定在點擊到某個選項後,就將點擊到的資料都存進一個HashMap,接著就可以將資料用putExtra的方式把資料丟給Intent,然後在將本地的Context以及目的地的Class填好,最後就可以呼叫startActivity將Intent傳入,讓他執行跳轉頁面的指令。

  • 補充 : 因為我的資料是用HashMap打包在包進ArrayList裡面,所以這裡我才要使用HashMap去接收資料。

MainActivity2

import androidx.appcompat.app.AppCompatActivity;

import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.widget.Button;
import android.widget.TextView;

import java.util.ArrayList;

public class MainActivity2 extends AppCompatActivity {
    private TextView result;
    private Button back;
    private ArrayList data;
    @SuppressLint("MissingInflatedId")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);

        result = findViewById(R.id.result);
        back = findViewById(R.id.back);

        data = new ArrayList();
        Intent intent = getIntent();
        if (intent != null){
            data.add(intent.getSerializableExtra("data"));
        }
        result.setText(data.get(0).toString());

        back.setOnClickListener(view -> finish());
    }
}

首先看到這個部分

        Intent intent = getIntent();
        if (intent != null){
            data.add(intent.getSerializableExtra("data"));
        }
        result.setText(data.get(0).toString());

因為這次的資料型態較複雜所以要用到getSerializableExtra,填入傳入資料時設定的key,就能將資料丟給ArrayList去存取,最後在將資料丟給TextView去顯示。

接著看到按鈕的設定

        back.setOnClickListener(view -> finish());

這邊要說明一下,可以想像一下有一個容器用來存取每個開啟的頁面,當使用Intent跳轉頁面時,就是在一個容器中將目的地的頁面也加進一個容器中,大概就像這樣https://ithelp.ithome.com.tw/upload/images/20230929/201615000jhqvLOX4n.png
接著我設定了,當點擊這個按鈕後就執行finish()這個指令,finish可以把當前的這個頁面給關掉,可以想像成將後面添加的頁面給丟掉
https://ithelp.ithome.com.tw/upload/images/20230929/20161500u3F0vo0NQx.png
最後就會剩下MainActivity這個頁面,也就會自動跳回上一頁囉~

以上就是本次將RecyclerView的點擊事件結合Intent跳轉頁面的全部內容,下一篇我會講解怎麼將RecyclerView加進Dialog,並且結合模糊搜尋的功能。


上一篇
【DAY 18】 Intent頁面跳轉
下一篇
【DAY 20】 RecyclerView + Dialog
系列文
Android Studio開發過程和介紹30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言