Android
 Computer >> コンピューター >  >> プログラミング >> Android

【Kotlin】Android RecyclerViewで選択したアイテムをハイライト表示する方法

Kotlinを使って、AndroidのRecyclerViewで選択したアイテムを適切にハイライト表示する方法を解説します。Selector DrawableとSparseBooleanArrayを組み合わせることで、タップ操作だけで項目の選択・解除を切り替えられる実装方法を、実際のコード例とともにステップごとに見ていきましょう。

完成イメージ

リストの項目をタップすると背景色が変化してハイライト表示され、もう一度タップすると元の状態に戻ります。サンプルデータにはサッカーの「バロンドール」受賞歴を使用しています。

ステップ1:新規プロジェクトの作成

Android Studioで新しいプロジェクトを作成します。メニューから「File」→「New Project」を選択し、必要な情報を入力してプロジェクトを作成してください。

ステップ2:activity_main.xmlの実装

res/layout/activity_main.xmlに以下のコードを追加します。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="4dp"
    tools:context=".MainActivity">
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingBottom="8dp" />
</RelativeLayout>

ステップ3:MainActivity.ktの実装

src/MainActivity.ktに以下のコードを追加します。ここではRecyclerViewの初期化、LayoutManagerの設定、そしてアダプターへのデータ受け渡しを行っています。

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        title = "KotlinApp"
        val recyclerView: RecyclerView = findViewById(R.id.recyclerView)
        recyclerView.addItemDecoration(SimpleItemDecoration(this))
        val layoutManager = LinearLayoutManager(this@MainActivity)
        recyclerView.layoutManager = layoutManager
        val posts = returnListItems()
        val adapter = RecyclerViewAdapter(this@MainActivity, posts)
        recyclerView.adapter = adapter
    }
    private fun returnListItems(): List<ItemObject>? {
        val items: MutableList<ItemObject> = ArrayList()
        items.add(ItemObject("Ballon'd'or", "2007", "Ricardo KaKa"))
        items.add(ItemObject("Ballon'd'or", "2008", "Cristiano Ronaldo"))
        items.add(ItemObject("Ballon'd'or", "2009 - 2012, 2015", "Lionel Messi"))
        items.add(ItemObject("Ballon'd'or", "2013, 2014, 2016, 2017", "Cristiano Ronaldo"))
        items.add(ItemObject("Ballon'd'or", "2018", "Luca Modric"))
        items.add(ItemObject("Ballon'd'or", "2019", "Lionel Messi"))
        return items
    }
}

ステップ4:Kotlinクラスファイルの作成

以下の4つのKotlinクラスファイルを作成し、それぞれ対応するコードを追加します。

ItemObject.kt

リスト1行分のデータを保持するデータクラスです。

internal class ItemObject(val awardTitle: String, val awardYear: String, val player: String) {
}

RecyclerViewAdapter.kt

リストの各行データをViewHolderにバインドするアダプタークラスです。

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.annotation.NonNull
import androidx.recyclerview.widget.RecyclerView
class RecyclerViewAdapter internal constructor(
    context: MainActivity,
    private val itemList: List<ItemObject>?
) : RecyclerView.Adapter<RecyclerViewHolders>() {
    @NonNull
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerViewHolders {
        val layoutView = LayoutInflater.from(parent.context).inflate(R.layout.list_layout, null)
        return RecyclerViewHolders(layoutView)
    }
    override fun onBindViewHolder(holder: RecyclerViewHolders, position: Int) {
        holder.awardTitle.text = "Award Title: " + itemList!![position].awardTitle
        holder.awardYear.text = "Award Year: " + itemList[position].awardYear
        holder.player.text = "Player Name: " + itemList[position].player
    }
    override fun getItemCount(): Int {
        return this.itemList!!.size
    }
}

RecyclerViewHolders.kt

ここがハイライト表示の要となるクラスです。SparseBooleanArrayで項目ごとの選択状態を管理し、クリックのたびにview.isSelectedを切り替えます。このフラグの変化によって、後述のセレクターDrawableが自動的に切り替わる仕組みです。

import android.util.SparseBooleanArray
import android.view.View
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView.ViewHolder
class RecyclerViewHolders(itemView: View) : ViewHolder(itemView),
View.OnClickListener {
    var awardTitle: TextView
    var awardYear: TextView
    var player: TextView
    private val selectedItems = SparseBooleanArray()
    override fun onClick(view: View) {
        if (selectedItems[adapterPosition, false]) {
            selectedItems.delete(adapterPosition)
            view.isSelected = false
        }
        else {
            selectedItems.put(adapterPosition, true)
            view.isSelected = true
        }
    }
    init {
        itemView.setOnClickListener(this)
        awardTitle = itemView.findViewById(R.id.awardTitle)
        awardYear = itemView.findViewById(R.id.awardYear)
        player = itemView.findViewById(R.id.playerName)
    }
}

SimpleItemDecoration.kt

リスト項目間に区切り線を描画するためのItemDecorationクラスです。

import android.content.Context
import android.graphics.Canvas
import android.graphics.drawable.Drawable
import androidx.annotation.NonNull
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
internal class SimpleItemDecoration(context: Context) : RecyclerView.ItemDecoration() {
    private val drawable: Drawable = ContextCompat.getDrawable(context, R.drawable.line_divider)!!
    override fun onDrawOver(
        @NonNull canvas: Canvas,
        parent: RecyclerView,
        @NonNull state: RecyclerView.State
    )
    {
        val left = parent.paddingLeft
        val right = parent.width - parent.paddingRight
        val childCount = parent.childCount
        for (i in 0 until childCount) {
            val child = parent.getChildAt(i)
            val params = child.layoutParams as RecyclerView.LayoutParams
            val top = child.bottom + params.bottomMargin
            val bottom = top + drawable.intrinsicHeight
            drawable.setBounds(left, top, right, bottom)
            drawable.draw(canvas)
        }
    }
}

ステップ5:Drawableリソースファイルの作成

以下のDrawableリソースファイルを作成し、それぞれのコードを追加します。

background_selector.xml

選択状態(state_selected)に応じて背景色を切り替えるセレクターです。選択時はholo_green_light、未選択時はholo_purpleが適用されます。

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="https://schemas.android.com/apk/res/android">
    <item android:drawable="@android:color/holo_green_light" android:state_pressed="false" android:state_selected="true" />
    <item android:drawable="@android:color/holo_purple" android:state_selected="false" />
</selector>

line_divider.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="https://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <size
        android:width="2dp"
        android:height="2dp" />
    <solid android:color="@color/colorPrimaryDark" />
</shape>

ステップ6:list_layout.xmlの作成

レイアウトリソースファイル(list_layout.xml)を作成し、以下のコードを追加します。ルートレイアウトのbackground属性に、ステップ5で作成したセレクター(@drawable/background_selector)を指定するのがポイントです。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/background_selector"
    android:padding="16dp">
    <TextView
        android:id="@+id/awardTitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="New Text"
        android:textColor="@android:color/background_dark"
        android:textSize="18sp"
        android:textStyle="bold" />
    <TextView
        android:id="@+id/awardYear"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/awardTitle"
        android:layout_alignStart="@+id/awardTitle"
        android:layout_marginTop="20dp"
        android:text="New Text"
        android:textColor="@android:color/background_dark" />
    <TextView
        android:layout_marginBottom="10dp"
        android:id="@+id/playerName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentEnd="true"
        android:text="New Text"
        android:textColor="@android:color/background_dark" />
</RelativeLayout>

ステップ7:AndroidManifest.xmlの編集

androidManifest.xmlに以下のコードを追加します。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
    package="com.example.q11">
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

アプリの実行と動作確認

それではアプリを実行してみましょう。実機のAndroidスマートフォンをPCに接続しているものとします。Android Studioからアプリを実行するには、プロジェクト内のいずれかのアクティビティファイルを開き、ツールバーの「Run」【Kotlin】Android RecyclerViewで選択したアイテムをハイライト表示する方法アイコンをクリックします。候補として表示された自分のモバイルデバイスを選択すると、端末にアプリの初期画面が表示されます。

【Kotlin】Android RecyclerViewで選択したアイテムをハイライト表示する方法

【Kotlin】Android RecyclerViewで選択したアイテムをハイライト表示する方法

まとめ

RecyclerViewでの選択ハイライト表示は、「ViewのisSelectedフラグ」と「StateListDrawable(セレクター)」を組み合わせることでシンプルに実装できます。なお、より新しいRecyclerViewのバージョンではadapterPositionは非推奨となっているため、必要に応じてbindingAdapterPositionへの置き換えを検討してください。マルチ選択や単一選択など、要件に合わせてSparseBooleanArrayの管理方法をカスタマイズしてみてください。

  1. Android RecyclerViewで選択したアイテムを適切にハイライト表示する方法【初心者向け完全ガイド】

    はじめにこの記事では、Androidアプリ開発においてRecyclerViewで選択されたアイテムを適切に強調表示(ハイライト表示)する方法を、ステップごとのサンプルコード付きで詳しく解説します。リスト形式のUIは多くのアプリで使われており、ユーザーがどの項目を選んだかを視覚的に分かりやすくすることは、使いやすいアプリを作る上で非常に重要なポイントです。Step 1:新規プロジェクトの作成と依存関係の追加まずAndroid Studioで新しいプロジェクトを作成します。File → New Project を選択し、必要な情報を入力してプロジェクトを作成しましょう。次に、build.gradl

  2. KotlinでAndroidアプリのGridViewスクロールを無効化する方法を徹底解説

    この記事では、Kotlinを使ってAndroidアプリのGridView(グリッドビュー)のスクロール機能を無効にする方法を、サンプルコードとともにわかりやすく解説します。GridViewは画像ギャラリーやメニュー表示などによく使われるUIコンポーネントですが、状況によってはスクロールさせたくないケースもあります。そのような場合に役立つテクニックです。実装の手順ステップ1:新規プロジェクトを作成するまず、Android Studioで新しいプロジェクトを作成します。メニューから「File」→「New Project」を選択し、必要な項目をすべて入力してプロジェクトを作成してください。ステップ2