この記事は「Androidアプリ開発 これどうやって実装するんだっけ?」の第一回です。
メインターゲットは私のような「そろそろググることを覚えた初中級者」を(勝手に)想定しています。
JavaとKotlinの両方について解説しているので、「Javaでの実装はわかるけど、Kotlinだとどう書くの?」という人にも
お役に立つかと思います。
本企画のサンプルは下のリンクにあります。masterブランチがKotlinのソースコード、javaブランチがJavaのソースコードです。
Buttonの実装
Androidアプリ開発を始めてまず最初に感動するところかと思っています。
サンプルとして、
- Buttonを押したらtextが変わる
- Floating Action Buttonを押したらSnack barが表示される
というのをやってみました。
環境
Android Studio 3.0+
Android 8.0で動作確認
Floating Action Buttonを使うので、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のとき
<?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を使わなくても大丈夫です。位置指定は↓の感じでやれば大丈夫。
<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を省略しています)
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処理が複数ある場合
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処理が一つの場合
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処理が複数ある場合
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ユーザーの皆さんからも需要があればコメント頂けると嬉しいです
間違い等あれば修正リクエストの方して頂けると助かります。