省エネ

Flutter、vue3修行中。

【Android】GoogleMapApiを使ったのでログ

こんにちは。 今年最後のブログを書こうと思います。

12月中は常駐のお仕事を一旦お休みしてだらだら生活を送ろうと思ってたのに、 ひょんなことからGoogleMapを使うお仕事をいただいてしまったので、 結局キリキリ働いていました。

GoogleMapApiを使ったのでどんなことをしたかログを残そうと思います。

まずは導入。

1、Apiキーの取得

API キーの取得  |  Google Maps Android API  |  Google Developers

ここからApiキーを取得する必要があります。

2、アプリの設定。

一番簡単な方法は、Projectを作成する時にGoogleMapActivityを選択することですね。 これを選択してprojectを作ると下のコードは作成済みの状態になります。

f:id:qkuroneko:20171230111204p:plain

AndroidManifest.xml

    <meta-data
        android:name="com.google.android.geo.API_KEY"
        android:value="@string/google_maps_key"/>

Manifestの<application></application>に上のようにApiキーを設定します。

実際にMapが表示されるレイアウトはこんな感じです。

activity_map.xml

    <fragment
        android:id="@+id/map"
        android:name="com.google.android.gms.maps.SupportMapFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="com.linkbal.together.together_android.view.map.MapsActivity"
        />

今回はSupportMapFragmentを使いました。

MapActivity.kt

import android.support.v7.app.AppCompatActivity
import android.os.Bundle

import com.google.android.gms.maps.CameraUpdateFactory
import com.google.android.gms.maps.GoogleMap
import com.google.android.gms.maps.OnMapReadyCallback
import com.google.android.gms.maps.SupportMapFragment
import com.google.android.gms.maps.model.LatLng
import com.google.android.gms.maps.model.MarkerOptions

class MapActivity : AppCompatActivity(), OnMapReadyCallback {

    private lateinit var mMap: GoogleMap

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_maps)
        // Obtain the SupportMapFragment and get notified when the map is ready to be used.
        val mapFragment = supportFragmentManager
                .findFragmentById(R.id.map) as SupportMapFragment
        mapFragment.getMapAsync(this)
    }
    
    override fun onMapReady(googleMap: GoogleMap) {
        mMap = googleMap

        // Add a marker in Sydney and move the camera
        val sydney = LatLng(-34.0, 151.0)
        mMap.addMarker(MarkerOptions().position(sydney).title("Marker in Sydney"))
        mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney))
    }
}

ここまでできたらもう地図を表示する事が可能です。

f:id:qkuroneko:20171230114120p:plain:w300

mMap.addMarker(MarkerOptions().position(sydney).title("Marker in Sydney")) これで、地図上にマーカーを追加する事ができます。 マーカーは複数追加できるみたいです。

mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney)) これで、設定した位置情報が中心にくるようにカメラが移動します。

4、カスタマイズ

今回のお客様のご要望により、このマーカーを自分の用意した画像に変更したいとのことです。

こうします。

mMap.addMarker(MarkerOptions()
        .position(sydney)
        .icon(BitmapDescriptorFactory.fromResource(R.mipmap.ic_launcher))
        .title("Marker in Sydney")

.icon(BitmapDescriptorFactory.fromResource(R.mipmap.ic_launcher)) ここですね。

すると、ごらんの通り。

f:id:qkuroneko:20171230122025p:plain:w300

お次のご要望としては、1kmの円を描きたいとの事。

 mMap.addCircle(CircleOptions()
         .center(sydney)
         .radius(500.0)
         .strokeWidth(5f)
         .strokeColor(ContextCompat.getColor(applicationContext, R.color.colorCircleStroke))
         .fillColor(ContextCompat.getColor(applicationContext, R.color.colorCircleFill))
         .clickable(false)
)

こうします。

すると、こう。

f:id:qkuroneko:20171230150046p:plain:w300

さて、このマーカーをタップした時の反応は、デフォルトだとこうなります。 .title("Marker in Sydney")に設定している文字が吹き出しで出てきます。

f:id:qkuroneko:20171230150442p:plain:w300

今回のご要望だと、ここをカスタマイズしたいとのこと。

そんなときはこうじゃっ!

class MapInfoAdapter : InfoWindowAdapter {

    override fun getInfoContents(marker: Marker?): View {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }

    override fun getInfoWindow(marker: Marker?): View {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }

}

InfoWindowAdapterを継承したadapterクラスを作ります。

ここにlayoutをinfrateすれば吹き出しをカスタマイズできます。 getInfoWindowは表示される枠全てがinfrateされます。 getInfoContentsは吹き出しの中だけがinftateされます。 デザインに合わせてどちらを使うかを決めてください。

mMap.setInfoWindowAdapter(MapInfoAdapter())

あとは、このadapterをsetするだけ。 簡単!

これくらいならApiの機能を使って簡単に実装できたのですが、 実際はもっと色々カスタマイズしたいとのご要望をいただいていて、 結構工夫を凝らさないとできない事があったのですが、 酔っ払ってきたのでこの辺で終わりにします。

また、年明けに続きを書くかもしれません。

それでは、良いお年を。

【Kotlin】Kotlin1.2がリリースされました!

Kotlin 1.2 リリース: プラットフォーム間のコード共有 | JetBrains ブログ

1.2のリリースでKotlinで書いたコードをJVMjavascript共用できる様になるらしいです。 AndroidとWebでデザインを似た様な感じにしておけば、 データを取ってくるロジックを使いまわすことができたりするかもですね。

一人でWebもNativeもやってる人には便利かもしれない。

今、一人で実装させてもらっている某社のお仕事で、 WebをGoで作ってしまったのですが、サーバーサイドもKotlinにすればよかったとちょっと後悔中です。

次回、Webのお仕事を貰えて、言語の選択ができるなら絶対Kotlinを選びますね。

以下、JETBRAINSブログより抜粋。 >GitHubオープンソースにおけるKotlinのコード行数は2千5百万行を超えました。StackOverflowでKotlinは一番成長している言語でかつ一番嫌われていない言語です。

凄く、重要な一文だと思いますので、ご紹介させていただきました。

以上です。

【Android】findViewByIdはもういらない、そうKotlinなら

kotlinlang.org

Kotlin Android Extensionsというプラグインがありまして、 これを使うとこんな書き方ができるようです。

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.qkuronekop.sample02.MainActivity">

    <com.google.android.flexbox.FlexboxLayout
        android:id="@+id/flexLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingLeft="16dp"
        android:paddingRight="16dp" />

</LinearLayout>

MainActivity.kt

package com.example.qkuronekop.sample02

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.widget.TextView
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        (0..10).forEach {
            val textView = TextView(applicationContext).apply {
                text = "aaaaaa"
            }
            flexLayout.addView(textView)
        }

    }
}

こんな感じ。 ポイントはここ。

flexLayout.addView(textView)

xmlでつけてるidをそのまま使えます。 findViewByIdもキャストも不要でコードもスッキリです。

import kotlinx.android.synthetic.main.activity_main.*

ここを見ていただくとお分りのように、activity_mainをimportする必要がありますので、ご注意ください。

詳しい使い方は一番上にリンクした公式ページにて!

【Android】Android Studio3.0正式版リリース!

Android Studio Release Notes | Android Studio

という訳で、某社で10月の中旬頃からお仕事させていただいたいるのですが、 新規のアプリ開発をさせていただいております。

その時点では、AndroidStudio3はまだベータ版だったのですが、 新しいバージョンのGradleが使いたいということでAndroid Studio beta7で開発を始めてました。

そのかいあってか、バージョンをあげても問題なくビルドできました!

リリースまで時間がなく、ベータ版での開発に少々の不安がありましたが、 リリース前に安定版が出てよかったです。

【CSS】グリッドレイアウトの存在に気づいてしまった

遅ればせながら、グリッドレイアウトの存在に気づいてしまいました。

今お仕事で作っているWebアプリの構成が下の図の通りなのですが。

f:id:qkuroneko:20171101081126p:plain

この、レイアウトだとメニューとコンテンツのところがちょっと面倒ですよね。

html

<div>
  <div class="menu"></div>
  <div class="contents"></div>
</div>

css

.menu {
  display: inline-block;
}
.contents {
  display: inline-block;
}

今まではこうやって凌いでました。 が、メニューのところの背景に色をつけたいとクライアント様から言われちゃいまして、 どうしたもんかと悩んでおりました。

<div>だとheight%が使えず中の要素の大きさになってしまうので、 いい感じに背景色がつけられなかったのです。

そこで、グリッドレイアウトです。

html

<div class="grid">
    <header></header>
    <div class="menu"></div>
    <div class="contents"></div>
    <footer></footer>
</div>

こいつをいい感じにレイアウトします。

まずは、外枠に

.grid {
  display: grid;
}

をつけます。 で、分割方法を指定します。

.grid {
  display: grid;
  grid-template-rows: 90px 1fr 40px;
  grid-template-columns: 200px 1fr;
}

縦方向に3分割、横方向に2分割しました。

あとはどこへ配置するかを指定します。

header {
  grid-row-start: 1;
  grid-row-end: 2;
  grid-column: 1 / -1;
  background-color: #cccccc;
}

.menu {
  grid-row-start: 2;
  grid-row-end: 3;
  grid-column-start: 1;
  grid-column-end: 2;
  background-color: #ff0000;
}

.content {
  grid-row: 2 / -2;
  grid-column: 2 / -1;
  background-color: #eeeeee;
}

footer {
  grid-column: 1 / -1;
  grid-row: 3 / -1;
  background-color: #666666;
}

こんな感じ。 分割したgridは左から1,2,3とナンバリングされていきます。 右からだと-1,-2,-3とナンバリングされるようです。 上下も同様。

入れたいエリアのナンバーを指定するとそこに配置されるようになります。

f:id:qkuroneko:20171031181213p:plain

ご覧の通り。 ちょっと要素入れてみました。

メニューとコンテンツの高さはどちらかの大きい方に合わせてくれるようなので、 これでメニューのところにいい感じに背景色をつけることができました。

めでたしめでたし。

参考: CSS Grid Layout を極める!(基礎編) - Qiita

ABC2017aへ行ってきました

japan-android-group.connpass.com

 

本日はこちらのカンファレンスへ行ってきました。

 

私が聞いたセッションは以下です。

 

Google AR101(TangoからARCore、WebAR)

はじめてのActions on Google

はじめてのAndroid Things入門

あれから2年、オープンソースによるドローン開発はここまで来た!

 

 

この辺の技術は凄く興味あるのですが、

日本では技適が通ってないデバイスばかりでやりづらそうという印象。

 

 

GoogleHomeが思いの外盛り上がってるみたいなので、

GoogleAsistant上で動作するアプリとか作ってみると面白そうですね。

 

 

ReactNativeに入門しました

お仕事させていただいているお客様先で、

社内の勉強会がありまして、順番でスピーカーにならねばならないのですが、

そちらでちょっとお話させていただく機会を与えられたのですが、

何を話していいのやらネタがなくて、

とりあえず最近気になっているReactNativeについて発表してみました。

 

 

「ReactNativeに入門しました」というタイトルで発表してきました。

勉強会の3日前に慌てて環境を作り、簡単なコンポーネントを作成し、

3日でできた内容について資料をまとめて、話してきました。

 

環境を作るのはmacならとても簡単でした。

ほぼこれ通り。

facebook.github.io

 

ただ、AndroidSDKにパスを通していてもエミュレータにインストールができなかったので、AndroidStudioで作ったプロジェクトからまま拝借したlocal.propatiesファイルを使いました。

 

作ったもの

github.com

 

まだちょっとしか触っていないので良くわかっていないのですが、

CSSはReactNativeが用意しているものしか使えないのでしょうか。

エラーになって使えないものがあったのですが、

何かやり方があるんでしょうか。

 

ちょっと良くわからないので、今後も引き続き勉強していこうと思います。