Edited at

Androidアプリ開発(Java, Kotlin両対応) これどうやって実装するんだっけ? 〜Button編〜

More than 1 year has passed since last update.

この記事は「Androidアプリ開発 これどうやって実装するんだっけ?」の第一回です。

メインターゲットは私のような「そろそろググることを覚えた初中級者」を(勝手に)想定しています。


JavaとKotlinの両方について解説しているので、「Javaでの実装はわかるけど、Kotlinだとどう書くの?」という人にも

お役に立つかと思います。

本企画のサンプルは下のリンクにあります。masterブランチがKotlinのソースコード、javaブランチがJavaのソースコードです。

https://github.com/Dai1678/SampleCodePrograms


Buttonの実装

Androidアプリ開発を始めてまず最初に感動するところかと思っています。

サンプルとして、


  • Buttonを押したらtextが変わる

  • Floating Action Buttonを押したらSnack barが表示される

というのをやってみました。


環境

Android Studio 3.0+

Android 8.0で動作確認

Floating Action Buttonを使うので、Gradleファイルに以下の文を追加してください。


build.gradle

apply plugin: 'com.android.application'

apply plugin: 'kotlin-android'

apply plugin: 'kotlin-android-extensions'

android {
compileSdkVersion 27
defaultConfig {
applicationId "net.ddns.dai.samplecodeprograms"
minSdkVersion 15
targetSdkVersion 27
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}

dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
implementation 'com.android.support:appcompat-v7:27.1.0'
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
implementation 'com.android.support:design:27.1.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
}



動作デモ


XMLの解説

rootタグを何にするかでFloatingActionButton周りの書き方が少し違ってきます。

作っているアプリのレイアウトに合わせて見てください。


  • LinearLayoutのとき


activity_button_sample.xml

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout
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:orientation="vertical"
tools:context="net.ddns.dai.samplecodeprograms.ButtonSampleActivity">

<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Buttonの実装について" />

<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:id="@+id/changeText"
android:text="押してください"/>

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:id="@+id/textChangeButton"
android:text="Button"/>

</LinearLayout>

<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/fab_margin"
app:srcCompat="@android:drawable/btn_star" />

<!-- @dimen/fab_margin -> 16dp -->

</FrameLayout>

</LinearLayout>


大事なところはコンテンツ部分をFrameLayoutで囲っているところ。

FrameLayoutはViewを重ねて表示したいときに使います。Floating Action Buttonがあるからね。

注意しなければならないのは、このLayout内のコンポーネントは位置指定ができない(全部左上に表示)ので、

この中にLinearLayoutを入れるなどしてコンポーネントを配置していってください。

この場合のFloating Action Buttonの位置指定は、android:layout_gravity="bottom|end"とするとイイ感じになります。


  • RelativeLayoutのとき

相対位置での配置ができるので、FrameLayoutを使わなくても大丈夫です。位置指定は↓の感じでやれば大丈夫。


activity_button_sample.xml

<android.support.design.widget.FloatingActionButton

android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_margin="@dimen/fab_margin"
app:srcCompat="@android:drawable/ic_dialog_email" />


  • CoordinatorLayoutのとき

後々の回で説明しますが、FloatingActionButtonについてはRelative Layoutと同様に考えてもらって大丈夫です。

Activityを新規作成するときにBasic Activityを選択するとデフォルトでこれが使われています。

さらにかっこよく使いたい人はこっちを使うと良いかも?


Activityの解説

buttonの処理については様々な記述方法があると思います。

僕が使い分けているのは2通り。

JavaとKotlinでそれぞれソースコードを交えて簡単に解説します。


Java編


  • Button処理が一つの場合 (例としてFloatingActionButtonを省略しています)


ButtonSampleActivity.java

public class ButtonSampleActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_button_sample);

ActionBar actionBar = getSupportActionBar();
if (actionBar != null){
actionBar.setDisplayHomeAsUpEnabled(true);
}

boolean flag = false;

Button button = findViewById(R.id.textChangeButton);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
TextView textView = findViewById(R.id.changeText);

if (flag){
textView.setText("押してください");
button.setText("BUTTON");
flag = false;

}else{
textView.setText("Buttonが押されました!");
button.setText("戻す");
flag = true;
}
}
});
}
}


多くのWebサイトで掲載されているサンプルコードやAndroid Developersなどでよく紹介されているやり方です。

onCreateメソッド内で匿名クラスを使っています。

Buttonが1,2個とかであればこのやり方で済ませて良いと思います。


  • Button処理が複数ある場合


ButtonSampleActivity.java

public class ButtonSampleActivity extends AppCompatActivity implements View.OnClickListener {

Button button;
boolean flag = false;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_button_sample);

ActionBar actionBar = getSupportActionBar();
if (actionBar != null){
actionBar.setDisplayHomeAsUpEnabled(true);
}

button = findViewById(R.id.textChangeButton);
button.setOnClickListener(this);

FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener(this);

}

@Override
public void onClick(View view) {
switch (view.getId()){

case R.id.textChangeButton:
TextView textView = findViewById(R.id.changeText);

if (flag){
textView.setText("押してください");
button.setText("BUTTON");
flag = false;

}else{
textView.setText("Buttonが押されました!");
button.setText("戻す");
flag = true;
}

break;

case R.id.fab:
Snackbar.make(view, "fabが押されました!", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
break;
}
}
}


匿名クラスを使用しない場合は、OnClickListenerをimplementsします。まずは1行目のところに書いてください。

赤線でエラーが出ている場合、Android Studio上で赤バルーンがpublick void onClick(View view){}というメソッドを

作るよう要求してくるので、実行すれば自動的にメソッドを作ってくれます。(自分で記述しても可)

onClickメソッド内では、view.getId()でxmlで指定したButtonのidを取得して処理を分けています。

忘れがちなのがfindViewByIdと、setOnClickListener(this)です。気をつけて!

(Butter KnifeやData Bidingを利用すると簡略化できますが、既存の書き方から大きく変わってしまうのが嫌だったので

導入していません。)


Kotlin編

build.gradleにも書いてありますが、こちらではkotlin-android-extensionsを導入しています。

これがかなり便利で、xmlで指定したidの名前をそのまま利用でき、なおかつコード量もとても少なくできます。


  • Button処理が一つの場合


ButtonSampleActivity.kt

class ButtonSampleActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_button_sample)

val actionBar = supportActionBar
actionBar!!.setDisplayHomeAsUpEnabled(true)

var flag = false

//kotlin-android-extensionsのおかげでfindViewByIdの一文を書かなくてもxmlのidで指定できる!!
textChangeButton.setOnClickListener { view ->
flag = if (flag){
changeText.text = "押してください"
textChangeButton.text = "BUTTON"
false

}else{
changeText.text = "Buttonが押されました"
textChangeButton.text = "戻す"
true
}
}

}
}


Javaのソースコードよりすっごいスッキリしてますよね?

findViewByIdや無駄なnullチェック、onClick、そしてセミコロンがない!

よし今すぐKotlinを始めよう()


  • Button処理が複数ある場合


ButtonSampleActivity.kt

class ButtonSampleActivity : AppCompatActivity(), View.OnClickListener {

private var flag = false

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_button_sample)

val actionBar = supportActionBar
actionBar!!.setDisplayHomeAsUpEnabled(true)

//kotlin-android-extensionsのおかげでfindViewByIdの一文を書かなくてもxmlのidで指定できる!!
textChangeButton.setOnClickListener(this)
fab.setOnClickListener(this)

}

override fun onClick(view: View) {

when (view.id){ //switch文はないのでwhen文を使う
R.id.textChangeButton -> {
this.flag = if (flag){
changeText.text = "押してください"
textChangeButton.text = "BUTTON"
false

}else{
changeText.text = "Buttonが押されました"
textChangeButton.text = "戻す"
true
}
}

R.id.fab -> {
Snackbar.make(view, "fabが押されました!", Snackbar.LENGTH_LONG)
.setAction("Action", null).show()
}
}
}
}


こちらも同様にonClickメソッドをonCreateメソッドの外に書く手法です。

このソースコードについてJavaとの違いで気をつけたいのは、


  • implementsとは書かずにカンマで追加する

  • Kotlinにはswitch文が存在しないのでwhen文を使用

  • var, valの型推論

といったところでしょうか。


参考

Kotlinの魅力と記法について細かく書かれています


次回予告

TextViewやEditTextなどのテキスト周りを書きます。


あとがき

大学の後輩などにも見せたいですが、Qiitaユーザーの皆さんからも需要があればコメント頂けると嬉しいです

間違い等あれば修正リクエストの方して頂けると助かります。