ساخت کیبورد سفارشی برای اندروید با Xamarin Forms — از صفر تا صد

۱۲۲۷ بازدید
آخرین به‌روزرسانی: ۱۹ اردیبهشت ۱۴۰۲
زمان مطالعه: ۸ دقیقه
ساخت کیبورد سفارشی برای اندروید با Xamarin Forms — از صفر تا صد

در برخی موارد هنگام اجرای پروژه‌ها نیاز به کیبوردهایی داریم که بعضی امکانات خاص دارند که کیبورد معمولی اندروید فاقد آن است. در این مقاله روش ساخت کیبورد سفارشی اندروید با Xamarin Forms را توضیح خواهیم داد.

فهرست مطالب این نوشته

نخستین گزینه‌ای که در این موارد به ذهن می‌رسد، این است که یک Entry غیر فعال با یک GestureRecognizer اضافه کنیم که یک کنترل به همراه یک انیمیشن نمایش می‌دهد تا ظاهر شدن کیبورد را شبیه‌سازی کند، اما به سرعت متوجه می‌شویم که این ایده قابلیت اجرای مجدد ندارد و لذا آن را کنار می‌گذاریم.

بهترین گزینه این است که مسیر native را پی بگیریم، اما اغلب این مسیرها در نهایت به ایجاد یک سرویس منتهی می‌شوند. بدیهی است که کاربران ما علاقه چندانی به این ندارند که یک کیبورد را جداگانه دانلود کنند تا صرفاً در اپلیکیشن مورد استفاده قرار دهند و باید توجه داشته باشیم که ما از Xamarin Forms استفاده می‌کنیم. از آنجا که می‌خواهیم این کیبورد سفارشی را در Xamarin Forms پیاده‌سازی کنیم، بهترین گزینه ممکن یک Custom Renderer (+) برای کنترل Entry است که از EditText به عنوان مبنایی برای کنترل native استفاده می‌کند. تلاش می‌کنیم تا همه دانشی که در نتیجه بررسی گزینه‌های مختلف به دست آمده است را در مورد این کیبورد سفارشی اندروید پیاده‌سازی کنیم.

کدنویسی

توجه کنید که به منظور پیاده‌سازی کیبورد سفارشی اندروید باید Xamarin Forms با نسخه 3.6.0.135200-pre1 یا بالاتر استفاده کنید، زیرا به متد OnFocusChangeRequest نیاز داریم که در این نسخه‌ها موجود است. ابتدا یک کنترل سفارشی می‌سازیم که یک مشخصه «اتصال‌پذیر» bindable دارد.

در این مشخصه، خصوصیتی به نام EnterCommand و با نوع ICommand وجود دارد که برای اتصال به اکشن فشرده شدن کلید Enter استفاده می‌شود. اینک کنترل سفارشی ما به صورت زیر است:

1namespace CustomKeyboard
2{
3    public class EntryWithCustomKeyboard : Entry
4    {
5        public static readonly BindableProperty EnterCommandProperty = BindableProperty.Create(
6            nameof(EnterCommand),
7            typeof(ICommand),
8            typeof(EntryWithCustomKeyboard),
9            default(ICommand),
10            BindingMode.OneWay
11        );
12
13        public ICommand EnterCommand
14        {
15            get => (ICommand)GetValue(EnterCommandProperty);
16            set => SetValue(EnterCommandProperty, value);
17        }
18    }
19}

سپس به پروژه اندروید می‌رویم و آنجا کار می‌کنیم. در ادامه دوباره به پروژه Xamarin Forms خود بازمی‌گردیم. پیش از ادامه باید مطمئن شویم که همه پکیج‌های اندروید مورد نیاز را داریم:

کیبورد سفارشی با Xamarin Forms

سپس باید MainActivity اندروید خود را ویرایش کنیم تا از نمایش کیبورد نیتیو جلوگیری کنیم. به این منظور از خصوصیت SoftInputMode.StateAlwaysHidden استفاده می‌کنیم:

1namespace CustomKeyboard.Droid
2{
3    [Activity(
4        Label = "CustomKeyboard",
5        Icon = "@mipmap/icon",
6        Theme = "@style/MainTheme",
7        MainLauncher = true,
8        ScreenOrientation = ScreenOrientation.Portrait,
9        ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation,
10        WindowSoftInputMode = SoftInput.StateAlwaysHidden,
11        LaunchMode = LaunchMode.SingleTask)]
12    public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
13    {
14        protected override void OnCreate(Bundle savedInstanceState)
15        {
16            TabLayoutResource = Resource.Layout.Tabbar;
17            ToolbarResource = Resource.Layout.Toolbar;
18
19            base.OnCreate(savedInstanceState);
20            global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
21
22            LoadApplication(new App());
23
24            Window.SetSoftInputMode(SoftInput.StateAlwaysHidden);
25        }
26    }
27}

کار بعدی که انجام می‌دهیم آغاز تعریف کیبورد سفارشی است.

درون پوشه Resource/layout یک لی‌آوت اندروید به نام CustomKeyboard و از نوع InputMethodService.Keyboard ایجاد می‌کنیم.

1<?xml version="1.0" encoding="utf-8"?>
2<android.inputmethodservice.Keyboard
3    xmlns:android="http://schemas.android.com/apk/res/android"
4    android:id="@+id/keyboard"
5    android:layout_width="match_parent"
6    android:layout_height="wrap_content"
7    android:layout_alignParentBottom="true"
8    android:keyPreviewLayout="@null"
9    android:keyBackground="@drawable/keyboard_background"
10    android:textColor="@android:color/white"
11    android:background="@android:color/white" />

قبل از هر چیز مشخصه alignParentBottom را به صورت true تنظیم می‌کنیم، زیرا می‌خواهیم کیبورد از سمت پایین صفحه ظاهر شود. سپس مشخصه keyPreviewLayout را به صورت null تنظیم می‌کنیم، زیرا در این نمونه نمی‌خواهیم وقتی کلیدی فشرده شد، لی‌آوت واکنشی داشته باشد.

چنان که می‌بینید مشخصه keyBackground به یک drawable به نام keyboard_background اشاره می‌کند که وجود ندارد، بنابراین باید آن را درون پوشه Drawable به صورت یک فایل xml بسازیم. در این بخش یک سلکتور حالت برای دو حالت کلید یعنی normal (بدون فشرده شدن) و pressed (فشرده شدن) تعریف می‌کنیم.

1<?xml version="1.0" encoding="UTF-8" ?>
2<selector xmlns:android="http://schemas.android.com/apk/res/android">
3    <item
4        android:state_focused="false"
5        android:state_selected="false"
6        android:state_pressed="false"
7        android:drawable="@drawable/normal" />
8    <item
9        android:state_pressed="true"
10        android:drawable="@drawable/pressed" />
11</selector>

چنان که می‌بینید می‌خواهیم دو xml دیگر درون پوشه Drawable بسازیم که در آن‌ها حس و ظاهر کیبورد خود را تعریف می‌کنیم تا با قالب اپلیکیشن هماهنگ باشد.

فایل normal.xml

1<?xml version="1.0" encoding="UTF-8" ?>
2<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
3    <item android:left="2dp" android:right="2dp">
4        <shape android:shape="rectangle">
5            <solid android:color="#FFFFFF" />
6        </shape>
7    </item>
8    
9    <item android:bottom="2dp">
10        <shape android:shape="rectangle">
11            <solid android:color="#FF6A00" />
12        </shape>
13    </item>
14</layer-list>

فایل pressed.xml

1<?xml version="1.0" encoding="UTF-8" ?>
2<shape xmlns:android="http://schemas.android.com/apk/res/android">
3    <solid android:color="#FF8C00" />
4</shape>

اینک درون پوشه values یک فایل xml به نام ids ایجاد می‌کنیم که در ادامه مورد استفاده قرار خواهد گرفت:

1<?xml version="1.0" encoding="UTF-8" ?>
2<resources>
3    <item
4        name="customKeyboard"
5        type="id" />
6</resources>

سپس درون پوشه Resources یک پوشه به نام xml می‌سازیم. درون آن یک فایل xml ایجاد می‌کنیم که کلیدهای کیبورد خاص خود را در آن تعریف می‌کنیم.

\در این مورد کیبورد به نام special_keyboard خوانده می‌شود و از نوع Keyboard خواهد بود که در آن اندازه افقی و عمودی کلیدها، مشخصه‌های horizontalGap و verticalGap که به فاصله‌بندی اشاره می‌کنند و همچنین نوع ابعاد ‎%p را تعریف می‌کنیم که نوعی از درصد مرتبط با نمای والد است.

هر ردیف از کلیدها درون بخش‌هایی قرار می‌گیرد که با تگ‌های <Row></Row> از هم جدا می‌شوند. ردیف نخست با یک خط جداکننده اشغال شده است که محدوده کیبورد را نشان می‌دهد. تگ ردیف دارای ارتفاع 4dp است و بخش فوقانی کیبورد را از طریق مشخصه rowEdgeFlags نشان می‌دهد. سپس یک خط به صورت یک key درون تگ‌های Row اضافه می‌کنیم که عرض کامل کیبورد را اشغال می‌کند. جداکننده ما یک Xml دیگر است که درون پوشه Drawable ایجاد خواهیم کرد.

فایل kb_separator_line.xml

1<?xml version="1.0" encoding="utf-8"?>
2<shape xmlns:android="http://schemas.android.com/apk/res/android"
3    android:shape="rectangle" >
4    <stroke android:width="1dp" />
5    <size android:height="2dp" />
6</shape>

هر Key دو مشخصه صراحتاً ضروری به نام‌های codes و keyLabel دارد. code عددی است که به سیستم عامل اعلام می‌کند که کلید به کدام حرف یا نماد مربوط است. کیبوردهای سفارشی مختلف از کدهای گوناگونی برای اشاره به نماد یا کلیدها استفاده می‌کنند؛ اما بهترین فرست کدها که اغلب نیازها را تأمین می‌کند Android Keycodes (+) است. می‌توانید مستندات رسمی اندروید (+) و یا حتی مستندات اندروید زامارین (+) را نیز ببینید، اما هیچ کدام از آن‌ها با دقت کار نمی‌کنند.

keyLabel رشته‌ای است که قرار است در کلید ما نمایش یابد. قرار دادن این مشخصه حتی در صورتی که قصد نمایش هیچ متنی روی کلید ندارید، حائز اهمیت بالایی است. در آن حالت می‌توانید از ""=keyLabel استفاده کنید.

در مورد استایل در ابتدا و انتهای هر ردیف یک کلید با کد معادل 0 اضافه می‌کنیم. این کلیدها دارای مشخصه keyEdgeFlags با مقادیر left یا right مناسب هستند. کد کامل کیبورد به صورت زیر است:

فایل special_keyboard.xml

1<?xml version="1.0" encoding="UTF-8" ?>
2<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
3    android:keyWidth="8%p"
4    android:keyHeight="50dp"
5    android:horizontalGap="1%p"
6    android:verticalGap="1%p">
7    
8    <Row android:keyHeight="4dp" android:rowEdgeFlags="top" android:verticalGap="1%p">
9        <Key android:codes="0" android:keyWidth="100%p" android:keyIcon="@drawable/kb_separator_line" />
10    </Row>
11    
12    <Row>
13        <Key android:codes="0" android:keyWidth="0dp" android:horizontalGap="2%p" android:keyEdgeFlags="left" />
14        <Key android:codes="29" android:keyLabel="A" android:keyWidth="18%p" />
15        <Key android:codes="30" android:keyLabel="B" android:keyWidth="18%p" />
16        <Key android:codes="31" android:keyLabel="C" android:keyWidth="18%p" />
17        <Key android:codes="32" android:keyLabel="D" android:keyWidth="18%p" />
18        <Key android:codes="33" android:keyLabel="E" android:keyWidth="18%p" />
19        <Key android:codes="0" android:keyWidth="0dp" android:horizontalGap="2%p" android:keyEdgeFlags="right"  />
20    </Row>
21
22    <Row>
23        <Key android:codes="0" android:keyWidth="0dp" android:horizontalGap="2%p" android:keyEdgeFlags="left" />
24        <Key android:codes="8" android:keyLabel="1" android:keyWidth="18%p" />
25        <Key android:codes="9" android:keyLabel="2" android:keyWidth="18%p" />
26        <Key android:codes="10" android:keyLabel="3" android:keyWidth="18%p" />
27        <Key android:codes="11" android:keyLabel="4" android:keyWidth="18%p" />
28        <Key android:codes="12" android:keyLabel="5" android:keyWidth="18%p" />
29        <Key android:codes="0" android:keyWidth="0dp" android:horizontalGap="2%p" android:keyEdgeFlags="right"  />
30    </Row>
31    
32    <Row>
33        <Key android:codes="0" android:keyWidth="0dp" android:horizontalGap="2%p" android:keyEdgeFlags="left" />
34        <Key android:codes="13" android:keyLabel="6" android:keyWidth="18%p" />
35        <Key android:codes="14" android:keyLabel="7" android:keyWidth="18%p" />
36        <Key android:codes="15" android:keyLabel="8" android:keyWidth="18%p" />
37        <Key android:codes="16" android:keyLabel="9" android:keyWidth="18%p" />
38        <Key android:codes="7" android:keyLabel="0" android:keyWidth="18%p" />
39        <Key android:codes="0" android:keyWidth="0dp" android:horizontalGap="2%p" android:keyEdgeFlags="right"  />
40    </Row>
41    
42    <Row>
43        <Key android:codes="0" android:keyWidth="0dp" android:horizontalGap="2%p" android:keyEdgeFlags="left" />
44        <Key android:codes="67" android:keyLabel="DELETE" android:keyWidth="37%p" />
45        <Key android:codes="66" android:keyLabel="ENTER" android:keyWidth="56%p" />
46        <Key android:codes="0" android:keyWidth="0dp" android:horizontalGap="2%p" android:keyEdgeFlags="right"  />
47    </Row>
48</Keyboard>

در نهایت پیش از کار روی رندر کننده پوشه دیگری درون Resources به نام anim ایجاد می‌کنیم که در آن یک فایل xml به نام slide_in_bottom می سازیم. انیمیشن ظاهرشدن کیبورد ما روی صفحه در این فایل قرار می‌گیرد:

1<?xml version="1.0" encoding="UTF-8" ?>
2<set xmlns:android="http://schemas.android.com/apk/res/android">
3    <translate android:fromYDelta="150%p" android:toYDelta="0" android:duration="200"/>
4    <alpha android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="200" />
5</set>

اکنون یک پوشه جدید به نام Renderers روی پروژه اندروید ایجاد می‌کنیم و درون آن رندر کننده خود را که EntryWithCustomKeyboardRenderer نام دارد و از EntryRenderer بسط یافته و اینترفیس IOnKeyboardActionListener را پیاده‌سازی می‌کند تعریف می‌کنیم. همچنین درون رندر کننده سفارشی یک کلاس خصوصی به نام NullListener ایجاد می‌کنیم که قرار است از Java.Lang.Object بسط یابد و اینترفیس IOnKeyboardActionListener را پیاده‌سازی کند که در رندر کننده خود مورد استفاده قرار می‌دهیم تا از استثناهای null جلوگیری کنیم.

1[assembly: ExportRenderer(typeof(EntryWithCustomKeyboard), typeof(EntryWithCustomKeyboardRenderer))]
2namespace CustomKeyboard.Droid.Renderers
3{
4    public class EntryWithCustomKeyboardRenderer : EntryRenderer, IOnKeyboardActionListener
5    {
6        private Context context;
7
8        private EntryWithCustomKeyboard entryWithCustomKeyboard;
9
10        private Android.InputMethodServices.KeyboardView mKeyboardView;
11        private Android.InputMethodServices.Keyboard mKeyboard;
12
13        private InputTypes inputTypeToUse;
14
15        private bool keyPressed;
16
17        public EntryWithCustomKeyboardRenderer(Context context) : base(context)
18        {
19            this.context = context;
20        }
21
22        protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
23        {
24            base.OnElementChanged(e);
25
26            var newCustomEntryKeyboard = e.NewElement as EntryWithCustomKeyboard;
27            var oldCustomEntryKeyboard = e.OldElement as EntryWithCustomKeyboard;
28
29            if (newCustomEntryKeyboard == null && oldCustomEntryKeyboard == null)
30                return;
31
32            if (e.NewElement != null)
33            {
34                this.entryWithCustomKeyboard = newCustomEntryKeyboard;
35                this.CreateCustomKeyboard();
36
37                this.inputTypeToUse = this.entryWithCustomKeyboard.Keyboard.ToInputType() | InputTypes.TextFlagNoSuggestions;
38                
39                // Here we set the EditText event handlers
40                this.EditText.FocusChange += Control_FocusChange;
41                this.EditText.TextChanged += EditText_TextChanged;
42                this.EditText.Click += EditText_Click;
43                this.EditText.Touch += EditText_Touch;
44            }
45
46            // Dispose control
47            if (e.OldElement != null)
48            {
49                this.EditText.FocusChange -= Control_FocusChange;
50                this.EditText.TextChanged -= EditText_TextChanged;
51                this.EditText.Click -= EditText_Click;
52                this.EditText.Touch -= EditText_Touch;
53            }
54        }
55
56        protected override void OnFocusChangeRequested(object sender, VisualElement.FocusRequestArgs e)
57        {
58            e.Result = true;
59
60            if (e.Focus)
61                this.Control.RequestFocus();
62            else
63                this.Control.ClearFocus();
64        }
65
66        // Event handlers
67        private void Control_FocusChange(object sender, FocusChangeEventArgs e)
68        {
69            // Workaround to avoid null reference exceptions in runtime
70            if (this.EditText.Text == null)
71                this.EditText.Text = string.Empty;
72
73            if (e.HasFocus)
74            {
75                this.mKeyboardView.OnKeyboardActionListener = this;
76
77                if (this.Element.Keyboard == Keyboard.Text)
78                    this.CreateCustomKeyboard();
79
80                this.ShowKeyboardWithAnimation();
81            }
82            else
83            {
84                // When the control looses focus, we set an empty listener to avoid crashes
85                this.mKeyboardView.OnKeyboardActionListener = new NullListener();
86
87                this.HideKeyboardView();
88            }
89        }
90
91        private void EditText_TextChanged(object sender, Android.Text.TextChangedEventArgs e)
92        {
93            // Ensure no key is pressed to clear focus
94            if (this.EditText.Text.Length != 0 && !this.keyPressed)
95            {
96                this.EditText.ClearFocus();
97                return;
98            }
99        }
100
101        private void EditText_Click(object sender, System.EventArgs e)
102        {
103            ShowKeyboardWithAnimation();
104        }
105
106        private void EditText_Touch(object sender, TouchEventArgs e)
107        {
108            this.EditText.InputType = InputTypes.Null;
109
110            this.EditText.OnTouchEvent(e.Event);
111
112            this.EditText.InputType = this.inputTypeToUse;
113
114            e.Handled = true;
115        }
116
117        // Keyboard related section
118
119        // Method to create our custom keyboard view
120        private void CreateCustomKeyboard()
121        {
122            var activity = (Activity)this.context;
123
124            var rootView = activity.Window.DecorView.FindViewById(Android.Resource.Id.Content);
125            var activityRootView = (ViewGroup)((ViewGroup)rootView).GetChildAt(0);
126
127            this.mKeyboardView = activityRootView.FindViewById<Android.InputMethodServices.KeyboardView>(Resource.Id.customKeyboard);
128
129            // If the previous line fails, it means the keyboard needs to be created and added
130            if (this.mKeyboardView == null)
131            {
132                this.mKeyboardView = (Android.InputMethodServices.KeyboardView)activity.LayoutInflater.Inflate(Resource.Layout.CustomKeyboard, null);
133                this.mKeyboardView.Id = Resource.Id.customKeyboard;
134                this.mKeyboardView.Focusable = true;
135                this.mKeyboardView.FocusableInTouchMode = true;
136
137                this.mKeyboardView.Release += (sender, e) => { };
138
139                var layoutParams = new Android.Widget.RelativeLayout.LayoutParams(LayoutParams.MatchParent, LayoutParams.WrapContent);
140                layoutParams.AddRule(LayoutRules.AlignParentBottom);
141                activityRootView.AddView(this.mKeyboardView, layoutParams);
142            }
143
144            this.HideKeyboardView();
145
146            this.mKeyboard = new Android.InputMethodServices.Keyboard(this.context, Resource.Xml.special_keyboard);
147
148            this.SetCurrentKeyboard();
149        }
150
151        private void SetCurrentKeyboard()
152        {
153            this.mKeyboardView.Keyboard = this.mKeyboard;
154        }
155
156        // Method to show our custom keyboard
157        private void ShowKeyboardWithAnimation()
158        {
159            // First we must ensure that keyboard is hidden to
160            // prevent showing it multiple times
161            if (this.mKeyboardView.Visibility == ViewStates.Gone)
162            {
163                // Ensure native keyboard is hidden
164                var imm = (InputMethodManager)this.context.GetSystemService(Context.InputMethodService);
165                imm.HideSoftInputFromWindow(this.EditText.WindowToken, 0);
166
167                this.EditText.InputType = InputTypes.Null;
168
169                var animation = AnimationUtils.LoadAnimation(this.context, Resource.Animation.slide_in_bottom);
170                this.mKeyboardView.Animation = animation;
171
172                this.mKeyboardView.Enabled = true;
173                
174                // Show custom keyboard with animation
175                this.mKeyboardView.Visibility = ViewStates.Visible;
176            }
177        }
178        
179        // Method to hide our custom keyboard
180        private void HideKeyboardView()
181        {
182            this.mKeyboardView.Visibility = ViewStates.Gone;
183            this.mKeyboardView.Enabled = false;
184
185            this.EditText.InputType = InputTypes.Null;
186        }
187        
188        // Implementing IOnKeyboardActionListener interface
189        public void OnKey([GeneratedEnum] Keycode primaryCode, [GeneratedEnum] Keycode[] keyCodes)
190        {
191            if (!this.EditText.IsFocused)
192                return;
193            
194            // Ensure key is pressed to avoid removing focus
195            this.keyPressed = true;
196
197            // Create event for key press
198            long eventTime = JavaSystem.CurrentTimeMillis();
199
200            var ev = new KeyEvent(eventTime, eventTime, KeyEventActions.Down, primaryCode, 0, 0, 0, 0,
201                                  KeyEventFlags.SoftKeyboard | KeyEventFlags.KeepTouchMode);
202                                  
203            // Ensure native keyboard is hidden
204            var imm = (InputMethodManager)this.context.GetSystemService(Context.InputMethodService);
205            imm.HideSoftInputFromWindow(this.EditText.WindowToken, HideSoftInputFlags.None);
206
207            this.EditText.InputType = this.inputTypeToUse;
208
209            switch(ev.KeyCode)
210            {
211                case Keycode.Enter:
212                    // Sometimes EditText takes long to update the HasFocus status
213                    if (this.EditText.HasFocus)
214                    {
215                        // Close the keyboard, remove focus and launch command asociated action
216                        this.HideKeyboardView();
217
218                        this.ClearFocus();
219
220                        this.entryWithCustomKeyboard.EnterCommand?.Execute(null);
221                    }
222
223                    break;
224            }
225
226            // Set the cursor at the end of the text
227            this.EditText.SetSelection(this.EditText.Text.Length);
228
229            if (this.EditText.HasFocus)
230            {
231                this.DispatchKeyEvent(ev);
232
233                this.keyPressed = false;
234            }
235        }
236
237        public void OnPress([GeneratedEnum] Keycode primaryCode)
238        {
239        }
240
241        public void OnRelease([GeneratedEnum] Keycode primaryCode)
242        {
243        }
244
245        public void OnText(ICharSequence text)
246        {
247        }
248
249        public void SwipeDown()
250        {
251        }
252
253        public void SwipeLeft()
254        {
255        }
256
257        public void SwipeRight()
258        {
259        }
260
261        public void SwipeUp()
262        {
263        }
264        
265        private class NullListener : Java.Lang.Object, IOnKeyboardActionListener
266        {
267            public void OnKey([GeneratedEnum] Keycode primaryCode, [GeneratedEnum] Keycode[] keyCodes)
268            {
269            }
270
271            public void OnPress([GeneratedEnum] Keycode primaryCode)
272            {
273            }
274
275            public void OnRelease([GeneratedEnum] Keycode primaryCode)
276            {
277            }
278
279            public void OnText(ICharSequence text)
280            {
281            }
282
283            public void SwipeDown()
284            {
285            }
286
287            public void SwipeLeft()
288            {
289            }
290
291            public void SwipeRight()
292            {
293            }
294
295            public void SwipeUp()
296            {
297            }
298        }
299    }
300}

در نهایت به پروژه Xamarin Forms باز می‌گردیم و کیبورد خاص خود را پیاده‌سازی می‌کنیم:

فایل MainPage.xaml

1<?xml version="1.0" encoding="utf-8"?>
2<ContentPage
3    xmlns="http://xamarin.com/schemas/2014/forms"
4    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
5    xmlns:local="clr-namespace:CustomKeyboard"
6    x:Class="CustomKeyboard.MainPage">
7    <ScrollView>
8        <StackLayout
9            Orientation="Vertical">
10            
11            <local:EntryWithCustomKeyboard
12                x:Name="entry1"
13                HorizontalOptions="FillAndExpand"
14                Margin="0, 0, 0, 20"
15                Keyboard="Text"
16                TextColor="Black"
17                Placeholder="Custom Keyboard entry..." />
18
19            <local:EntryWithCustomKeyboard
20                x:Name="entry2"
21                HorizontalOptions="FillAndExpand"
22                Keyboard="Text"
23                TextColor="Black"
24                Placeholder="Custom Keyboard entry 2..." />
25
26        </StackLayout>
27    </ScrollView>
28</ContentPage>

همچنین در کد قبلی خود EnterCommand را که پیش‌تر ساختیم پیاده‌سازی می‌کنیم. بدین ترتیب اکشنی که می‌خواهیم هنگام فشردن کلید اینتر کیبورد سفارشی انجام یابد را تعریف می‌کنیم:

فایل MainPage.cs

1namespace CustomKeyboard
2{
3    public partial class MainPage : ContentPage
4    {
5        public MainPage()
6        {
7            InitializeComponent();
8
9            // Here we implement the action of the Enter button on our custom keyboard
10            this.entry1.EnterCommand = new Command(() => this.entry2.Focus());
11            this.entry2.EnterCommand = new Command(() => this.entry1.Focus());
12        }
13    }
14}

نتیجه نهایی به صورت زیر است:

کیبورد سفارشی با Xamarin Forms

بدین ترتیب به پایان راهنما می‌رسیم. برای مشاهده کد کامل این پروژه به این ریپوی گیت‌هاب (+) مراجعه کنید.

اگر این مطلب برای شما مفید بوده است، آموزش‌های زیر نیز به شما پیشنهاد می‌شوند:

==

بر اساس رای ۵۹ نفر
آیا این مطلب برای شما مفید بود؟
اگر بازخوردی درباره این مطلب دارید یا پرسشی دارید که بدون پاسخ مانده است، آن را از طریق بخش نظرات مطرح کنید.
منابع:
swlh
۵ دیدگاه برای «ساخت کیبورد سفارشی برای اندروید با Xamarin Forms — از صفر تا صد»

درود استاد
بنده یکم گیج شدم اگه میشه لطف کنید فیلم همین کارو بذارین که راحت تر بتونم بفهممش…
مورد ضروری دمتون گرم لطفاً کمک کنید🙏🏻

سلام
آموزش ساخت کیبورد واقعا خیلی خوب بود ممنون

خیلی زیبا آموزش دادین ، خیلی ممنون برای این آموزشتون

دمتون گرم عالی

سلام لطفا اگر کسی برنانکه نویسی کیبورد سفارشی بلده بسازه به ایمیل من پیام بده بهم یاد بده خیلی ازش ممنون میشم

نظر شما چیست؟

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *