0
0

More than 1 year has passed since last update.

【2022年】LegacyだけどListViewにソース側からデータを渡して表示する(半ソース依存)

Posted at

前置き

ソース内で用意したアイテムのListをView側に用意したListViewに渡して表示するだけの
簡単な処理を作ります

作る物

下記のListViewを表示するだけのActivityを作ります
image.png

人選は、個人的にホットな奴らを採用してます
別にちびまる子ちゃんの登場人物とかでもいいです

なんでLegacy

なんでか知らんけど、分類がLegacyになってた

image.png

Legacyって書いてあるから、今後の追加機能とかは望めないけど
消したら影響受けるアプリも多そうだし、残り続けはするんじゃないかなと予想

軽く調べた限りでは、移行先候補として「RecyclerView」があるらしい

使った事ないので、説明だけで判断すると
「表示領域外に移動したアイテムを再利用する」とか
ゲームとかで大量のアイテムをスクロールメニューに表示したいときに使えそうだね
まぁ、ゲーム作るならAndroid直に触るよりもUnityとかUnrealEngine使うわって話になるけど

プロジェクト作成

例によって「Empty Activity」でプロジェクト作成

パッケージ名とプロジェクト名はなんでもいいが、筆者は
パッケージ名:com.arrayadapter.arrayadaptertest
プロジェクト名:ArrayAdapterTest

にした

これから作る各ファイルのファイル構成は以下となる
image.png

test_list_item_header.xmlは最後のほうで語る「おまけ」で使うので
今の所は無いものとして扱ってください

build.gradle(app)

Android セクションに下記を追加

build.gradle(app)
    buildFeatures {
        dataBinding = true
    }

main_activity.xml

HelloWorld消して、空っぽのListViewを置くだけ
ソース側で引っ張ってこれるようにIDも付与する

main_activity.xml
<?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=".MainActivity">

    <ListView
        android:id="@+id/list_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    </ListView>

</androidx.constraintlayout.widget.ConstraintLayout>

test_list_item.xml

ListViewに表示する1行分のアイテムの
見た目やバインディング情報を定義する

test_list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable
            name="li"
            type="com.arrayadapter.arrayadaptertest.TestListItem" />
    </data>

    <LinearLayout
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
        <TextView
            android:id="@+id/name"
            android:layout_width="70dp"
            android:layout_height="wrap_content"
            android:text="@{li.name}"/>

        <TextView
            android:id="@+id/gender"
            android:layout_width="70dp"
            android:layout_height="wrap_content"
            android:text="@{li.gender}"/>

        <TextView
            android:id="@+id/age"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{Integer.toString(li.age)}"/>
    </LinearLayout>

</layout>

後述で作る「TestListItem」の名前を、このxml内部で「li」と命名し
セットした3つのTextViewそれぞれにバインディングするだけのxml

最初のrootを「layout」で宣言したため、ビルドすれば
com.arrayadapter.arayadaptertest.databinding パッケージが自動生成され
そこに「TestListItemBinding」クラスが自動生成される

TestListItem.kt

ListViewにぶち込むアイテム1個分の情報

TestListItem.kt
package com.arrayadapter.arrayadaptertest

class TestListItem (val name : String , val gender : String , val age : Int ){

}

余談だが、これだけで、Javaで言う、下みたいな事を書いた事になるらしい

example.java

public class TestListArray {

     public string name;
     public string gender;
     public string age;

     public TestListArray ( string _name , string _gender , int _age )
     {
          name = _name;
          gender = _gender;
          age = _age;
     }
}

いやぁ、便利っすねぇ~ Kotlin

TestListAdapter.kt

こいつが重要

View側のListViewとソースを結び付ける中継役と思えばいい
たぶんもっといろんなことができそうな気がする

TestListAdapter.kt
package com.arrayadapter.arrayadaptertest

import android.content.Context
import android.view.LayoutInflater
import android.widget.ArrayAdapter
import android.view.View
import android.view.ViewGroup
import com.arrayadapter.arrayadaptertest.databinding.TestListItemBinding

class TestListAdapter(context: Context, objects: List<TestListItem>) :
    ArrayAdapter<TestListItem>(context, 0, objects)  {

    private lateinit var iLayoutInflater : LayoutInflater

    override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
        iLayoutInflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater

        // test_list_item.xmlのバインディングデータ取得
        var binding = TestListItemBinding.inflate(iLayoutInflater)

        // test_list_item.xmlのli変数とbindさせる
        val li : TestListItem = getItem(position)!!
        binding.li = li

        return binding.root
    }

}

重要なのはgetView関数の実装

TestListAdapterの生成時にListが渡されて、すでにListを持っているため、
getView関数が実行されたときに、引数で渡されたpositionが示すlistのTestListItemを取得し
それを「test_list_item.xml」内部で定義した「li」とバインドさせてバインディングを行う

MainActivity.kt

まずはソース全文

MainActivity.kt
package com.arrayadapter.arrayadaptertest

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.ListView;


class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // listviewの参照を取得
        var listView : ListView = findViewById(R.id.list_view) as ListView

        // 仮データ作成
        var list : MutableList<TestListItem> = mutableListOf(
            TestListItem("田所浩二" , "ホモ" , 24 ),
            TestListItem("長谷川亮太" , "男" , 810 ),
            TestListItem("唐澤貴洋" , "男" , 1000000 ),
            TestListItem("岩間好一" , "男" , 931 ),
        )

        // リストを自動的に構築するための必要な処理や情報をセット
        var adapter : TestListAdapter = TestListAdapter(this,list)
        listView.adapter = adapter

    }
}

//仮データ作成 の所は、お好みの男児や美少女とかを好きなだけ追加していい

重要なのは

MainActivity.kt
        // リストを自動的に構築するための必要な処理や情報をセット
        var adapter : TestListAdapter = TestListAdapter(this,list)
        listView.adapter = adapter

この部分で、用意したlistを元にAdapterを生成し
listViewが持つAdapterと関連付ける
これによって、listViewの内容がソース内で設定したList通りに表示される

ビルドしてみよう

成功すれば、愉快な仲間たちがList形式で表示されたAcitivityが起動するはず

課題

ソース部分にいろいろごちゃごちゃ書きすぎてるので
XMLの記述でうまく吸収できないか

参考

おまけ

ヘッダーをつけてみよう

リスト自体は表示できたけど、項目名が表示されてなくて、なんかイケてないので
ヘッダーをつけてみる事にする

ヘッダー表示用の「test_list_item_header.xml」を用意する

test_list_item_header.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <TextView
            android:id="@+id/name"
            android:layout_width="70dp"
            android:layout_height="wrap_content"
            android:text="Name"
            android:background="#000000"
            android:textColor="#FFFFFF"/>

        <TextView
            android:id="@+id/gender"
            android:layout_width="70dp"
            android:layout_height="wrap_content"
            android:text="Gender"
            android:background="#000000"
            android:textColor="#FFFFFF"/>

        <TextView
            android:id="@+id/age"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Age"
            android:background="#000000"
            android:textColor="#FFFFFF"/>
    </LinearLayout>

</layout>

ヘッダーと項目アイテムが別個になってるのが確認できるように
ヘッダーの背景色を黒、文字色を白に適当に設定

MainActivity.ktに3行追加する

MainActivity.kt
package com.arrayadapter.arrayadaptertest

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.ListView;
import com.arrayadapter.arrayadaptertest.databinding.TestListItemHeaderBinding //追加


class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // listviewの参照を取得
        var listView : ListView = findViewById(R.id.list_view) as ListView

        // ヘッダーをセットする
        val testListItemHeaderBinding = TestListItemHeaderBinding.inflate(layoutInflater) //追加
        listView.addHeaderView(testListItemHeaderBinding.root) // 追加

        // 仮データ作成
        var list : MutableList<TestListItem> = mutableListOf(
            TestListItem("田所浩二" , "ホモ" , 24 ),
            TestListItem("長谷川亮太" , "男" , 810 ),
            TestListItem("唐澤貴洋" , "男" , 1000000 ),
            TestListItem("岩間好一" , "男" , 931 ),
        )

        // リストを自動的に構築するための必要な処理や情報をセット
        var adapter : TestListAdapter = TestListAdapter(this,list)
        listView.adapter = adapter

    }
}

もっと奇麗なやり方がありそうだが、手っ取り早く思いついた方法はこれ

ビルドしてみよう

成功すれば、以下のように表示されるはず

image.png

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0