質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Xamarin

Xamarin(ザマリン)は、iPhoneなどのiOSやAndroidで動作し、C# 言語を用いてアプリを開発できるクロスプラットフォーム開発環境です。Xamarin Studioと C# 言語を用いて、 iOS と Android の両方の開発を行うことができます。

Q&A

解決済

1回答

888閲覧

Xamarin.Formsにてカスタムレンダラーの描画が更新されません

kamingout

総合スコア44

Xamarin

Xamarin(ザマリン)は、iPhoneなどのiOSやAndroidで動作し、C# 言語を用いてアプリを開発できるクロスプラットフォーム開発環境です。Xamarin Studioと C# 言語を用いて、 iOS と Android の両方の開発を行うことができます。

0グッド

0クリップ

投稿2017/07/22 08:54

Xamarin.Formsにてアプリケーションの開発をしています。
BoxViewのカスタムレンダラーを作成し、iOS, Android各プロジェクトでカスタムレンダラーのViewの描画処理の実装をしています。

流れ
①メインスレッドとは別のスレッドを立ち上げる。
②別スレッド内でカスタムレンダラーのバインディングプロパティを更新する。
③メインスレッド内のOnPropertyChanged関数内でAndroidは「Invalidate」、iOSは「SetNeedsDisplay」関数を呼び出す。

iOSでは上記のような流れでDraw関数に入り、描画の更新がされたのですが、
AndroidではDraw関数に処理が移行せず、描画の更新がされません。

何が原因と考えられますでしょうか?

よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

「何が原因か」はいったん置いておくとして、iOSやAndroidはViewの更新をメインスレッド(UIスレッド)で行う必要があります。
よって、当該バインディングプロパティを更新する部分をメインスレッドで実行するように変更すれば解決すると思います。

Xamarin.FormsではDevice.BeginInvokeOnMainThread()メソッドを使ってメインスレッドで処理を実行させることができます。

Device.BeginInvokeOnMainThread(() => { viewModel.ViewとBindしているプロパティ = 新しい値; });

iOSで動いているのは、ワーカースレッドで「描画の更新が必要である」ことのマークが行われ、更新自体はメインスレッドでGUIシステムが行なう、という状態になっているからだと思います。


2017/7/27 追記

見直してきました。
「BoxViewのカスタムレンダラーを作成」ということはBoxRendererか、(その基底クラスである)VisualElementRenderer<T>の派生クラスを作っていると思います。

これらのクラスはandroid.view.ViewGroupから派生しています。

ViewGroupは子Viewのレイアウトを管理するクラスなので、通常ではViewGroup自身のonDraw(Canvas)メソッドは呼ばれません。
その代わり、子Viewに描画を移譲するdispatchDraw(Canvas)が呼ばれるので、こちらを使うと思った通りの動作を実現できるかもしれません。

投稿2017/07/22 09:51

編集2017/07/26 15:31
P3PPP

総合スコア359

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kamingout

2017/07/25 15:07

ご返信ありがとうございます。 メインスレッドでバインディングプロパティを更新する必要があり、そのためにDevice.BeginInvokeOnMainThreadを使用するとのこと理解できました。 ただ、現在作成中のアプリではサブスレッド内でDevice.BeginInvokeOnMainThreadメソッドを使用してメインスレッドの処理を実行しております。 それでもAndroidでは画面更新が行われませんでした。 ネット上で検索したところ、RunOnUiThreadというメソッドなどもあるそうですが、こちらの使用が解決策になったりしないでしょうか? お手数おかけしますが、ご返信よろしくお願いいたします。
kamingout

2017/07/27 14:54

P3PPPさん ご返信ありがとうございます。 dispatchDrawメソッドを使用することでDrawを呼び出すことができました! あと、そのほかの方法としてカスタムレンダラーのDrawメソッドはデフォルトではInvalidateを記述してもOnDrawが呼び出されないそうです。 解決策としてカスタムレンダラーのコンストラクタなどでsetWillNotDraw(false)を呼び出しておくことでOnDrawが呼び出されます。 実際にそちらの方法で試してもうまくいきました。 お世話になりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問