2

I am trying to get some style consistency in my xamarin forms app (for android alone for now). I'm trying to give all buttons the same look. In general, this is easily done by adding a Style in the App.xaml file with TargetType set to Button. The problem is that I'm using a Picker (also a TimePicker which has similar issues). When clicking this picker a pop up is shown with a cancel button. This cancel button I can not change the style for (changing background and border for example). This screen shot of a dummy project explains the issue a bit more: enter image description here

Apart from trying the App.xaml solution, I also tried to set the style in the android project by adjusting styles.xml. This did also have an influence on all the buttons except for the one in the Picker dialog.

Anyone any idea's on how to fix it?

Gert Hermans
  • 769
  • 1
  • 9
  • 30
  • 1
    Maybe like this , have not tryed if it works. https://stackoverflow.com/questions/56391601/how-to-change-the-change-cancel-and-ok-buttons-color-in-the-picker – Bas H Dec 15 '21 at 13:54
  • Thanks Bas, I had l0oked at this one, but the solution is basically rewriting the Picker, might as well write my own version (which will make styling easier) – Gert Hermans Dec 15 '21 at 14:05
  • And even when I try this, I still can not change the style of the cancel button – Gert Hermans Dec 15 '21 at 14:53
  • Don't know if you can change the style but i can change the color of the OK and Cancel button . – Bas H Dec 15 '21 at 15:52

2 Answers2

3

Gert , Found something for the style for a Picker . This is for Android .

Change color of cancel or change the text of it ,did not try the Fonts or other things to adjust

[assembly: ExportRenderer(typeof(Picker), typeof(MyPickerRenderer))]
namespace Pickerstyle.Droid
{
   
    public class MyPickerRenderer : Xamarin.Forms.Platform.Android.PickerRenderer
    {
        Typeface fontFace = null;
        private IElementController ElementController => Element as IElementController;
        private AlertDialog _dialog;
        public MyPickerRenderer(Context context) : base(context)
        {
            AutoPackage = false;
        }
        [Obsolete("This constructor is obsolete as of version 2.5. Please use PickerRenderer(Context) instead.")]
        public MyPickerRenderer()
        {
            AutoPackage = false;
        }
        protected override void OnElementChanged(ElementChangedEventArgs<Picker> e)
        {
            base.OnElementChanged(e);

            if (e.NewElement == null || e.OldElement != null || Control == null)
                return;

          //  fontFace = Typeface.CreateFromAsset(this.Context.Assets, "somefont.ttf");

            GradientDrawable gd = new GradientDrawable();
            gd.SetStroke(0, Android.Graphics.Color.Transparent);
            Control.SetBackground(gd);

            Control.TextSize = 18f;
            Control.SetTypeface(fontFace, TypefaceStyle.Normal);

            Control.Click += Control_Click;
        }
        protected override void Dispose(bool disposing)
        {
            Control.Click -= Control_Click;
            base.Dispose(disposing);
        }

        private void Control_Click(object sender, EventArgs e)
        {
            Picker model = Element;
            NumberPicker picker = new NumberPicker(Context);

            int count = picker.ChildCount;
            for (int i = 0; i < count; i++)
            {
                Android.Views.View v = picker.GetChildAt(i);
                if (v.GetType() == typeof(EditText))
                {
                    Java.Lang.Reflect.Field field = picker.Class.GetDeclaredField("mSelectorWheelPaint");
                    field.Accessible = true;
                    ((Paint)field.Get(picker)).SetTypeface(fontFace);
                    ((EditText)v).SetTypeface(fontFace, TypefaceStyle.Normal);
                    picker.Invalidate();
                }
            }

            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;
                picker.Visibility = ViewStates.Visible;

            }


            var layout = new LinearLayout(Context) { Orientation = Orientation.Vertical };
            layout.Visibility = ViewStates.Visible;
            layout.AddView(picker);


            ElementController.SetValueFromRenderer(VisualElement.IsFocusedProperty, true);

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

            builder.SetTitle(model.Title ?? "");

            builder.SetNegativeButton("Cancel", (s, a) =>
            {
                ElementController.SetValueFromRenderer(VisualElement.IsFocusedProperty, false);
                Control?.ClearFocus();
                _dialog = null;
            });

            builder.SetPositiveButton("Or this", (s, a) =>
            {
                ElementController.SetValueFromRenderer(Picker.SelectedIndexProperty, picker.Value);
                if (Element != null)
                {
                    if (model.Items.Count > 0 && Element.SelectedIndex >= 0)
                        Control.Text = model.Items[Element.SelectedIndex];
                    ElementController.SetValueFromRenderer(VisualElement.IsFocusedProperty, false);
                    Control?.ClearFocus();
                }
                _dialog = null;
            });

            _dialog = builder.Create();

            _dialog.DismissEvent += (ssender, args) =>
            {
                ElementController?.SetValueFromRenderer(VisualElement.IsFocusedProperty, false);
            };
            _dialog.Show();


            Android.Widget.Button nbutton = _dialog.GetButton((int)Android.Content.DialogButtonType.Positive);
            nbutton.SetTypeface(fontFace, TypefaceStyle.Normal);
            nbutton.SetTextColor(Android.Graphics.Color.ParseColor("#ff9500"));
            nbutton.TextSize = 16f;
            LinearLayout layOut = (LinearLayout)nbutton.Parent;
            layOut.SetGravity(GravityFlags.CenterHorizontal);
            Android.Views.View v1 = layOut.GetChildAt(1);
            v1.Visibility = ViewStates.Gone;


            int res = Resources.GetIdentifier("alertTitle", "id", "android");
            TextView textView = (TextView)_dialog.FindViewById(res);
            textView.SetTextColor(Android.Graphics.Color.Green);
            textView.SetTypeface(fontFace, TypefaceStyle.Normal);
            textView.Gravity = GravityFlags.Center;

        }
    }
}

enter image description here

enter image description here

Bas H
  • 2,114
  • 10
  • 14
  • 23
1

Found a rather easy way to adjust the buttons style on the picker popup by only adjusting styles.xml. This solution is for android only. found the solution here: How can I change default dialog button text color in android 5

styles.xml will look something like this:

<style name="MainTheme" >
    <item name="buttonBarNegativeButtonStyle">@style/ButtonStyle</item>
    <item name="buttonBarPositiveButtonStyle">@style/ButtonStyle</item>
    <item name="android:buttonStyle">@style/ButtonStyle</item>
</style>

<style name="ButtonStyle" >
    <item name="android:textColor">#000000</item>
    <item name="android:background">#FF0000</item>
</style>

The buttonBarNegativeButtonStyle, changes the cancel buttons style. This solution will also adjust the buttons in for example a TimePicker. (This also has buttonBarPositiveButtonStyle)

If you want control over the whole picker popup, then the solution of Bas H will be more appropriate

Zoe
  • 27,060
  • 21
  • 118
  • 148
Gert Hermans
  • 769
  • 1
  • 9
  • 30
  • Please note that newbedev is a Stack Overflow scraper; don't link to it. Instead, google the text or title (optionally with `site:stackoverflow.com`) and find the correct on-site link, instead of giving scrapers more traffic that they don't deserve. However, in this particular case, this also means your question is a duplicate, so I've gone ahead and closed it. – Zoe Dec 26 '21 at 16:02