Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
8
Help us understand the problem. What is going on with this article?
@e-takazawa

KotlinでマテリアルデザインのViewを実装する

More than 3 years have passed since last update.

ディップ Advent Calendarの20日目です。

前回の続きになります。

せっかくなので、Kotlinでマテリアルデザイン関連のViewを実装するにはどうすればいいのか調べてみました。
基本的にはJavaで書いたソースコードをKotlinのプラグインに食わせるとKotlinに変換してくれるので、変換されたコードをKotlinっぽく書き直せるところは書き直してみます。
⇒というテーマで記事を書こうとしたのですが、KotlinプラグインのJava⇒Kotlinコード変換機能は大変優秀だったので、Null安全にかかわる変数宣言の辺り以外はほとんど直すところなかったです、Kotlinえらい。

Floating Action Button

Javaで書く場合

レイアウトファイルは基本的にJavaだろうとKotlinだろうと変わらないはず。

fragment_layout.xml
<android.support.design.widget.CoordinatorLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/blue_grey_600"
        android:transitionGroup="false">

    <include layout="@layout/map_description" />

    <android.support.design.widget.FloatingActionButton
            android:id="@+id/fab"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:srcCompat="@drawable/ic_panorama"
            android:contentDescription="@string/action_panorama"
            android:visibility="invisible"/>

</android.support.design.widget.CoordinatorLayout>
MyFragment.java
package com.samples.fragment;

import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.transition.ChangeBounds;
import android.transition.Fade;
import android.transition.Transition;
import android.transition.TransitionInflater;
import android.transition.TransitionManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class MyFragment extends Fragment {

    public static final String TAG = "MyFragment";
    private FloatingActionButton mFloatingActionButton;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View contentView = inflater.inflate(R.layout.fragment_layout, container, false);
        mFloatingActionButton = (FloatingActionButton) contentView.findViewById(R.id.fab);
        mFloatingActionButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Log.d(TAG, "FAB Pushed");
            }
        });
        return contentView;
    }
}

Kotlinで書く場合

Kotlinのプラグインに食わせると以下のコードを吐き出してくれますが、直せるところは直してみる。

MyFragment.kt(プラグインが変換した直後)
class DetailFragment : Fragment(), DataView<Detail> {
    private var mFloatingActionButton: FloatingActionButton? = null

    override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
        val contentView = inflater!!.inflate(R.layout.fragment_detail, container, false)
        mFloatingActionButton = contentView.findViewById(R.id.fab) as FloatingActionButton
        mFloatingActionButton!!.setOnClickListener(View.OnClickListener {
            Log.d(TAG, "FAB Pushed")
        })
        return contentView
    }
}

View.OnClickListener自体はJavaのコードなので、SAM変換が使えます。
View.OnClickListenerをview ->に変えても大丈夫です。

MyFragment.kt(SAMに修正)
class DetailFragment : Fragment(), DataView<Detail> {
    private var mFloatingActionButton: FloatingActionButton? = null

    override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
        val contentView = inflater!!.inflate(R.layout.fragment_detail, container, false)
        mFloatingActionButton = contentView.findViewById(R.id.fab) as FloatingActionButton

        // View.OnClickListenerをview ->に変える
        mFloatingActionButton?.setOnClickListener {view ->
            Log.d(TAG, "FAB Pushed")
        }
        return contentView
    }
}

Navigation Drawer

Navigation DrawerはJavaとKotlinの実装の差異はほとんどない様子。

Javaで書く場合

MainActivity.java
package com.sample.activity;

import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.view.View;
import android.support.design.widget.NavigationView;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;

public class MainActivity extends AppCompatActivity
        implements NavigationView.OnNavigationItemSelectedListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawer.setDrawerListener(toggle);
        toggle.syncState();

        NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
        navigationView.setNavigationItemSelectedListener(this);
    }

    @Override
    public void onBackPressed() {
        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        if (drawer.isDrawerOpen(GravityCompat.START)) {
            drawer.closeDrawer(GravityCompat.START);
        } else {
            super.onBackPressed();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @SuppressWarnings("StatementWithEmptyBody")
    @Override
    public boolean onNavigationItemSelected(MenuItem item) {
        // Handle navigation view item clicks here.
        int id = item.getItemId();

        if (id == R.id.nav_camera) {
            // Handle the camera action
        } else if (id == R.id.nav_gallery) {

        } else if (id == R.id.nav_slideshow) {

        } else if (id == R.id.nav_manage) {

        } else if (id == R.id.nav_share) {

        } else if (id == R.id.nav_send) {

        }

        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        drawer.closeDrawer(GravityCompat.START);
        return true;
    }
}

Kotlinで書く場合

MainActivity.kt
package com.sample.activity

import android.os.Bundle
import android.support.design.widget.FloatingActionButton
import android.support.design.widget.Snackbar
import android.view.View
import android.support.design.widget.NavigationView
import android.support.v4.view.GravityCompat
import android.support.v4.widget.DrawerLayout
import android.support.v7.app.ActionBarDrawerToggle
import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.Toolbar
import android.view.Menu
import android.view.MenuItem

class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val toolbar = findViewById(R.id.toolbar) as Toolbar
        setSupportActionBar(toolbar)

        val drawer = findViewById(R.id.drawer_layout) as DrawerLayout
        val toggle = ActionBarDrawerToggle(
                this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close)
        drawer.setDrawerListener(toggle)
        toggle.syncState()

        val navigationView = findViewById(R.id.nav_view) as NavigationView
        navigationView.setNavigationItemSelectedListener(this)
    }

    override fun onBackPressed() {
        val drawer = findViewById(R.id.drawer_layout) as DrawerLayout
        if (drawer.isDrawerOpen(GravityCompat.START)) {
            drawer.closeDrawer(GravityCompat.START)
        } else {
            super.onBackPressed()
        }
    }

    override fun onCreateOptionsMenu(menu: Menu): Boolean {
        // Inflate the menu; this adds items to the action bar if it is present.
        menuInflater.inflate(R.menu.main, menu)
        return true
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        val id = item.itemId


        if (id == R.id.action_settings) {
            return true
        }

        return super.onOptionsItemSelected(item)
    }

    override fun onNavigationItemSelected(item: MenuItem): Boolean {
        // Handle navigation view item clicks here.
        val id = item.itemId

        if (id == R.id.nav_camera) {
            // Handle the camera action
        } else if (id == R.id.nav_gallery) {

        } else if (id == R.id.nav_slideshow) {

        } else if (id == R.id.nav_manage) {

        } else if (id == R.id.nav_share) {

        } else if (id == R.id.nav_send) {

        }

        val drawer = findViewById(R.id.drawer_layout) as DrawerLayout
        drawer.closeDrawer(GravityCompat.START)
        return true
    }
}

Activity Transition

Javaで書く場合

こちらを参照。
基本的にstyle.xmlとかAndroidManifest.xmlの設定、layout.xml周りはKotlinで書くにしても特に変わりはない様子。

Kotlinで書く場合

ActivityOptionsCompat.makeSceneTransitionAnimationを実行する箇所はJavaとはそれほど変わりがないですね。
Intentのインスタンス化もJavaでは
Intent intent = new Intent(MainActivity.this, ImaveDetailActivity.class);ですが、
Kotlinではval intent = Intent(this, ImageDetailActivity::class.java)でいけるようです。

MainActivity.kt

class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener {

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

        //imageview
        val imageview = findViewById(R.id.imageview_content) as ImageView
        imageview.setOnClickListener { view ->
            val options = ActivityOptionsCompat.makeSceneTransitionAnimation(
                    this,
                    findViewById(R.id.imageview_content),
                    getString(R.string.trans_name))
            val intent = Intent(this, ImageDetailActivity::class.java)
            ActivityCompat.startActivity(this, intent, options.toBundle())

        }
    }
}

さいごに

まずはJavaで無駄な処理を書いていない綺麗なコードで実装して、プラグインで変換するとKotlinのコードができるので、それを見て学習するのがいいかもですね。
Kotlinかわいい。

8
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
e-takazawa
WEBサイト開発チームでマネジメントを担当しています。(WEBサイト自体はLaravelです。) Java、CakePHP、Androidの開発を経験して、iOS/Android開発チームのマネージャーになった後、現在のポジションにいます。
dip-net
ディップ株式会社は「バイトル」「はたらこねっと」などの求人情報サービスをはじめ、人工知能専門メディア「AINOW」、スタートアップ専門メディア「スタートアップタイムズ」、アニメなどの舞台を紹介するサイト「聖地巡礼マップ」といった新しい分野のサービスを自社で開発・運営しています。

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
8
Help us understand the problem. What is going on with this article?