xamarin forms pcl android的段控件自定义呈现程序不工作

xamarin forms pcl android的段控件自定义呈现程序不工作,xamarin,xamarin.android,xamarin.forms,Xamarin,Xamarin.android,Xamarin.forms,请在下面找到用于分段控制的Android自定义渲染器的代码。我从stack overflow中的一篇文章中复制了这篇文章。它在IOS上运行良好,但在android上运行失败。有人知道吗?我遗漏了什么吗 这就是事件 protected override void OnElementChanged(ElementChangedEventArgs<SegmentedControl> e) { base.OnElementChanged(e); var la

请在下面找到用于分段控制的Android自定义渲染器的代码。我从stack overflow中的一篇文章中复制了这篇文章。它在IOS上运行良好,但在android上运行失败。有人知道吗?我遗漏了什么吗

这就是事件

protected override void OnElementChanged(ElementChangedEventArgs<SegmentedControl> e)
{
        base.OnElementChanged(e);

        var layoutInflater = (LayoutInflater)Context.GetSystemService(Context.LayoutInflaterService);

        var g = new RadioGroup(Context);
        g.Orientation = Orientation.Horizontal;
        g.CheckedChange += (sender, eventArgs) =>
        {
            var rg = (RadioGroup)sender;
            if (rg.CheckedRadioButtonId != -1)
            {
                var id = rg.CheckedRadioButtonId;
                var radioButton = rg.FindViewById(id);
                var radioId = rg.IndexOfChild(radioButton);
                var btn = (RadioButton)rg.GetChildAt(radioId);
                var selection = (String)btn.Text;
                e.NewElement.SelectedValue = selection;
            }
        };

        for (var i = 0; i < e.NewElement.Children.Count; i++)
        {
            var o = e.NewElement.Children[i];
            var v = (SegmentedControlButton)layoutInflater.Inflate(Resource.Layout.SegmentedControl, null);
  //Error at this above line

            v.Text = o.Text;
            if (i == 0)
                v.SetBackgroundResource(Resource.Drawable.segmented_control_first_background);
            else if (i == e.NewElement.Children.Count - 1)
                v.SetBackgroundResource(Resource.Drawable.segmented_control_last_background);
            g.AddView(v);
        }

        SetNativeControl(g);
    }
}
错误

 Android.Views.InflateException: Binary XML file line #1: Binary XML file line #1: 
 Error inflating class SegmentedControl.Android.SegmentedControlButton ---> Android.Views.InflateException: 
 Binary XML file line #1: Error inflating class SegmentedControl.Android.SegmentedControlButton ---> Java.Lang.ClassNotFoundException: 
 Didn't find class "SegmentedControl.Android.SegmentedControlButton" on path: DexPathList[[zip file "/data/app/com.mytestapp.myfirstapp-1/base.apk"],
 nativeLibraryDirectories=[/data/app/com.mytestapp.myfirstapp-1/lib/x86, /data/app/com.mytestapp.myfirstapp-1/base.apk!/lib/x86, /vendor/lib, /system/lib]]

尝试以下
分段控制渲染器
。我还添加了所需的文件

在xaml文件中使用以下命令

<StackLayout BackgroundColor="#0A0E3F" Padding="10" Spacing="0" Grid.Row="0">
    <local:CustomSegmentedControl SelectedValue="Offices" x:Name="segmentControl" HorizontalOptions="FillAndExpand">
        <local:CustomSegmentedControl.Children>
            <local:CustomSegmentedControlOption Text="Control1" />
            <local:CustomSegmentedControlOption Text="Control2" />
            <local:CustomSegmentedControlOption Text="Control3" />
        </local:CustomSegmentedControl.Children>
    </local:CustomSegmentedControl>
</StackLayout>
分段控制.axml(放置在Droid/Resources/layout中)


attrs.xml(放在Droid/Resources/values中)


段控制选项\u bg.xml(放置在Droid/Resources/layout中)


段控制\u选择的\u选项\u bg.xml(放置在Droid/Resources/layout中)


问题出在分段控件中。我给了错误的名称空间

<?xml version="1.0" encoding="utf-8"?>
<*MyFirstApp*.Droid.SegmentedControlButton
style="@style/SegmentedControlOption" />

它解决了一切#大海捞针#


@user12345无论你提到什么,我在帖子中已经有了正确的代码。谢谢你简洁的解释。

我已经更新了答案。我忘了添加xaml代码(即如何使用它),我没有使用XLabs。我在代码中看到了名称空间,您在使用它吗?我不想为此添加任何nuget。
using System;
using Xamarin.Forms.Platform.Android;
using Android.Widget;
using Android.Content;
using Android.Util;
using Android.Graphics;
using Android.Views;
using System.Collections.Generic;

[assembly: Xamarin.Forms.ExportRenderer(typeof(App.CustomSegmentedControl), typeof(App.Droid.SegmentedControlRenderer))]
namespace App.Droid
{
    public class SegmentedControlRenderer : ViewRenderer<CustomSegmentedControl, RadioGroup>
    {
        RadioGroup g = null;
        List<CustomSegmentedControlButton> listSegmentControl = new List<CustomSegmentedControlButton>();

        public SegmentedControlRenderer()
        {

        }

        protected override void OnConfigurationChanged(Android.Content.Res.Configuration newConfig)
        {
            base.OnConfigurationChanged(newConfig);

            if (listSegmentControl == null)
                return;

            foreach (var control in listSegmentControl)
            {
                control.SetWidth(Resources.DisplayMetrics.WidthPixels / listSegmentControl.Count);
            }
        }

        protected override void OnElementChanged(ElementChangedEventArgs<TPSegmentedControl> e)
        {
            base.OnElementChanged(e);

            var layoutInflater = (LayoutInflater)Context.GetSystemService(Context.LayoutInflaterService);

            g = new RadioGroup(Context);
            g.Orientation = Orientation.Horizontal;

            g.CheckedChange += (sender, eventArgs) =>
            {
                var rg = (RadioGroup)sender;
                if (rg.CheckedRadioButtonId != -1)
                {
                    var id = rg.CheckedRadioButtonId;
                    var radioButton = rg.FindViewById(id);
                    var radioId = rg.IndexOfChild(radioButton);
                    var btn = (RadioButton)rg.GetChildAt(radioId);
                    for (int i = 0; i < g.ChildCount; i++)
                    {
                        g.GetChildAt(i).SetBackgroundResource(Resource.Drawable.segment_control_option_bg);
                    }
                    btn.SetBackgroundResource(btn.Checked ? Resource.Drawable.segment_control_selected_option_bg : Resource.Drawable.segment_control_option_bg);
                    var selection = (String)btn.Text;
                    e.NewElement.SelectedValue = selection;
                }
            };


            for (var i = 0; i < e.NewElement.Children.Count; i++)
            {
                var o = e.NewElement.Children[i];
                var v = (TPSegmentedControlButton)layoutInflater.Inflate(Resource.Layout.SegmentedControl, null);
                v.Text = o.Text;
                int minWidth = Resources.DisplayMetrics.WidthPixels / e.NewElement.Children.Count;
                v.SetWidth(minWidth);
                v.SetBackgroundResource(v.Checked ? Resource.Drawable.segment_control_selected_option_bg : Resource.Drawable.segment_control_option_bg);
                g.AddView(v);
                listSegmentControl.Add(v);
            }

            try
            {
                g.GetChildAt(0).PerformClick();
            }
            catch (Exception ex)
            {

            }
            SetNativeControl(g);

        }
    }

    public class CustomSegmentedControlButton : RadioButton
    {
        private int lineHeightSelected;
        private int lineHeightUnselected;

        private Paint linePaint;

        public CustomSegmentedControlButton(Context context) : this(context, null)
        {
        }

        public CustomSegmentedControlButton(Context context, IAttributeSet attributes) : this(context, attributes, Resource.Attribute.segmentedControlOptionStyle)
        {
        }

        public CustomSegmentedControlButton(Context context, IAttributeSet attributes, int defStyle) : base(context, attributes, defStyle)
        {
            Initialize(attributes, defStyle);
        }

        private void Initialize(IAttributeSet attributes, int defStyle)
        {
            var a = this.Context.ObtainStyledAttributes(attributes, Resource.Styleable.SegmentedControlOption, defStyle, Resource.Style.SegmentedControlOption);

            var lineColor = Color.ParseColor("#4aa3f4");
            linePaint = new Paint();
            linePaint.Color = lineColor;

            lineHeightUnselected = a.GetDimensionPixelSize(Resource.Styleable.SegmentedControlOption_lineHeightUnselected, 0);
            lineHeightSelected = a.GetDimensionPixelSize(Resource.Styleable.SegmentedControlOption_lineHeightSelected, 0);

            a.Recycle();
        }

        protected override void OnDraw(Canvas canvas)
        {
            base.OnDraw(canvas);

            if (linePaint.Color != 0 && (lineHeightSelected > 0 || lineHeightUnselected > 0))
            {
                var lineHeight = Checked ? lineHeightSelected : lineHeightUnselected;

                if (lineHeight > 0)
                {
                    var rect = new Rect(0, Height - lineHeight, Width, Height);
                    canvas.DrawRect(rect, linePaint);
                }
            }
        }
    }
}
using System;
using Xamarin.Forms;
using System.Collections.Generic;

namespace App
{
    public class CustomSegmentedControl : View, IViewContainer<CustomSegmentedControlOption>
    {
        public IList<CustomSegmentedControlOption> Children { get; set; }

        public TPSegmentedControl()
        {
            Children = new List<CustomSegmentedControlOption>();
        }

        public event ValueChangedEventHandler ValueChanged;

        public delegate void ValueChangedEventHandler(object sender, EventArgs e);

        private string selectedValue;

        public string SelectedValue
        {
            get { return selectedValue; }
            set
            {
                selectedValue = value;
                if (ValueChanged != null)
                    ValueChanged(this, EventArgs.Empty);
            }
        }
    }

    public class CustomSegmentedControlOption : View
    {
        public static readonly BindableProperty TextProperty = BindableProperty.Create<CustomSegmentedControlOption, string>(p => p.Text, "");

        public string Text
        {
            get { return (string)GetValue(TextProperty); }
            set { SetValue(TextProperty, value); }
        }

        public TPSegmentedControlOption()
        {
        }
    }
}
using System;
using XLabs.Forms.Controls;
namespace App
{
    public class CustomSegmentedView : SegmentedControlView
    {
        public ISegmentedControlView Listener { get; set;}
        public CustomSegmentedView()
        {

        }

        protected override void OnPropertyChanged(string propertyName = null)
        {
            base.OnPropertyChanged(propertyName);
            if (propertyName == "SelectedItem") {
                if (Listener == null)
                    return;

                Listener.SegmentedControlOnValueChanged(SelectedItem);
            }
        }
    }

    public interface ISegmentedControlView {
        void SegmentedControlOnValueChanged(int selectedIndex);
    }
}
<?xml version="1.0" encoding="utf-8"?>
<App.Droid.CustomSegmentedControlButton
    style="@style/SegmentedControlOption" />
<?xml version="1.0" encoding="utf-8"?>
<resources>

  <declare-styleable name="SegmentedControlOption">
    <attr name="segmentedControlOptionStyle" format="string" />

    <attr name="lineColor" format="color" />
    <attr name="lineHeightUnselected" format="dimension" />
    <attr name="lineHeightSelected" format="dimension" />
  </declare-styleable>

  <declare-styleable name="ScaleImageView">

  </declare-styleable>

</resources>
<shape xmlns:android="http://schemas.android.com/apk/res/android">

  <solid android:color="#4aa3f4" />

  <stroke
        android:width="0.5dp"
        android:color="#0a0e3f" />

  <corners
      android:bottomLeftRadius="0dp"
      android:bottomRightRadius="0dp"
      android:topLeftRadius="0dp"
      android:topRightRadius="0dp" />

</shape>
<shape xmlns:android="http://schemas.android.com/apk/res/android">

  <solid android:color="#0271d5" />

  <stroke
        android:width="0.5dp"
        android:color="#0a0e3f" />

  <corners
      android:bottomLeftRadius="0dp"
      android:bottomRightRadius="0dp"
      android:topLeftRadius="0dp"
      android:topRightRadius="0dp" />

</shape>
<?xml version="1.0" encoding="utf-8"?>
<*MyFirstApp*.Droid.SegmentedControlButton
style="@style/SegmentedControlOption" />