请在下面找到适用于Android的自定义渲染器以进行分段控制的代码。我从堆栈溢出中的一个帖子中复制了这个。它适用于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);
}
}
它发生在这条线上。
var v = (SegmentedControlButton)layoutInflater.Inflate(Resource.Layout.SegmentedControl, null);
v.Text = o.Text;
错误
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]]
答案 0 :(得分:0)
尝试关注SegmentControlRenderer
。我也添加了所需的文件。
在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>
确保将所有这7个文件放在正确的目录中。如果出现任何问题,请告诉我
SegmentedControlRenderer.cs (放置在Droid模块中)
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);
}
}
}
}
}
CustomSegmentedControl.cs (置于共享应用模块中)
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()
{
}
}
}
CustomSegmentedView.cs (放入共享应用模块)
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);
}
}
SegmentedControl.axml (放置在Droid / Resources / layout中)
<?xml version="1.0" encoding="utf-8"?>
<App.Droid.CustomSegmentedControlButton
style="@style/SegmentedControlOption" />
attrs.xml (放置在Droid / Resources / values中)
<?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>
segment_control_option_bg.xml (放置在Droid / Resources / layout中)
<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>
segment_control_selected_option_bg.xml (放置在Droid / Resources / layout中)
<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>
答案 1 :(得分:-1)
问题在于segmented control.axml我提供了错误的命名空间。
<?xml version="1.0" encoding="utf-8"?>
<*MyFirstApp*.Droid.SegmentedControlButton
style="@style/SegmentedControlOption" />
它解决了一切。 #Needle in the haystack#
@ user12345我已经在帖子中提供了正确的代码。谢谢你的巧妙解释。