Android プログラミングを始めました。
開発環境としては、最も標準的な Android Studio と Kotlin を使うことにしました。
Android Studio のインストールや使い方の説明を始めるとスクリーンショット だらけになりますので、そこは、他のサイトを参照してください。
このコーナーでは、ビューパーツを特定する ViewBinding のための build.gradleファイルと、文字列のための XML ファイルと、 レイアウトのための XML ファイルと、メインの Kotlin ファイルの掲載が中心になります。
フラグメント(fragment、断片)は、アクティビティの中に埋め込むことのできる、 XMLとKotlinファイルのセットです。XMLを持っているので独自のビューを 設定できます。そしてKotlinファイルで独自の処理も設定できます。
一つのアクティビティに複数のフラグメントを埋め込むこともできます。 また一つのフラグメントを複数のアクティビティに埋め込むこともできます。
フラグメントはAndoroid プログラミングおいて重要なものになっているみたいです。
トランジション(画面遷移)の章では、アプリをスマホで使うことを想定して プログラミングしました。もしあのアプリをタブレットで使った場合はかなり間延びした 画面表示になってしまいます。 ここではフラグメントを使ってタブレットで使った場合は、 タブレットに適した画面表示になるようにします。
Empty Activity テンプレートで Fragment という名前のプロジェクトを作ります。
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にアプリで使用する文字列をすべて登録 しておきます。
<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 にします。
<?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"/>
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(メイン画面のレイアウトファイル)に、先ほど作ったフラグメントを 埋め込みます。
<?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 Name | activity-main.xml |
Resource type | Layout |
Root element | LinearLyoujt |
Source Set | main src/main/res |
Directory name | layout-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を次のように書き換えます。
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に次のように記述します。
<?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>
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 フラグメントを埋め込みます。
<?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>
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
}
}