アプリの作り方の基本を習得するために、ボタンを押したら文字が変わるという簡単なアプリを作ってみます。
Android Studio
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
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.xm l にはレイアウトを記述
やり方としては、
「Code」で全てコードで記述
「Split」 CodeとDesignの混合
「Design」を使って画面上にUIパーツを配置する
「Design」ではレイアウトの配置全体をデザイン的に決めていくには便利です。
レイアウトの種類に応じて設定方法がことなりますが、デフォルトのConstraintLayout の使い方は慣れないと初めはわかりにくいかもしれません。
右上の3つ並んだアイコンで「Code」「Split」「Design」の切り替えができます。
「Code」は並んだアイコンの左端です。
微調整も含めた細かな設定はコーディングがいいでしょう
MainActivity.javaの
onCreate メソッドにボタンを設定する記述をします。
@Override
protected void onCreate ( Bundle savedInstanceState ) {
. . .
// ボタンを設定
Button button = findViewById ( R . id . button ) ;
}
ここで、エラーが表示されますが後でコードを正しく追加すれば消えます。
あるいは、エラーとなっているところにこのようポップアップが出た場合は、エラー部分にマウスを置いて「Alt+Enter 」を行うと自動的に以下の行が追加されます。(MacとWindowsではコマンドが異なります)
import android . widget . Button ;
また、R.id.button がエラーになっていますが、後でレイアウトの設定をすれば解消します。
setContentView:
Screenにテキスト、ボタン、画像を表示させる仕組みで SetContentView() は最終的にViewをまとめるところです。
それぞれTextViewなどのViewを何種類かある Layout に設定し、それを SetContentView() に入れます。
ファイルでは(LinearLayoutの例)
setContentView ( R . layout . activity_main ) ;
既にこれが記述されていて、これが activity_main.xml ファイルをレイアウトとして登録し表示する設定です。
findViewById ( R . id . button )
これはリソースの(レイアウトファイル)からid が button のものを見つけてくることを意味します。
findViewById
findViewById は呼び出しが増えると重くなるなどプロジェクトが大きくなると問題が発生することもあり、対案としてNull安全、型安全であるView Binding を使うことができます。ただ今のところ findViewById は非推奨ではありません
次に TextView を設定します。このケースではTextViewは事前に onCreate() の前に作成します。
private TextView textView;
onCreate() の中に
textView = findViewById(R.id.textView);
その後に、ボタンがタップされた事が分かるようにリスナー登録します。
OnClickListener():
リスナー、つまりアプリが起動中に、ユーザーがボタンをタップしたイベント発生を聞き耳を立てているというようなことでしょうか。
button . setOnClickListener ( new View . OnClickListener ( ) {
@Override
public void onClick ( View view ) {
// ...
}
} ) ;
尚、lambda式を使うとよりシンプルになります。
button . setOnClickListener ( v -> {
// ...
} ) ;
lambda式は分かりにくいかもしれませんがおいおい理解していきましょう
lambda
Java8の機能の1つで関数型プログラミングを行うために導入され、Android Studio 2.4 辺りから使える...
ボタンがタップされた時の挙動を決めます。
ボタンタップされるとフラグのbuttonTapを判別して
trueなら「Hello」
falseなら「World」
が表示されるコードです
setText() でTextViewの文字列を設定
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
minSdk
targetSdk
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’」とするか
三角のアイコンをクリックするとビルドが始まります
あまりレイアウトはぱっとしませんが
とりあえず、ボタンを押すとテキストが変わるアプリができました
テキストサイズとテキストの色を指定して
少し見栄えを良くしてみます
< 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を使うようにと注意されているわけです。
例えば日本語でハードコーディングすると文字化けやコードが走らない事があり得るのです。修正は、
textView . setText ( R . string . hello ) ;
この res\values\strings.xml に
nameが”hello”というkeyに対してHelloというvalueを設定します。
< resources >
< string name = "app_name" > TestButton < / string >
< string name = "hello" > Hello < / string >
< / resources >
このワーニングはactivity_main.xmlのリテラルにも出ているので合わせて修正すると。
strings.xml
< 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
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" / >
. . .
完成です。
VIDEO
以上はJava言語で記述しましたが、Kotlin も正式に使用可能言語となりました。以上をKotolinで書くと以下のようになります。
KotlinでAndroidの Button アプリを簡単に作ってみました。
findViewByIdの代わりにAndroid Kotli...
関連ページ:
Reference:
Buttons | Android Developers