Android   フラグメント

ホーム

Android プログラミングを始めました。

開発環境としては、最も標準的な Android Studio と Kotlin を使うことにしました。

Android Studio のインストールや使い方の説明を始めるとスクリーンショット だらけになりますので、そこは、他のサイトを参照してください。

このコーナーでは、ビューパーツを特定する ViewBinding のための build.gradleファイルと、文字列のための XML ファイルと、 レイアウトのための XML ファイルと、メインの Kotlin ファイルの掲載が中心になります。

フラグメント

フラグメント(fragment、断片)は、アクティビティの中に埋め込むことのできる、 XMLとKotlinファイルのセットです。XMLを持っているので独自のビューを 設定できます。そしてKotlinファイルで独自の処理も設定できます。

一つのアクティビティに複数のフラグメントを埋め込むこともできます。 また一つのフラグメントを複数のアクティビティに埋め込むこともできます。

フラグメントはAndoroid プログラミングおいて重要なものになっているみたいです。

トランジション(画面遷移)の章では、アプリをスマホで使うことを想定して プログラミングしました。もしあのアプリをタブレットで使った場合はかなり間延びした 画面表示になってしまいます。 ここではフラグメントを使ってタブレットで使った場合は、 タブレットに適した画面表示になるようにします。

プロジェクトの作成

Empty Activity テンプレートで Fragment という名前のプロジェクトを作ります。

コーディング

build.gradle

Gradle Scripts/build.gradle (Module: Fragment.app)

Android プログラミングでビューバーツを特定する最新の方法 View Binding を有効にするために、build.gradle の android グループに viewBinding 項目を追加します。


・・・
android {
    ・・・
    viewBinding {
        enabled = true
    }
}

dependencies {
    ・・・
	

項目を追加した後は、エディタウィンドウ上部の「Sync Now」ボタンをクリックします。

なお、dependencies グループの testImplementation 'junit:junit:4.+' を削除すると警告が消えます。


次に appの中のresの中のvaluesの中のstrings.xmlにアプリで使用する文字列をすべて登録 しておきます。

strings.xml


<resources>
    <string name="app_name">フードメニュー</string>
    <string-array name="food">
        <item>カレー</item>
        <item>カツカレー</item>
        <item>牛丼</item>
        <item>天丼</item>
        <item>かつ丼</item>
        <item>うどん</item>
        <item>そば</item>
        <item>ハンバーグ定食</item>
        <item>唐揚げ定食</item>
        <item>焼き魚定食</item>
        <item>生姜焼き定食</item>
        <item>とんかつ定食</item>
        <item>焼肉定食</item>
        <item>コロッケ定食</item>
        <item>ミンチかつ定食</item>
    </string-array>
    <string name="thanks_title">
        承りました。</string>
    <string name="thanks_item">
        をご注文ですね。\n
        ありがとうございます。</string>
    <string name="back">戻る</string>
</resources>
    


最初にメイン画面に埋め込むフラグメントを作ります。File メニューから、New → Fragment → Fragment (Blank)を選んでください。現れるダイアログで名前を MainFragment にします。

fragment_main.xml


<?xml version="1.0" encoding="utf-8"?>
<ListView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/listview"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:entries="@array/food"/>
    


MainFragment.kt


package com.example.fragment

import android.content.Intent
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.AdapterView
import com.example.fragment.databinding.FragmentMainBinding

class MainFragment : Fragment() {

    private lateinit var binding: FragmentMainBinding
    private var _isLayoutXLarge = true

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        binding = FragmentMainBinding.inflate(inflater, container, false)
        val thanksFrame = activity?.findViewById<View>(R.id.thanksFrame)
        if(thanksFrame == null) {
            _isLayoutXLarge = false
        }
        binding.listview.onItemClickListener = ListItemClickListener()
        return binding.root
    }

    private inner class ListItemClickListener:
        AdapterView.OnItemClickListener {
        override fun onItemClick(parent: AdapterView<*>, view: View,
                                 position: Int, id: Long) {
            val item = parent.getItemAtPosition(position) as String
            val bundle = Bundle()
            bundle.putString("item", item)
            if(_isLayoutXLarge) {
                val transaction = parentFragmentManager.beginTransaction()
                val thanksFragment = ThanksFragment()
                thanksFragment.arguments = bundle
                transaction.replace(R.id.thanksFrame, thanksFragment)
                transaction.commit()
            } else {
                val intent = Intent(context, ThanksActivity::class.java)
                intent.putExtra("item", item)
                startActivity(intent)
            }
        }
    }
}
    


次に activity_main.xml(メイン画面のレイアウトファイル)に、先ほど作ったフラグメントを 埋め込みます。

activity_main.xml


<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/fragmentMenu"
        android:name="com.example.fragment.MainFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</FrameLayout>
    


ここで、タブレット用の activity_main.xml ファイルも作っておきます。 プロジェクトウィンドウで app を右クリックして、 New → Android Resource File を選択します。 次に表示されるダイアログで次のように設定します。

File Nameactivity-main.xml
Resource typeLayout
Root elementLinearLyoujt
Source Setmain src/main/res
Directory namelayout-xlarge

出来上がった activity_main (Xlarge)ファイルがタブレット用のメイン画面の表示ファイルに なります。次のように記述してください。

activity_main (Xlarge)


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:baselineAligned="false"
    android:orientation="horizontal">

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/fragmentMenu"
        android:name="com.example.fragment.MainFragment"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="0.4"
        tools:ignore="InvalidId" />

    <FrameLayout
        android:id="@+id/thanksFrame"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_marginEnd="10dp"
        android:layout_marginStart="50dp"
        android:layout_weight="0.6"
        android:background="?android:attr/detailsElementBackground"/>

</LinearLayout>
    


そして、MainActivity.ktを次のように書き換えます。

MainActivity.kt


package com.example.fragment

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.example.fragment.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {
    private lateinit var binding:ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
    }
}
    


次に注文確認用のアクティビティとフラグメントを作ります。File メニューから → New → Activity → Empty Activity を選んでください。次の画面で名前を ThanksActivity にします。 次に File メニュー → New → Fragment → Ftagment (Blank) を選んでください。 次の画面で名前を ThanksFragment にします。

そして、fragment_thanks.xmlとThanksFragment.ktに次のように記述します。

fragment_thanks.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=".ThanksActivity">

    <Button
        android:id="@+id/back"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="16dp"
        android:text="@string/back"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/thanks_order"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="@style/TextAppearance.AppCompat.Large"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
    


ThanksFragment.kt


package com.example.fragment

import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.example.fragment.databinding.FragmentThanksBinding

class ThanksFragment : Fragment() {
    private lateinit var binding: FragmentThanksBinding
    private var _isLayoutXLarge = true

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val menuFragment = parentFragmentManager.findFragmentById(R.id.fragmentMenu)
        if(menuFragment == null) {
            _isLayoutXLarge = false
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        binding = FragmentThanksBinding.inflate(inflater, container, false)
        val back = binding.back
        val extras: Bundle?

        if (_isLayoutXLarge) {
           extras = arguments
        } else {
            val intent = activity?.intent
            intent?.extras
            extras = intent?.extras
            back.visibility = View.INVISIBLE
        }
        val item = extras?.getString("item")
        val order = item + getString(R.string.thanks_item)
        binding.thanksOrder.text = order

        back.setOnClickListener(ButtonClickLister())
        return binding.root
    }

    private inner class ButtonClickLister: View.OnClickListener {
        override fun onClick(view: View) {
            if(_isLayoutXLarge) {
                val transaction = parentFragmentManager.beginTransaction()
                transaction.remove(this@ThanksFragment)
                transaction.commit()
            } else {
                activity?.finish()
            }
        }
    }
}
    


最後に activity_thanks.xml に Thanks フラグメントを埋め込みます。

activity_thanks.xml


<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/fragmentThanks"
        android:name="com.example.fragment.ThanksFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
        
</FrameLayout>
    


ThanksActivity.kt


package com.example.fragment

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.MenuItem
import com.example.fragment.databinding.ActivityThanksBinding

class ThanksActivity : AppCompatActivity() {
    private lateinit var binding: ActivityThanksBinding
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityThanksBinding.inflate(layoutInflater)
        setContentView(binding.root)
        supportActionBar?.setDisplayHomeAsUpEnabled(true)
        supportActionBar?.setTitle(R.string.thanks_title)
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        var returnVal = true
        if(item.itemId == android.R.id.home) {
            finish()
        } else {
            returnVal = super.onOptionsItemSelected(item)
        }
        return returnVal
    }
}
    


実行結果

スマホ

タブレット




14009 visits
Posted: Dec. 05, 2021
Update: Dec. 07, 2021

ホーム   目次