Xamarin.forms ic类LCPickerRenderer:PickerRenderer,IPickerRenderer//ViewRenderer,IPickerRenderer { AlertDialog\u对话框; 号码选择器; 公共LCPickerRenderer(上

Xamarin.forms ic类LCPickerRenderer:PickerRenderer,IPickerRenderer//ViewRenderer,IPickerRenderer { AlertDialog\u对话框; 号码选择器; 公共LCPickerRenderer(上,xamarin.forms,themes,Xamarin.forms,Themes,ic类LCPickerRenderer:PickerRenderer,IPickerRenderer//ViewRenderer,IPickerRenderer { AlertDialog\u对话框; 号码选择器; 公共LCPickerRenderer(上下文):基(上下文) { //自动包装=错误; } [过时(“此构造函数从2.5版起已过时。请改用PickerRenderer(上下文)。] [EditorBrowsable(EditorBrowsableState.Never)] 公共图书馆

ic类LCPickerRenderer:PickerRenderer,IPickerRenderer//ViewRenderer,IPickerRenderer { AlertDialog\u对话框; 号码选择器; 公共LCPickerRenderer(上下文):基(上下文) { //自动包装=错误; } [过时(“此构造函数从2.5版起已过时。请改用PickerRenderer(上下文)。] [EditorBrowsable(EditorBrowsableState.Never)] 公共图书馆 { //自动包装=错误; } IElementController元素控制器=>元素作为IElementController; 受保护的覆盖无效OnElementChanged(ElementChangedEventArgs e) { if(e.OldElement!=null){ //((INotifyCollectionChanged)e.OldElement.Items)。CollectionChanged-=RowsCollectionChanged; } 基础。一个要素发生变化(e); if(例如NewElement!=null){ //---海关工作--- if(控件!=null){ SetTextColor(); SetBackgroundColor(); } } } 受保护的覆盖无效OnElementPropertyChanged(对象发送方,PropertyChangedEventArgs e) { base.OnElementPropertyChanged(发送方,e); if(e.PropertyName==Picker.BackgroundColorProperty.PropertyName){ SetBackgroundColor(); }else if(e.PropertyName==Picker.TextColorProperty.PropertyName){ SetTextColor(); } //如果(e.PropertyName==Picker.TitleProperty.PropertyName | | e.PropertyName==Picker.TitleColorProperty.PropertyName) //更新Epicker(); //else if(e.PropertyName==Picker.SelectedIndexProperty.PropertyName) //更新Epicker(); //else if(e.PropertyName==Picker.CharacterSpacingProperty.PropertyName) //UpdateCharacterSpacing(); //else if(e.PropertyName==Picker.TextColorProperty.PropertyName) //UpdateTextColor(); //如果(e.PropertyName==Picker.FontAttributesProperty.PropertyName | | | e.PropertyName==Picker.FontFamilyProperty.PropertyName | | e.PropertyName==Picker.FontSizeProperty.PropertyName) //UpdateFont(); } void ipickerender.OnClick() { 选择器模型=元件; 如果(_dialog!=null) 返回; var xfTextColor=Element.TextColor; _picker=新的NumberPicker(上下文); if(model.Items!=null&&model.Items.Any()){ _picker.MaxValue=model.Items.Count-1; _picker.MinValue=0; _picker.SetDisplayedValues(model.Items.ToArray()); _picker.WrapSelectorWheel=假; _picker.genderantfocusability=genderantfocusability.blocksubstands; _picker.Value=model.SelectedIndex; } 变量布局=新线性布局(上下文){Orientation=Orientation.Vertical}; 布局。添加视图(_选择器); ElementController.SetValueFromRenderer(VisualElement.IsFocusedPropertyKey,true); var builder=新建AlertDialog.builder(上下文); builder.SetView(布局); if(!Element.IsSet(Picker.TitleColorProperty)){ builder.SetTitle(model.Title??); }否则{ var title=新跨距平衡环(model.title???); title.SetSpan(新的ForegroundColorSpan(model.TitleColor.ToAndroid()),0,title.Length(),SpanTypes.ExclusiveExclusive); 建造商名称(名称); } //TODO:从XF元素获取文本(以及是否显示)。 builder.SetNegativeButton(全局::Android.Resource.String.Cancel,(s,a)=>{ ElementController.SetValueFromRenderer(VisualElement.IsFocusedPropertyKey,false); _dialog=null; }); builder.SetPositiveButton(全局::Android.Resource.String.Ok,(s,a)=>{ ElementController.SetValueFromRenderer(Picker.SelectedIndexProperty,_Picker.Value); //可以在SelectedIndexChanged上更改页面内容。 //在这种情况下,元素和控件将不再存在。 if(元素!=null){ 如果(model.Items.Count>0&&Element.SelectedIndex>=0) Control.Text=model.Items[Element.SelectedIndex]; ElementController.SetValueFromRenderer(VisualElement.IsFocusedPropertyKey,false); } _dialog=null; }); _dialog=builder.Create(); _dialog.DismissEvent+=(发送方,参数)=>{ ElementController?.SetValueFromRenderer(VisualElement.IsFocusedPropertyKey,false); _对话框?.Dispose(); _dialog=null; }; _dialog.Show(); //TODO:通过自定义XF属性控制此操作。 var buttonColor=Color.Accent.ToAndroid(); //从https://stackoverflow.com/a/56555965/199364. var btnCancel=_dialog.GetButton((int)DialogInterface.ButtonNegative); //“?”以防未连接此类按钮。 btnCancel?.SetTextColor(按钮颜色); var btnOK=_dialog.GetButton((int)DialogInterface.ButtonPositive); btnOK?.SetTextColor(按钮颜色); SetTextColor(); SetBackgroundColor(); } 私有void SetTextColor() { 控件?.SetTextColor(Element.TextColor.ToAndroid()); if(_picker!=null) SetTextColor(_选择器,Element.TextColor.ToAndroid()); } 私有void SetBackgroundColor() { 控件?.SetBackgroundColor(Element.BackgroundColor.ToAndroid()); _皮克?塞巴
using Android.App;
using Android.Util;
using Android.Views;
using Android.Widget;
using System;
using System.ComponentModel;
using System.Linq;
using Orientation = Android.Widget.Orientation;
using Android.Content;
using Android.Text;
using Android.Text.Style;
using Java.Lang;

// PickerEditText
using Xamarin.Forms.Platform.Android;

using AColor = Android.Graphics.Color;
using Picker = Xamarin.Forms.Picker;

[assembly: Xamarin.Forms.ExportRenderer(typeof(Picker), typeof(LCPickerRenderer))]
namespace Xamarin.Forms.Platform.Android
{
    // Based on Xamarin.Forms source code, modified.
    public class LCPickerRenderer : PickerRenderer, IPickerRenderer   //ViewRenderer<Picker, EditText>, IPickerRenderer
    {
        AlertDialog _dialog;
        NumberPicker _picker;

        public LCPickerRenderer(Context context) : base(context)
        {
            //AutoPackage = false;
        }

        [Obsolete("This constructor is obsolete as of version 2.5. Please use PickerRenderer(Context) instead.")]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public LCPickerRenderer()
        {
            //AutoPackage = false;
        }

        IElementController ElementController => Element as IElementController;

        protected override void OnElementChanged(ElementChangedEventArgs<Picker> e)
        {
            if (e.OldElement != null) {
                //((INotifyCollectionChanged)e.OldElement.Items).CollectionChanged -= RowsCollectionChanged;
            }

            base.OnElementChanged(e);

            if (e.NewElement != null) {
                // --- custom work ---
                if (Control != null) {
                    SetTextColor();
                    SetBackgroundColor();
                }
            }
        }

        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);

            if (e.PropertyName == Picker.BackgroundColorProperty.PropertyName) {
                SetBackgroundColor();
            } else if (e.PropertyName == Picker.TextColorProperty.PropertyName) {
                SetTextColor();
            }

            //if (e.PropertyName == Picker.TitleProperty.PropertyName || e.PropertyName == Picker.TitleColorProperty.PropertyName)
            //    UpdatePicker();
            //else if (e.PropertyName == Picker.SelectedIndexProperty.PropertyName)
            //    UpdatePicker();
            //else if (e.PropertyName == Picker.CharacterSpacingProperty.PropertyName)
            //    UpdateCharacterSpacing();
            //else if (e.PropertyName == Picker.TextColorProperty.PropertyName)
            //    UpdateTextColor();
            //else if (e.PropertyName == Picker.FontAttributesProperty.PropertyName || e.PropertyName == Picker.FontFamilyProperty.PropertyName || e.PropertyName == Picker.FontSizeProperty.PropertyName)
            //    UpdateFont();
        }


        void IPickerRenderer.OnClick()
        {
            Picker model = Element;

            if (_dialog != null)
                return;

            var xfTextColor = Element.TextColor;
            _picker = new NumberPicker(Context);
            if (model.Items != null && model.Items.Any()) {
                _picker.MaxValue = model.Items.Count - 1;
                _picker.MinValue = 0;
                _picker.SetDisplayedValues(model.Items.ToArray());
                _picker.WrapSelectorWheel = false;
                _picker.DescendantFocusability = DescendantFocusability.BlockDescendants;
                _picker.Value = model.SelectedIndex;
            }

            var layout = new LinearLayout(Context) { Orientation = Orientation.Vertical };
            layout.AddView(_picker);

            ElementController.SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, true);

            var builder = new AlertDialog.Builder(Context);
            builder.SetView(layout);

            if (!Element.IsSet(Picker.TitleColorProperty)) {
                builder.SetTitle(model.Title ?? "");
            } else {
                var title = new SpannableString(model.Title ?? "");
                title.SetSpan(new ForegroundColorSpan(model.TitleColor.ToAndroid()), 0, title.Length(), SpanTypes.ExclusiveExclusive);

                builder.SetTitle(title);
            }

            // TODO: get texts (and whether to show) from XF Element.
            builder.SetNegativeButton(global::Android.Resource.String.Cancel, (s, a) => {
                ElementController.SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, false);
                _dialog = null;
            });
            builder.SetPositiveButton(global::Android.Resource.String.Ok, (s, a) => {
                ElementController.SetValueFromRenderer(Picker.SelectedIndexProperty, _picker.Value);
                // It is possible for the Content of the Page to be changed on SelectedIndexChanged. 
                // In this case, the Element & Control will no longer exist.
                if (Element != null) {
                    if (model.Items.Count > 0 && Element.SelectedIndex >= 0)
                        Control.Text = model.Items[Element.SelectedIndex];
                    ElementController.SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, false);
                }
                _dialog = null;
            });

            _dialog = builder.Create();
            _dialog.DismissEvent += (sender, args) => {
                ElementController?.SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, false);
                _dialog?.Dispose();
                _dialog = null;
            };
            _dialog.Show();

            // TODO: Control this via a custom XF property.
            var buttonColor = Color.Accent.ToAndroid();
            // From https://stackoverflow.com/a/56555965/199364.
            var btnCancel = _dialog.GetButton((int)DialogInterface.ButtonNegative);
            // "?" in case no such button was attached.
            btnCancel?.SetTextColor(buttonColor);
            var btnOK = _dialog.GetButton((int)DialogInterface.ButtonPositive);
            btnOK?.SetTextColor(buttonColor);

            SetTextColor();
            SetBackgroundColor();
        }

        private void SetTextColor()
        {
            Control?.SetTextColor(Element.TextColor.ToAndroid());
            if (_picker != null)
                SetTextColor(_picker, Element.TextColor.ToAndroid());
        }

        private void SetBackgroundColor()
        {
            Control?.SetBackgroundColor(Element.BackgroundColor.ToAndroid());
            _picker?.SetBackgroundColor(Element.BackgroundColor.ToAndroid());
            _dialog?.Window.SetBackgroundDrawable(new global::Android.Graphics.Drawables.ColorDrawable(Element.BackgroundColor.ToAndroid()));
        }

        // From https://stackoverflow.com/a/26657169/199364
        // TODO: When support API 29, this needs to be modified re https://stackoverflow.com/a/56883356/199364 ?
        public static bool SetTextColor(NumberPicker numberPicker, AColor color)
        {
            var sdkInt = global::Android.OS.Build.VERSION.SdkInt;
            //var limitSdk = global::Android.OS.Build.VERSION_CODES.Q;

            int count = numberPicker.ChildCount;
            for (int i = 0; i < count; i++) {
                var child = numberPicker.GetChildAt(i);
                if (child.GetType() == typeof(EditText)) {
                    try {
                        var selectorWheelPaintField = numberPicker.Class
                                                                    .GetDeclaredField("mSelectorWheelPaint");
                        selectorWheelPaintField.Accessible = true;

                        EditText editText = (EditText)child;
                        editText.SetTextColor(color);

                        var paint = (global::Android.Graphics.Paint)selectorWheelPaintField.Get(numberPicker);
                        paint.Color = color;

                        numberPicker.Invalidate();
                        return true;
                    }
                    catch (NoSuchFieldException e) {
                        Log.Warn("setNumberPickerTextColor", e);
                    }
                    catch (IllegalAccessException e) {
                        Log.Warn("setNumberPickerTextColor", e);
                    }
                    catch (IllegalArgumentException e) {
                        Log.Warn("setNumberPickerTextColor", e);
                    }
                }
            }
            return false;
        }
    }
}
// Extracted from a larger class. Some of these not used in the code here.
using System;
using System.Collections.Generic;
using System.IO;

using Android.Content;
using Android.Content.PM;
using Android.Graphics;
using Android.Provider;
using Android.Views;
using Android.Widget;

using Android.Support.V4.Content;
using Android.Support.V4.App;
using Android.Support.V7.App;

// For Extension: color.ToAndroid.
using Xamarin.Forms.Platform.Android;

public static partial class UI
{

    // If cancelHandler is null, no Cancel button will be added.
    // If noHandler is not null, then "OK" is renamed "Yes".
    public static void ShowAlertDialog(string title, string message,
                                        EventHandler okHandler, EventHandler cancelHandler,
                                        EventHandler noHandler = null, bool textIsYes = false)
    {
        bool hasCancel = (cancelHandler != null);
        bool hasNo = (noHandler != null);
        string okOrYes = PS.LocalizedString((textIsYes || hasNo ? "Yes" : "OK"));
        // When both cancel and no, is "Cancel".
        // When neither cancel or no, defaults to "Cancel", which does nothing.
        // The only time this is "No", is if there is a No button, but no Cancel button.
        string cancelOrNo = PS.LocalizedString((hasNo && !hasCancel ? "No" : "Cancel"));
        EventHandler cancelOrNoHandler = (hasCancel ? cancelHandler : noHandler);

        AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.it);

        var titleOb = new Android.Text.SpannableString(title);
        // TODO: Add custom XF property to set this.
        var titleColor = (Xamarin.Forms.Color)Xamarin.Forms.Application.Current.Resources["MaxForegroundColor"];
        titleOb.SetSpan(new Android.Text.Style.ForegroundColorSpan(titleColor.ToAndroid()), 0, title.Length, Android.Text.SpanTypes.ExclusiveExclusive);
        builder.SetTitle(titleOb);

        builder.SetMessage(message);

        if (hasCancel || hasNo) {
            builder.SetNegativeButton(cancelOrNo,
                                 (s, e) => {
                                     cancelOrNoHandler?.Invoke(null, EventArgs.Empty);
                                 });
        }

        // Only used when BOTH Cancel and No buttons.
        if (hasNo && hasCancel)
            builder.SetNeutralButton(PS.LocalizedString("No"),
                                (s, e) => { noHandler.Invoke(null, EventArgs.Empty); });

        builder.SetPositiveButton(okOrYes, (s, e) => {
            if (okHandler != null)
                okHandler.Invoke(null, EventArgs.Empty);
        });

        AlertDialog dialog = builder.Show();
        SetAlertStyle(dialog);
    }

    /// <summary>
    /// This doesn't set Title Color. Set that earlier, while building the dialog.
    /// </summary>
    /// <param name="dialog"></param>
    private static void SetAlertStyle(AlertDialog dialog)
    {
        // Use these if succeed in changing both title and background colors.
        var foreColor = (Xamarin.Forms.Color)Xamarin.Forms.Application.Current.Resources["ForegroundColor"];
        var accentAgainstBack = (Xamarin.Forms.Color)Xamarin.Forms.Application.Current.Resources["AccentSaturated25Fore33"];

        var backColor = (Xamarin.Forms.Color)Xamarin.Forms.Application.Current.Resources["BackgroundColor"];
        SetBackgroundColor(dialog, backColor);

        //// DIDN'T WORK: No effect on title color. Set earlier, while building the dialog.
        //int alertViewId = Android.App.Application.Context.Resources.GetIdentifier("alertTitle", "id", "android");
        //SetItemTextColor(dialog, "alertTitle", accentAgainstBack);

        SetItemTextColor(dialog, "message", foreColor);

        SetItemTextColor(dialog, "button1", (Xamarin.Forms.Color)Xamarin.Forms.Application.Current.Resources["AccentSaturated25Fore33"]);
        SetItemTextColor(dialog, "button2", (Xamarin.Forms.Color)Xamarin.Forms.Application.Current.Resources["ForegroundColor"]);
    }

    private static void SetItemTextColor(AlertDialog dialog, string itemResourceName, Xamarin.Forms.Color color)
    {
        int textId = Android.App.Application.Context.Resources.GetIdentifier(itemResourceName, "id", "android");
        TextView text = dialog.FindViewById<TextView>(textId);
        text?.SetTextColor(color.ToAndroid());
    }

    private static void SetBackgroundColor(AlertDialog dialog, Xamarin.Forms.Color xfColor)
    {
        dialog?.Window.SetBackgroundDrawable(new global::Android.Graphics.Drawables.ColorDrawable(xfColor.ToAndroid()));
    }

}