728x90
728x170

Android 에서 ComboBox 를 선택한 경우 아래 처럼 기본적으로 아래에 취소 버튼이 나타납니다.
하지만 이부분을 없애고 글자 크기등을 변경하고 싶을때 팝업을 Custom 하게 정의하여 나타낼 수 있습니다.

예전 포스팅에 CustomPicker 처리하는 방법을 우선 참고해야합니다.

2019.02.05 - [C#/Xamarin Maui] - (Xamarin.Forms) Picker 에 화살표 표시하기

공용프로젝트에 CustomPicker.cs 추가
CustomPicker.cs

using Xamarin.Forms;

namespace App10
{
    public class CustomPicker : Picker
    {
        public static readonly BindableProperty ImageProperty = BindableProperty.Create(nameof(Image), typeof(string), typeof(CustomPicker), string.Empty);

        public string Image
        {
            get { return (string)GetValue(ImageProperty); }
            set { SetValue(ImageProperty, value); }
        }

        public CustomPicker() : base()
        {
            Margin = 3;
        }
    }
}

Android 프로젝트에 팝업디자인을 정의합니다.
먼저 박스 모양을 정의합니다.
Resources > layout 폴더에 Dialog.xml 을 추가합니다. (layout 폴더없으면 추가)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="200dp"
    android:layout_height="match_parent">
    
 <TextView 
  android:id="@+id/pickerTitle"
  android:text=""
  android:layout_width="match_parent"
  android:layout_height="wrap_content" 
  android:textAlignment="center"
  android:gravity="center_horizontal"
  android:padding ="20dp"
  android:textSize="25dp"
  android:textStyle="bold"/>
 <ListView
  android:id="@+id/pickerListView"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:layout_weight="1" />
  
</LinearLayout>

위 내용에서 pickerTitle 의 textSize 등을 조절하여 Title 의 폰트 사이즈 등을 변경할 수 있습니다.

ListView 에 나타날 항목의 모양을 정의합니다.
Resources > layout 폴더에 CustomListItem.xml 을 추가합니다

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@android:id/text1"
  android:textSize="20dp"
  android:paddingTop="10dp"
  android:paddingBottom="10dp"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  android:textColor="#ff000000"
  android:gravity="center"/>

위 내용에서 ListView 에 뿌려질 아이템인 text1 의 textSize, textColor 등을 변경하여 크기 및 색상등을 변경할 수 있습니다.

위 정의한 내용을 이제 Renderer 에서 사용하면됩니다.
CustomPickerRenderer.cs

using System;

using Android.App;
using Android.Content;
using Android.Content.Res;
using Android.Graphics;
using Android.Graphics.Drawables;
using Android.Views;
using Android.Widget;

using AndroidX.Core.Content;

using App10;
using App10.Droid;

using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;

[assembly: ExportRenderer(typeof(CustomPicker), typeof(CustomPickerRenderer))]
namespace App10.Droid
{
    public class CustomPickerRenderer : PickerRenderer
    {
        CustomPicker element;
        private Xamarin.Forms.Picker picker;
        private Dialog dialog;

        public CustomPickerRenderer(Context context) : base(context)
        {
        }

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

            element = (CustomPicker)this.Element;

            if (Control != null && this.Element != null && !string.IsNullOrEmpty(element.Image))
            {
                Control.Background = AddPickerStyles(element.Image);
            }

            if (Control != null)
            {
                picker = e.NewElement as Xamarin.Forms.Picker;

                Control.SetPadding(0, 0, 0, 0);
                Control.Gravity = GravityFlags.Center;

                Control.Click += Control_Click;
            }
        }

        public LayerDrawable AddPickerStyles(string imagePath)
        {
            ShapeDrawable border = new ShapeDrawable();
            border.Paint.Color = Android.Graphics.Color.Gray;
            border.SetPadding(10, 10, 10, 10);
            border.Paint.SetStyle(Paint.Style.Stroke);

            Drawable[] layers = { border, GetDrawable(imagePath) };
            LayerDrawable layerDrawable = new LayerDrawable(layers);
            layerDrawable.SetLayerInset(0, 0, 0, 0, 0);

            return layerDrawable;
        }

        private BitmapDrawable GetDrawable(string imagePath)
        {
            int resID = Resources.GetIdentifier(imagePath, "drawable", this.Context.PackageName);
            var drawable = ContextCompat.GetDrawable(this.Context, resID);
            var bitmap = ((BitmapDrawable)drawable).Bitmap;

            var result = new BitmapDrawable(Resources, Bitmap.CreateScaledBitmap(bitmap, 30, 30, true));
            result.Gravity = Android.Views.GravityFlags.Right;

            return result;
        }


        private void Control_Click(object sender, EventArgs e)
        {
            dialog = new Dialog(Context);

            dialog.SetContentView(Resource.Layout.Dialog);

            Android.Widget.TextView title = (Android.Widget.TextView)dialog.FindViewById(Resource.Id.pickerTitle);

            title.Text = picker.Title;

            Android.Widget.ListView listView = (Android.Widget.ListView)dialog.FindViewById(Resource.Id.pickerListView);

            listView.Adapter = new ArrayAdapter<string>(Context, Resource.Layout.CustomListItem, picker.Items);

            listView.ItemClick += ListView_ItemClick;

            dialog.Show();
        }

        private void ListView_ItemClick(object sender, AdapterView.ItemClickEventArgs e)
        {
            picker.SelectedIndex = e.Position;
            dialog.Cancel();
        }
        protected override void Dispose(bool disposing)
        {
            Control.Click -= Control_Click;
            base.Dispose(disposing);
        }
    }
}

위 내용에서 알수 있듯이 Control_Click 에서 앞서 정의한 Dialog, CustomListItem 을 사용하여 팝업을 표시하고 항목 선택시 팝업을 닫도록 처리가 됩니다.

실행결과 (기본 Picker vs Custom Picker)



[Source]
https://github.com/kei-soft/Custom-ComboBox-Dialog/tree/master

 

728x90
그리드형
Posted by kjun
,