アプリの作り方の基本を習得するために、ボタンを押したら文字が変わるという簡単なアプリを作ってみます。
2024.1.1
Button
アプリ開発の最初にButtonを試すのは意味があります。表示するだけでなく、UIをタップするとActionが発生するというアプリの基本を実感できるからです。Androidではこれが簡単にできるようにAPIが組まれています。
ここではJava言語を使いますが Kotlin を使うとコード量を減らすことができます
また、Flutterではこちら
最初はプロジェクトの作成から入っていますが、既に理解できていればコードの記述にSkipして「MainActivity」から始めても構いません。
プロジェクトの作成
Android Studio から「New project」を選択します。
あるいは既にプロジェクトが表示されているのであれば
「File」「New」「New Project…」
を選択して新規プロジェクトを開始できます。
「File」「Close project」では一旦プロジェクトを終了させてTop画面に戻ることもできます。
Activityのタイプを選定:
Empty Views Activity が使いやすいです。他のものは便利なのですが、ある程度アプリ構築を理解できてからのほうがいいでしょう。「Next」
プロジェクトの名前を入れます。
例: TestButton プロジェクトを作成する場合
- Name: TestButton
- Package name: com.example
- これはテストでは適当なexample.com.testbutton にしておきます。本番アプリではユニークなパッケージ名を付けます。
- Save location: アプリプロジェクトを保存する場所
- MacとWindowsでは異なりますが、後で自分で分かるようにしておきます
- Language: Java
- KotlinかJavaの開発言語の選択
- Minimum API Level: API 34: Android 14.0
例としてAPI34で始めますが、実機でテストする場合は、Levelを実機に合わせて落とすこともあります
後からMinimum SDKを build.gradle から変えることもできます
これでプロジェクトを作成
プロジェクトが完成しました。
MainActivity
コードを記述していきます。
プロジェクトが作成されると「Project」のTAGで階層が表示されます。
主に MainActivity.java と activity_main.xml を使います。
Java のコーディングは MainActivity.java にします。Empty Activityを選んだので、ある程度の基本的なコードは既に入っています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
//package com.example.testbutton; import android.os.Bundle; import androidx.activity.EdgeToEdge; import androidx.appcompat.app.AppCompatActivity; import androidx.core.graphics.Insets; import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); EdgeToEdge.enable(this); setContentView(R.layout.activity_main); ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> { Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()); v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom); return insets; }); } |
activity_main.xml にはレイアウトを記述
やり方としては、
- 「Code」で全てコードで記述
- 「Split」 CodeとDesignの混合
- 「Design」を使って画面上にUIパーツを配置する
「Design」ではレイアウトの配置全体をデザイン的に決めていくには便利です。
レイアウトの種類に応じて設定方法がことなりますが、デフォルトのConstraintLayoutの使い方は慣れないと初めはわかりにくいかもしれません。
右上の3つ並んだアイコンで「Code」「Split」「Design」の切り替えができます。
「Code」は並んだアイコンの左端です。
微調整も含めた細かな設定はコーディングがいいでしょう
MainActivity.javaの onCreateメソッドにボタンを設定する記述をします。
1 2 3 4 5 6 7 |
@Override protected void onCreate(Bundle savedInstanceState) { ... // ボタンを設定 Button button = findViewById(R.id.button); } |
ここで、エラーが表示されますが後でコードを正しく追加すれば消えます。
あるいは、エラーとなっているところにこのようポップアップが出た場合は、エラー部分にマウスを置いて「Alt+Enter」を行うと自動的に以下の行が追加されます。(MacとWindowsではコマンドが異なります)
1 |
import android.widget.Button; |
また、R.id.button がエラーになっていますが、後でレイアウトの設定をすれば解消します。
setContentView:
Screenにテキスト、ボタン、画像を表示させる仕組みで SetContentView() は最終的にViewをまとめるところです。
それぞれTextViewなどのViewを何種類かある Layout に設定し、それを SetContentView() に入れます。
ファイルでは(LinearLayoutの例)
1 |
setContentView(R.layout.activity_main); |
既にこれが記述されていて、これが activity_main.xml ファイルをレイアウトとして登録し表示する設定です。
1 |
findViewById(R.id.button) |
これはリソースの(レイアウトファイル)からid が button のものを見つけてくることを意味します。
findViewById
次に TextView を設定します。このケースではTextViewは事前に onCreate() の前に作成します。
private TextView textView;
onCreate() の中に
textView = findViewById(R.id.textView);
その後に、ボタンがタップされた事が分かるようにリスナー登録します。
OnClickListener():
リスナー、つまりアプリが起動中に、ユーザーがボタンをタップしたイベント発生を聞き耳を立てているというようなことでしょうか。
1 2 3 4 5 6 |
button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // ... } }); |
尚、lambda式を使うとよりシンプルになります。
1 2 3 |
button.setOnClickListener( v -> { // ... }); |
lambda式は分かりにくいかもしれませんがおいおい理解していきましょう
ボタンがタップされた時の挙動を決めます。
ボタンタップされるとフラグのbuttonTapを判別して
- trueなら「Hello」
- falseなら「World」
が表示されるコードです
setText() でTextViewの文字列を設定
1 2 3 4 5 6 7 8 |
if(buttonTap){ textView.setText("Hello"); buttonTap= false; } else{ textView.setText("World"); buttonTap= true; } |
いくつか追加して、
import android.widget.TextView;
private TextView textView;
private boolean buttonTap = false;
とりあえずコードをまとめるとこうなります。
MainActivity.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
//package com.example.testbutton; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.TextView; public class MainActivity extends AppCompatActivity { private TextView textView; private boolean buttonTap = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // ボタンを設定 Button button = findViewById(R.id.button); // TextView の設定 textView = findViewById(R.id.text_view); // button.setOnClickListener(new View.OnClickListener() { // @Override // public void onClick(View view) { // // flagがtrueの時 // if (buttonTap) { // textView.setText("Hello"); // buttonTap = false; // } // // flagがfalseの時 // else { // textView.setText("World"); // buttonTap = true; // } // } // }); // lambda式で簡略化 button.setOnClickListener( v -> { // flagがtrueの時 if (buttonTap) { textView.setText("Hello"); buttonTap = false; } // flagがfalseの時 else { textView.setText("World"); buttonTap = true; } }); } } |
この状態ではまだエラーがありますがレイアウトファイルを設定すれば解消します。
package com.example.testbutton;
これは上ではコメントアウトしていますが、あなたが作ったプロジェクトのパッケージ名ができているのをつかってください。
activity_main
レイアウトを設定します。
フォルダ res 以下の layout に activity_main.xmlファイルがあります
MainActivity.java では button と textView を呼び出していますのでそれをここに作成します。デフォルトでは「ConstraintLayout」が設定されています。
ボタンのIDは以下で定義されています
android:id=”@+id/button”
TextViewも同様です
android:id=”@+id/text_view”
またTextViewの垂直方向の位置調整で
app:layout_constraintVertical_bias=”0.4″
と設定します。
またButtonは
app:layout_constraintVertical_bias=”0.6″
..\res\layout\activity_main.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
<?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:id="@+id/main" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <TextView android:id="@+id/text_view" android:text="Hello" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.4" /> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.6" /> </androidx.constraintlayout.widget.ConstraintLayout> |
build.gradle
ここではこのファイルに記述が必要ではありませんが
後々必要となりますので紹介しておきます。
build.gradle(Module: app)はプロジェクトの依存関係、APIレベル、バージョンなどを設定するところで最初のうちは使う頻度は少ないかもしれません。
他にもbuild.gradle(Project: XXOO)やsettings.gradleなどあります。
プロジェクト作成時に設定したAPIレベルですが、後から変更するにはこれを使います。
(これは環境によって変わります)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
plugins { alias(libs.plugins.android.application) } android { namespace = "com.example.testbutton" compileSdk = 34 defaultConfig { applicationId = "com.example.testbutton" minSdk = 34 targetSdk = 34 versionCode = 1 versionName = "1.0" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } buildTypes { release { isMinifyEnabled = false proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro" ) } } compileOptions { sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 } } dependencies { implementation(libs.appcompat) implementation(libs.material) implementation(libs.activity) implementation(libs.constraintlayout) testImplementation(libs.junit) androidTestImplementation(libs.ext.junit) androidTestImplementation(libs.espresso.core) } |
- compileSdk
- compileする API のバージョン
- minSdk
- 対応できる最下位のAPIバージョン
- targetSdk
- アプリケーションが対応しているAPIのバージョン
- versionCode
- アプリのリリース毎にアップデートさせるべきコード、1 -> 2 -> 3 …
- versionName
- ユーザーから見えるバージョンですversionCodeは上げてもこれはそのままにできます。リリース直後のバグ修正にはversionCodeは上げてもversionNameはそのままにするケース。1.0.0 -> 1.0.1 -> 1.1.0 ….
アプリを実行
実際のAndroidで実行させてみましょう。PCのスペックが低くなければエミュレーターで確認できます。
エミュレーターの立ち上がりに時間がかかるようであれば実機を使います。
Windows の場合は、実機のUSBドライバーを入れてください。スマホメーカーから提供されていると思います。USB ドライバーの設定
Macの場合はこのドライバーの設定は必要ありませんが、スマホのUSBデバッグを有効にする必要があります。
エミュレーターを選択し
メニューから「Run」->「Run ’app’」とするか
三角のアイコンをクリックするとビルドが始まります
あまりレイアウトはぱっとしませんが
とりあえず、ボタンを押すとテキストが変わるアプリができました
テキストサイズとテキストの色を指定して
少し見栄えを良くしてみます
1 2 3 4 5 6 7 8 9 10 11 |
<TextView ... android:textSize="50sp" android:textColor="#00ff00" ... <Button ... android:layout_width="200dp" ... android:textSize="20sp" ... |
activity_main.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
<?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" android:padding="20dp" tools:context=".MainActivity"> <TextView android:id="@+id/text_view" android:text="Hello" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="50sp" android:textColor="#00ff00" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.4" /> <Button android:id="@+id/button" android:layout_width="200dp" android:layout_height="wrap_content" android:text="Button" android:textSize="20sp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.6" /> </androidx.constraintlayout.widget.ConstraintLayout> |
文字が大きく、色が変わりました。
リテラルの修正
このコードは確かに動くのですが、コードをよく見るとあちこちにワーニングが出ています。黄色いバックグラウンドになっているところにマウスを持ってくると、
String literal in setText can not be translated. Use Android resources instead.
Localizing with Resources | Android Developers
とあります。
setTex(“Hello”)
のようにHelloという文字列をハードコードで直書きしているリテラルが、正しく解釈されないのでresourceを使うようにと注意されているわけです。
例えば日本語でハードコーディングすると文字化けやコードが走らない事があり得るのです。修正は、
1 |
textView.setText(R.string.hello); |
この res\values\strings.xml に
nameが”hello”というkeyに対してHelloというvalueを設定します。
1 2 3 4 |
<resources> <string name="app_name">TestButton</string> <string name="hello">Hello</string> </resources> |
このワーニングはactivity_main.xmlのリテラルにも出ているので合わせて修正すると。
strings.xml
1 2 3 4 5 6 |
<resources> <string name="app_name">TestButton</string> <string name="hello">Hello</string> <string name="world">World</string> <string name="button">Button</string> </resources> |
それぞれの修正箇所です。
MainActivity.java
1 2 3 4 5 6 7 8 9 10 11 12 |
button.setOnClickListener( v -> { // buttonTapがtrueの時 if (buttonTap) { textView.setText(R.string.hello); buttonTap= false; } // buttonTapがfalseの時 else { textView.setText(R.string.world); buttonTap= true; } }); |
レイアウトは
activity_main.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
... <TextView android:id="@+id/text_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hello" android:textSize="50sp" android:textColor="#00ff00" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.4" /> <Button android:id="@+id/button" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/button" android:textSize="20sp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.6" /> ... |
完成です。
以上はJava言語で記述しましたが、Kotlin も正式に使用可能言語となりました。以上をKotolinで書くと以下のようになります。
関連ページ:
- 簡単な Button アプリを作る
- ButtonをJavaコードだけで設定する
- カスタムボタンを作る
- ImageButton:Button, ImageButton に画像を設定する
- onClickListenerの色々な設定
- Button 配列を設定する
Reference:
Buttons | Android Developers