こんばんは。sunn-sudoです。
前回に引き続き、ユーザインターフェイスの改良を行いました。
グーグルマップのアプリと連携して、検索を楽にする個人用Androidアプリをご紹介いたします。
前回の内容は以下の記事となりますので、ご覧ください。
https://qiita.com/sunn-sudo/items/6bef0f7169b73d4e06e2
画面レイアウト
メイン画面
【ボタン】
検索ワードを追加する: 検索ワード登録画面へ遷移するボタン
【リスト内】
検索ボタン: タップしたボタンのテキストをグーグルマップに連携する
削除ボタン(✖ボタン): タップしたリストを削除する
検索ワード登録画面
【入力フォーム】
登録ボタン: 入力内容を検索ワードとして登録する。
※空文字の登録不可
ソースコード
メイン画面
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="AppGoogleMap.MainPage"
Title="メイン画面">
<StackLayout Margin="10">
<Label Text="現在地周辺のスポットを検索します。" />
<Button Text="検索ワードを追加する" Clicked="NextPage"/>
<ListView
x:Name="wordList"
HasUnevenRows="true">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout
HorizontalOptions="FillAndExpand"
Orientation="Horizontal">
<StackLayout
Orientation="Vertical">
<Label Text="{Binding TimeStamp}" />
<Button Text="{Binding Word}" Clicked="OnButtonSearch" />
</StackLayout>
<Button
WidthRequest="40"
HeightRequest="40"
Text="✖"
BackgroundColor="Silver"
VerticalOptions="Center"
HorizontalOptions="EndAndExpand"
CommandParameter="{Binding .}"
Clicked="OnButtonDelete"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
using System;
using Xamarin.Essentials;
using Xamarin.Forms;
using Plugin.Geolocator;
using Plugin.Geolocator.Abstractions;
using System.Collections.ObjectModel;
namespace AppGoogleMap
{
public class SearchWord
{
[SQLite.PrimaryKey, SQLite.AutoIncrement]
public int Id { get; set; }
public String Word { get; set; }
public DateTime TimeStamp { get; set; }
}
// リスト1件のデータを表すクラス
public class SearchWordList
{
public int Id { get; set; }
public string Word { get; set; }
public string TimeStamp { get; set; }
public SearchWordList(int Id, string Word, string TimeStamp)
{
this.Id = Id;
this.Word = Word;
this.TimeStamp = TimeStamp;
}
}
public partial class MainPage : ContentPage
{
public static string DbPath { get; }
= System.IO.Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
, "SQLiteDataBase.db");
public static ObservableCollection<SearchWordList> WordListData { get; set; }
= new ObservableCollection<SearchWordList>();
public MainPage()
{
InitializeComponent();
// ListViewの初期化
WordListData = new ObservableCollection<SearchWordList>();
// データベース初期設定
using (var db = new SQLite.SQLiteConnection(DbPath))
{ // テーブル作成
db.CreateTable<SearchWord>();
// データ取得
foreach (var row in db.Table<SearchWord>())
{
WordListData.Add(new SearchWordList(row.Id, row.Word, row.TimeStamp.ToString()));
}
}
// ListViewにデータソースをセット
wordList.ItemsSource = WordListData;
}
async void OnButtonSearch(object sender, EventArgs e)
{
if (Device.RuntimePlatform == Device.Android)
{
try
{
IGeolocator locator = CrossGeolocator.Current;
// 1. 50mの精度に指定
// locator.DesiredAccuracy = 50;
Position position = await locator.GetPositionAsync();
string result = position.Latitude.ToString() + ',' + position.Longitude.ToString();
string search_text = ((Button)sender).Text;
await Launcher.OpenAsync("geo:" + result + "?q=" + search_text);
}
catch
{
await DisplayAlert("確認", "位置情報をオンにしてください。", "OK");
}
}
}
private void OnButtonDelete(object sender, EventArgs e)
{
SearchWordList remove_list = (SearchWordList)((Button)sender).CommandParameter;
using (var db = new SQLite.SQLiteConnection(MainPage.DbPath))
{
db.Delete<SearchWord>(remove_list.Id);
}
WordListData.Remove(remove_list);
}
private void NextPage(object sender, EventArgs e)
{
Navigation.PushAsync(new SubPage());
}
}
}
検索ワード登録画面
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="AppGoogleMap.SubPage"
Title="検索ワード登録画面">
<StackLayout>
<Label Text="登録する検索ワードを入力してください。" />
<Entry x:Name="insertText" Placeholder="登録内容" MaxLength="100" />
<Button Text="登録" Clicked="OnButtonInsert" />
</StackLayout>
</ContentPage>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace AppGoogleMap
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class SubPage : ContentPage
{
public SubPage()
{
InitializeComponent();
}
private void OnButtonInsert(object sender, EventArgs e)
{
// 登録制限
if (insertText.Text == null || insertText.Text == "")
{
// 登録成功アラート
DisplayAlert("登録失敗", "入力文字が空です。", "OK");
return;
}
DateTime temp_now = DateTime.Now;
String temp_word = insertText.Text;
// データ追加
using (var db = new SQLite.SQLiteConnection(MainPage.DbPath))
{
db.Insert(new SearchWord() {TimeStamp = temp_now, Word = temp_word});
foreach (var row in db.Query<SearchWord>("select Id, Word, TimeStamp from SearchWord where ROWID = last_insert_rowid();"))
{
MainPage.WordListData.Add(new SearchWordList(row.Id, row.Word, row.TimeStamp.ToString()));
}
}
// 登録成功アラート
DisplayAlert("登録成功", insertText.Text + "を登録しました。", "OK");
}
}
}
参考サイト
【Xamarin Forms で SQLite を使う】
https://rksoftware.hatenablog.com/entry/2018/01/01/135248
【Xamarin.Formsで画面遷移を実装】
https://rainbow-engine.com/xamarin-page-transition/
【Xamarin.Forms ListViewのデータソース更新時にUIを更新させる方法】
https://qiita.com/chooyan_eng/items/35594efea1bd5109b0f4
【Xamarinでデバイスの許可をアプリのダイアログで行う方法】
※位置情報権限を許可するために参考にした
https://intellectual-curiosity.tokyo/2020/01/09/xamarin%E3%81%A7%E3%83%87%E3%83%90%E3%82%A4%E3%82%B9%E3%81%AE%E8%A8%B1%E5%8F%AF%E3%82%92%E3%82%A2%E3%83%97%E3%83%AA%E3%81%AE%E3%83%80%E3%82%A4%E3%82%A2%E3%83%AD%E3%82%B0%E3%81%A7%E8%A1%8C%E3%81%86/
この記事のコード
コードはGitHubで公開しております。