2017-08-22 16 views
0

enter image description hereボタンがクリックされません - Xamarinは

こんにちは皆を形成して、私は上のスクリーンショットに示すようにxamarinフォームでカスタム情報ウィンドウを作成する必要がありました。私はそれのためのカスタムレンダラーを作成しましたが、今私が持っている問題は、ボタンがクリックされていないということです。 Xamarinはinfo-window全体をクリック可能なビューとして利用しています。私が間違っていることを教えてください、またはXamarinフォームでボタンのクリックを達成することが可能ですか?前もって感謝します。ここで

は、カスタムレンダラのためのコードです:

using System; 
using System.Collections.Generic; 
using Android.Content; 
using Android.Gms.Maps; 
using Android.Gms.Maps.Model; 
using Xamarin.Forms; 
using Xamarin.Forms.Maps; 
using Xamarin.Forms.Maps.Android; 
using SalesApp.Droid.CustomRenderer; 
using Android.Widget; 
using SalesApp.CustomControls; 
using SalesApp.Droid.Listeners; 

[assembly: ExportRenderer(typeof(CustomMap), typeof(CustomMapRenderer))] 
namespace SalesApp.Droid.CustomRenderer 
{ 
    public class CustomMapRenderer : MapRenderer, GoogleMap.IInfoWindowAdapter, IOnMapReadyCallback 
    { 
     GoogleMap map; 
     List<CustomPin> customPins; 
     bool isDrawn; 

     protected override void OnElementChanged(Xamarin.Forms.Platform.Android.ElementChangedEventArgs<Map> e) 
     { 
      base.OnElementChanged(e); 

      if (e.OldElement != null) 
      { 
       map.InfoWindowClick -= OnInfoWindowClick; 
      } 

      if (e.NewElement != null) 
      { 
       var formsMap = (CustomMap)e.NewElement; 
       customPins = formsMap.CustomPins 
       Control.GetMapAsync(this); 
      } 
     } 

     public void OnMapReady(GoogleMap googleMap) 
     { 
      map = googleMap; 
      map.InfoWindowClick += OnInfoWindowClick; 
      map.SetInfoWindowAdapter(this); 
     } 

     protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) 
     { 
      base.OnElementPropertyChanged(sender, e); 
      if (e.PropertyName.Equals("VisibleRegion") && !isDrawn) 
      { 
       map.Clear(); 

       if (customPins != null) 
       { 
        foreach (var pin in customPins) 
        { 
         var marker = new MarkerOptions(); 
         marker.SetPosition(new LatLng(pin.Pin.Position.Latitude, pin.Pin.Position.Longitude)); 
         marker.SetTitle(pin.Pin.Label); 
         marker.SetSnippet(pin.Pin.Address); 
         marker.SetIcon(BitmapDescriptorFactory.FromResource((int)typeof(Resource.Drawable).GetField(pin.Image).GetValue(null))); 

         map.AddMarker(marker); 
        } 
        isDrawn = true; 
       } 
      } 
     } 

     protected override void OnLayout(bool changed, int l, int t, int r, int b) 
     { 
      base.OnLayout(changed, l, t, r, b); 

      if (changed) 
      { 
       isDrawn = false; 
      } 
     } 

     void OnInfoWindowClick(object sender, GoogleMap.InfoWindowClickEventArgs e) 
     { 
      var customPin = GetCustomPin(e.Marker); 
      if (customPin == null) 
      { 
       throw new Exception("Custom pin not found"); 
      } 

      //if (!string.IsNullOrWhiteSpace(customPin.Url)) 
      //{ 
      // var url = Android.Net.Uri.Parse(customPin.Url); 
      // var intent = new Intent(Intent.ActionView, url); 
      // intent.AddFlags(ActivityFlags.NewTask); 
      // Android.App.Application.Context.StartActivity(intent); 
      //} 

      Android.App.Application.Context.StartActivity(new Intent(Android.App.Application.Context, typeof(DialogActivity))); 

     } 

     void IOnMapReadyCallback.OnMapReady(GoogleMap googleMap) 
     { 
      InvokeOnMapReadyBaseClassHack(googleMap); 
      map = googleMap; 
      map.SetInfoWindowAdapter(this); 
      map.InfoWindowClick += OnInfoWindowClick; 
     } 

     public Android.Views.View GetInfoContents(Marker marker) 
     { 
      var inflater = Android.App.Application.Context.GetSystemService(Context.LayoutInflaterService) as Android.Views.LayoutInflater; 
      if (inflater != null) 
      { 
       Android.Views.View view; 

       var customPin = GetCustomPin(marker); 
       if (customPin == null) 
       { 
        throw new Exception("Custom pin not found"); 
       } 

       if (customPin.Id == "Xamarin") 
       { 
        view = inflater.Inflate(Resource.Layout.XamarinMapInfoWindow, null); 
       } 
       else 
       { 
        view = inflater.Inflate(Resource.Layout.MapInfoWindow, null); 
       } 

       var infoTitle = view.FindViewById<TextView>(Resource.Id.InfoWindowTitle); 
       var address = view.FindViewById<TextView>(Resource.Id.Address); 
       var contactPerson = view.FindViewById<TextView>(Resource.Id.ContactPerson); 
       var phone = view.FindViewById<TextView>(Resource.Id.Phone); 
       var zip = view.FindViewById<TextView>(Resource.Id.Zip); 
       var email = view.FindViewById<TextView>(Resource.Id.Email); 
       var cvr = view.FindViewById<TextView>(Resource.Id.CVR); 
       var turnover = view.FindViewById<TextView>(Resource.Id.Turnover); 
       var noOfEmp = view.FindViewById<TextView>(Resource.Id.NoOfEmp); 
       var leadStatus = view.FindViewById<TextView>(Resource.Id.LeadStatus); 
       var category = view.FindViewById<TextView>(Resource.Id.Cat); 

       if (infoTitle != null) 
       { 
        infoTitle.Text = customPin.LeedsAndCustomersData.FullName; 
       } 
       if (address != null) 
       { 
        address.Text = customPin.LeedsAndCustomersData.Address + " " + customPin.LeedsAndCustomersData.CityName; 
       } 
       if (contactPerson != null) 
       { 
        contactPerson.Text = customPin.LeedsAndCustomersData.FirstName; 
       } 
       if (phone != null) 
       { 
        phone.Text = customPin.LeedsAndCustomersData.Phone; 
       } 
       if (zip != null) 
       { 
        zip.Text = customPin.LeedsAndCustomersData.ZipCode; 
       } 
       if (email != null) 
       { 
        email.Text = customPin.LeedsAndCustomersData.Email; 
       } 
       if (cvr != null) 
       { 
        cvr.Text = customPin.LeedsAndCustomersData.CVR; 
       } 
       if (turnover != null) 
       { 
        turnover.Text = customPin.LeedsAndCustomersData.Turnover; 
       } 
       if (noOfEmp != null) 
       { 
        noOfEmp.Text = customPin.LeedsAndCustomersData.NoOfEmployees.ToString(); 
       } 
       if (leadStatus != null) 
       { 
        leadStatus.Text = customPin.LeedsAndCustomersData.LeadStatus; 
       } 
       if (category != null) 
       { 
        category.Text = customPin.LeedsAndCustomersData.BusinessType; 
       } 

       //add listeners 
       OnTouchPhoneListener callButtonListener = new OnTouchPhoneListener(); 
       phone.SetOnTouchListener(callButtonListener); 

       return view; 
      } 
      return null; 
     } 

     public Android.Views.View GetInfoWindow(Marker marker) 
     { 
      return null; 
     } 

     CustomPin GetCustomPin(Marker annotation) 
     { 
      var position = new Position(annotation.Position.Latitude, annotation.Position.Longitude); 
      foreach (var pin in customPins) 
      { 
       if (pin.Pin.Position == position) 
       { 
        return pin; 
       } 
      } 
      return null; 
     } 

     void InvokeOnMapReadyBaseClassHack(GoogleMap googleMap) 
     { 
      System.Reflection.MethodInfo onMapReadyMethodInfo = null; 

      Type baseType = typeof(MapRenderer); 
      foreach (var currentMethod in baseType.GetMethods(System.Reflection.BindingFlags.NonPublic | 
                  System.Reflection.BindingFlags.Instance | 
                   System.Reflection.BindingFlags.DeclaredOnly)) 
      { 
       if (currentMethod.IsFinal && currentMethod.IsPrivate) 
       { 
        if (string.Equals(currentMethod.Name, "OnMapReady", StringComparison.Ordinal)) 
        { 
         onMapReadyMethodInfo = currentMethod; 
         break; 
        } 

        if (currentMethod.Name.EndsWith(".OnMapReady", StringComparison.Ordinal)) 
        { 
         onMapReadyMethodInfo = currentMethod; 
         break; 
        } 
       } 
      } 

      if (onMapReadyMethodInfo != null) 
      { 
       onMapReadyMethodInfo.Invoke(this, new[] { googleMap }); 
      } 
     } 
    } 
} 

OnInfoWindowElemTouchListener:

using Android.OS; 
using Android.Views; 
using Android.Widget; 
using System.Threading.Tasks; 
using Android.Gms.Maps.Model; 
using Android.Graphics.Drawables; 
using Java.Lang; 

namespace SalesApp.Droid.Listeners 
{ 
    public abstract class OnInfoWindowElemTouchListener : Java.Lang.Object, View.IOnTouchListener 
    { 
     private View view; 

     private Drawable bgDrawableNormal; 
     private Drawable bgDrawablePressed; 
     private Handler handler = new Handler(); 
     private Marker marker; 
     private static bool endPressStatus = false; 
     private bool pressed = false; 


     //public OnInfoWindowElemTouchListener(View view, Drawable bgDrawableNormal, Drawable bgDrawablePressed) 
     //{ 
     // this.view = this.view; 
     // this.bgDrawableNormal = this.bgDrawableNormal; 
     // this.bgDrawablePressed = this.bgDrawablePressed; 
     //} 

     public OnInfoWindowElemTouchListener(View view) 
     { 
      this.view = this.view; 
     } 

     public OnInfoWindowElemTouchListener(Button button) 
     { 

     } 
     public OnInfoWindowElemTouchListener() 
     { 

     } 

     public void setMarker(Marker marker) 
     { 
      this.marker = this.marker; 
     } 

     /*public bool OnTouch(View v, MotionEvent e) 
     { 
      if (e.Action == MotionEventActions.Down) 
      { 
       // do stuff 
       return true; 
      } 
      if (e.Action == MotionEventActions.Up) 
      { 
       // do other stuff 
       return true; 
      } 

      return false; 
     }*/ 


     public bool OnTouch(View vv, MotionEvent e) 
     { 
      if (0 <= e.GetX() && e.GetX() <= vv.Width && 0 <= e.GetY() && e.GetY() <= vv.Height) 
      { 
       switch (e.ActionMasked) 
       { 
        case MotionEventActions.Down: 
         startPress(); 
         break; 

        // We need to delay releasing of the view a little so it shows the 
        // pressed state on the screen 
        case MotionEventActions.Up: 
         //handler.PostDelayed(ConfirmClickRunnable, 150); 
         //Task.Factory.StartNew(() =>onClickConfirmed(view, marker)); 
         Task.Factory.StartNew(() => onClickConfirmed()); 
         Task.Delay(150); 
         break; 

        case MotionEventActions.Cancel: 
         endPress(); 
         break; 
        default: 
         break; 
       } 
      } 
      else 
      { 
       // If the touch goes outside of the view's area 
       // (like when moving finger out of the pressed button) 
       // just release the press 
       endPress(); 
      } 

      return false; 
     } 


     private void startPress() 
     { 
      if (!pressed) 
      { 
       pressed = true; 
       //handler.RemoveCallbacks(ConfirmClickRunnable); 

       if ((marker != null)) 
       { 
        marker.ShowInfoWindow(); 
       } 

      } 

     } 

     public bool endPress() 
     { 
      if (pressed) 
      { 
       this.pressed = false; 
       //handler.RemoveCallbacks(ConfirmClickRunnable); 
       view.SetBackgroundColor(Android.Graphics.Color.Green); 


       if ((marker != null)) 
       { 
        marker.ShowInfoWindow(); 
       } 
       endPressStatus = true; 
       return true; 
      } 
      else 
      { 
       endPressStatus = false; 
       return false; 
      } 

     } 

     //private Runnable confirmClickRunnable = new RunnableAnonymousInnerClassHelper(this); 
     private Runnable ConfirmClickRunnable = new Java.Lang.Runnable(() => 
     { 
      if (endPressStatus) 
      { 

       //onClickConfirmed(view, marker); 
      } 
     }); 




     /*private class RunnableAnonymousInnerClassHelper : Java.Lang.Object, Java.Lang.IRunnable 
     { 
      private readonly Context outerInstance;  

      public RunnableAnonymousInnerClassHelper(Context outerInstance) 
      { 
       this.outerInstance = outerInstance;   
      } 

      public void Run() 
      { 
       if (endPressStatus) 
       { 
        onClickConfirmed(); 
       } 
      } 
     }*/ 


     //public abstract void onClickConfirmed(View v, Marker marker); 
     public abstract void onClickConfirmed(); 

    } 
} 

OnTouchPhoneListener:

using Android.Widget; 
using System; 

namespace SalesApp.Droid.Listeners 
{ 
    public class OnTouchPhoneListener : OnInfoWindowElemTouchListener 
    //public class OnTouchPhoneListener 
    { 
     Button button; 
     public OnTouchPhoneListener(Button button) 
     { 

     } 

     public OnTouchPhoneListener() 
     { 

     } 
     public override void onClickConfirmed() { 
      Console.WriteLine("call Button Clicked"); 
     } 
    } 
} 
+0

代わりに[mcve]を作成した場合は、この問題を再現できます。 –

+0

ありがとう@ポール、私は自分のために1つを作成し、同じ問題があります。ボタンリスナーはトリガーされません。 –

答えて

0

カスタムレンダラに情報ウィンドウが実装されているのはなぜですか?これにより、クラスCustomMapRendererは(少なくとも)2つのことを行い、SRPに違反し、コードを理解しにくくします。

代わりに、マップのカスタムレンダラーに行ってみましょう。次に、Xamarin.FormsでオーバーレイをXamarin.Forms手段で実装することができます(たとえば、絶対または相対レイアウトのマップビュー、同じレイアウトのオーバーレイが縮小されたサイズ)。今度は - - すべてのバインド次にあなたがMapView.SelectedPinInfoによって露出され、MapOverlay.BindingContext

<local:MapOverlay AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds=".5, .5, .5, .5" BindingContext="{Binding Source={x:Reference MapView}, Path=SelectedPinInfo}" /> 

MapOverlayとして設定することができるのviewmodel PinInfoViewModelを導入することができ、次の擬似 -XAML

<ContentPage [...]> 
    <AbsoluteLayout> 
    <local:MapView x:Name="MapView" AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds="0,0,1,1" /> 
    <local:MapOverlay AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds=".5, .5, .5, .5" /> 
    </AbsoluteLayout> 
</ContentPage> 

を参照してください。 PinInfoViewModelの特性。最後に、ピンが選択されていない場合はオーバーレイを非表示にする必要があります。私たちはあなたの問題を解決するために何もしていないこの時点まで、あなたが今、オーバーレイを実装することができますが、この目的のために我々はMapView.IsPinSelectedを公開し、それ

<local:MapOverlay AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds=".5, .5, .5, .5" BindingContext="{Binding Source={x:Reference MapView}, Path=SelectedPinInfo}" IsVisible="{Binding Source=MapView, Path=IsPinSelected}" /> 

MapOverlay.IsVisibleをバインドする方法シンプルな、例えばStackLayoutである。そして、あなたがしたいことを何でもするためにButtonのコマンドを縛ることができます。

+0

はあなたのソリューションを本当に感謝しています。私はカスタムレンダラで一度やってみてください。 –

関連する問題