第1回 Japan Xamarin User Group Conference の発表資料です。
資料とサンプルのソースは https://github.com/amay077/jxug_1_xamarin_forms_talk
HexRinger is an Android app that allows users to turn their ringer on and off based on their location using hexagonal coordinates rather than GPS. It uses the phone's AlarmManager to check location periodically, saving battery and memory compared to other location-based apps. The app is free to download and has been downloaded over 3,000 times. Future updates may include multiple hex selection, using the accelerometer, sending emails, locking with Felica tags, and other features based on user feedback.
HexRinger is an Android app that allows users to turn their ringer on and off by selecting different hexagonal patterns. It uses WiFi and 3G location services as well as AlarmManager to save battery and memory. The developer cites GeoHex! as a strong rival but notes HexRinger is free. Future updates may include multiple hex selection, accelerometer support, email integration, and Felica locking. The app is available for download on the Android Market and the developer welcomes feedback.
41. Model(適当)
public class MyLocationModel {!
public IObservable<bool> GpsAvailable() {!
return Observable.Return(true);!
}!
!
public IObservable<LatLon> GetLocation() {!
var r = new System.Random();!
!
return Observable.Interval(TimeSpan.FromSeconds(1))!
.Select(x => new LatLon(!
34d + r.NextDouble(), !
135d + r.NextDouble()));!
}!
}
41
42. ViewModel
public class FourthViewModel : ReactiveObject {!
MyLocationModel _model = new MyLocationModel();!
!
ObservableAsPropertyHelper<LatLon> _location;!
public LatLon Location { get { return _location.Value; } }!
!
public ICommand StartGps { get; private set; }!
!
public FourthViewModel() {!
var cmd = new ReactiveCommand(_model.GpsAvailable());!
!
_location = cmd.SelectMany(_ => _model.GetLocation())!
.ToProperty(this, vm => vm.Location);!
!
this.StartGps = cmd;!
}!
}
42
43. public class FourthViewModel : ReactiveObject {!
MyLocationModel _model = new MyLocationModel();!
!
ObservableAsPropertyHelper<LatLon> _location;!
public LatLon Location { get { return _location.Value; } }!
!
public ICommand StartGps { get; private set; }!
!
public FourthViewModel() {!
var cmd = new ReactiveCommand(_model.GpsAvailable());!
!
_location = cmd.SelectMany(_ => _model.GetLocation())!
.ToProperty(this, vm => vm.Location);!
!
this.StartGps = cmd;!
}!
}
ViewModel
43
Execute されたらモデルで測位開始、
結果を逐次 Property へ
GPS が使えるなら
CanExecute = true
44. View は普通に Binding
public override void ViewDidLoad() {!
base.ViewDidLoad();!
!
this.OneWayBind(this.ViewModel, !
vm => vm.Location, v => v.LatLabel.Text, !
x => x.Lat.ToString("0.00"));!
!
this.OneWayBind(this.ViewModel, !
vm => vm.Location, v => v.LonLabel.Text, !
x => x.Lon.ToString("0.00"));!
!
this.BindCommand(this.ViewModel, !
vm => vm.StartGps, v => v.StartGpsButton);!
!
this.ViewModel = new FourthViewModel(); !
}
44
47. ViewModel
public class FifthViewModel : ReactiveObject {!
float _red;!
public float Red {!
get { return _red; } set { this.RaiseAndSetIfChanged(ref _red, value); }!
}!
/* Blue, Green は省略 */!
!
ObservableAsPropertyHelper<Color> _color;!
public Color Color { get { return _color.Value; } }!
!
public FifthViewModel() {!
var r = this.ObservableForProperty(vm => vm.Red).Select(x => x.Value);!
var g = this.ObservableForProperty(vm => vm.Green).Select(x => x.Value);!
var b = this.ObservableForProperty(vm => vm.Blue).Select(x => x.Value);!
!
_color = Observable.CombineLatest(r, g, b, !
(x, y, z) => new Color(x, y, z)).ToProperty(this, vm => vm.Color);!
}!
}
47
48. public class FifthViewModel : ReactiveObject {!
float _red;!
public float Red {!
get { return _red; } set { this.RaiseAndSetIfChanged(ref _red, value); }!
}!
/* Blue, Green は省略 */!
!
ObservableAsPropertyHelper<Color> _color;!
public Color Color { get { return _color.Value; } }!
!
public FifthViewModel() {!
var r = this.ObservableForProperty(vm => vm.Red).Select(x => x.Value);!
var g = this.ObservableForProperty(vm => vm.Green).Select(x => x.Value);!
var b = this.ObservableForProperty(vm => vm.Blue).Select(x => x.Value);!
!
_color = Observable.CombineLatest(r, g, b, !
(x, y, z) => new Color(x, y, z)).ToProperty(this, vm => vm.Color);!
}!
}
ViewModel
48
3つの値が ったら初回設定、
以降はいずれかが変わったら設定
49. View と Binding
public override void ViewDidLoad() {!
this.Bind(this.ViewModel, vm => vm.Red, v => v.RedSlider.Value);!
this.Bind(this.ViewModel, vm => vm.Green, v => v.GreenSlider.Value);!
this.Bind(this.ViewModel, vm => vm.Blue, v => v.BlueSlider.Value);!
!
this.OneWayBind(this.ViewModel, !
vm => vm.Color, !
v => v.ColorView.BackgroundColor, !
x => new UIColor(x.R, x.G, x.B, 1f));!
}
49
iOSなのでUIColorに変換
50. View で MultiBinding でも
public override void ViewDidLoad() {!
var r = this.ObservableForProperty(v => v.ViewModel.Red)!
.Select(x => x.Value);!
var g = this.ObservableForProperty(v => v.ViewModel.Green)!
.Select(x => x.Value);!
var b = this.ObservableForProperty(v => v.ViewModel.Blue)!
.Select(x => x.Value);!
!
Observable.CombineLatest(r, g, b, !
(x, y, z) => new UIColor(x, y, z, 1f))!
.ObserveOn(RxApp.MainThreadScheduler)!
.Subscribe(x => this.ColorView.BackgroundColor = x);!
}
50
UIThread で
53. スッキリ!
public class FifthViewModel {!
public ReactiveProperty<float> Red { get; private set; }!
public ReactiveProperty<float> Green { get; private set; }!
public ReactiveProperty<float> Blue { get; private set; }!
!
public ReactiveProperty<Color> Color { get; private set; }!
!
public FifthViewModel() {!
!
this.Color = Observable.CombineLatest(Red, Green, Blue, !
(x, y, z) => new Color(x, y, z)).ToReactiveProperty();!
!
}!
}
53