我的自定义 android 键盘应用程序,使用 visual studio 和 c#,在屏幕顶部绘制,而不是底部

问题描述 投票:0回答:0

我正在制作一个自定义键盘,但是当我在我的设备上选择键盘时,它绘制在屏幕的顶部而不是底部,有效地阻止了我正在使用键盘写入的输入。

我试过在布局参数中设置重力以及 keyboar_layout.xml 文件中的相对布局。它拒绝在底部绘制。我一直在为我的键盘使用现在已经过时的 Keyboardview,并且工作正常。但是当我切换到使用 View.IOnTouchListener 时,这是它开始不在底部绘制的时候。在我的 oncreateview 中,我修复它的一些尝试被注释掉了,但无论哪种方式(如果它没有被注释掉)它仍然会绘制到屏幕顶部。

这里是keyboard_layout.xml:

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_alignParentBottom="true"
    android:background="@android:color/darker_gray"
    android:orientation="vertical">

    <TextView
        android:id="@+id/myLabel"
        android:layout_alignParentBottom="true"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Label text"
        android:textColor="@android:color/white"
        android:background="@android:color/black"
        android:layout_marginTop="0.0dp" />

    <NewKeyboard.CustomKeyboardView
        android:id="@+id/keyboard"
        android:layout_alignParentBottom="true"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:background="@android:color/black"
        android:layout_marginTop="0.0dp" />
</LinearLayout>

Here is the manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.yourcompanyname.NewKeyboard" 
    android:versionCode="1" android:versionName="1.0">
    <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="33" />
    <application android:label="NewKeyboard">
        <service android:name=".MyInputMethodService"
                 android:permission="android.permission.BIND_INPUT_METHOD"
                 android:exported="true">
            <intent-filter>
                <action android:name="android.view.InputMethod" />
            </intent-filter>
            <meta-data android:name="android.view.im" android:resource="@xml/method" />
        </service>
    </application>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
</manifest>
Here is method.xml: 
<input-method xmlns:android="http://schemas.android.com/apk/res/android">
    <subtype
        android:label="@string/subtype_en_US"
        android:imeSubtypeLocale="en_US"
        android:imeSubtypeMode="keyboard"
        android:imeSubtypeExtraValue="AsciiCapable,EmojiCapable,SupportTouchPosition" />
</input-method>

CustomKeyboardview.cs:
using Android.Content;
using Android.Content.Res;
using Android.Graphics;
using Android.Runtime;
using Android.Util;
using Android.Views;
using Android.Views.InputMethods;
using Android.Widget;
using System;
using System.Collections.Generic;
using System.Xml;
using System.Xml.Linq;

namespace NewKeyboard
{
    public class Key
    {
        public int Code { get; set; }
        public string Label { get; set; }
        public RectF Rect { get; set; }
    }

    [Register("com.yourcompanyname.NewKeyboard.CustomKeyboardView")]
    public class CustomKeyboardView : View, View.IOnTouchListener
    {
        private List<Key> keys;
        private Paint keyPaint;
        private Paint labelPaint;

        public MyInputMethodService InputMethodService { get; set; }

        public CustomKeyboardView(Context context) : base(context)
        {
            Initialize();
        }

        public CustomKeyboardView(Context context, IAttributeSet attrs) : base(context, attrs)
        {
            Initialize();
        }

        public CustomKeyboardView(Context context, IAttributeSet attrs, int defStyleAttr) : base(context, attrs, defStyleAttr)
        {
            Initialize();
        }

        public CustomKeyboardView(Context context, IAttributeSet attrs, int defStyleAttr, int defStyleRes) : base(context, attrs, defStyleAttr, defStyleRes)
        {
            Initialize();
        }

        protected CustomKeyboardView(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
        {
        }

        private void Initialize()
        {
            // Create the keys from the context
            keys = KeyboardLoader.CreateKeysList(Context);

            // Initialize the Paint objects for drawing keys and labels
            keyPaint = new Paint { Color = Color.LightGray };
            labelPaint = new Paint { Color = Color.Black, TextSize = 40 };

            // Set the OnTouchListener for this view
            SetOnTouchListener(this);
        }

        protected override void OnDraw(Canvas canvas)
        {
            base.OnDraw(canvas);

            // Draw the keys
            foreach (var key in keys)
            {
                canvas.DrawRoundRect(key.Rect, 5, 5, keyPaint);
                canvas.DrawText(key.Label, key.Rect.Left + key.Rect.Width() / 2 - labelPaint.MeasureText(key.Label) / 2, key.Rect.Top + key.Rect.Height() / 2 + labelPaint.TextSize / 2, labelPaint);
            }
        }

        public bool OnTouch(View v, MotionEvent e)
        {
            if (e.Action == MotionEventActions.Down || e.Action == MotionEventActions.Move)
            {
                // Find the key that was touched
                foreach (var key in keys)
                {
                    if (key.Rect.Contains((int)e.GetX(), (int)e.GetY()))
                    {
                        // Trigger the appropriate key action
                        var ic = InputMethodService.CurrentInputConnection;
                        switch (key.Code)
                        {
                            case -1: // Shift
                                // Toggle caps and update the keyboard
                                break;
                            case -4: // Done
                                ic.SendKeyEvent(new KeyEvent(KeyEventActions.Down, Keycode.Enter));
                                break;
                            case -5: // Delete
                                ic.DeleteSurroundingText(1, 0);
                                break;
                            default:
                                char code = (char)key.Code;
                                ic.CommitText(code.ToString(), 1);
                                break;
                        }
                        break;
                    }
                }
            }

            return true;
        }
    }

    public static class KeyboardLoader
    {
        public static List<Key> CreateKeysList(Context context)
        {
            var keys = new List<Key>();

            float keyWidth = 0.1f * Resources.System.DisplayMetrics.WidthPixels;
            float keyHeight = TypedValue.ApplyDimension(ComplexUnitType.Dip, 60, context.Resources.DisplayMetrics);

            float x = 0;
            float y = 0;

            int[][] keyCodes = new int[][]
            {
            new int[] { 49, 50, 51, 52, 53, 54, 55, 56, 57, 48 },
            new int[] { 113, 119, 101, 114, 116, 121, 117, 105, 111, 112 },
            new int[] { 97, 115, 100, 102, 103, 104, 106, 107, 108, -2 },
            new int[] { -1, 122, 120, 99, 118, 98, 110, 109, 46, -3 },
            new int[] { 44, 47, 32, -5, -4 }
            };

            string[][] keyLabels = new string[][]
            {
            new string[] { "1", "2", "3", "4", "5", "6", "7", "8", "9", "0" },
            new string[] { "q", "w", "e", "r", "t", "y", "u", "i", "o", "p" },
            new string[] { "a", "s", "d", "f", "g", "h", "j", "k", "l", "# @" },
            new string[] { "CAPS", "z", "x", "c", "v", "b", "n", "m", ".", "? ! :" },
            new string[] { ",", "/", "SPACE", "DEL", "DONE" }
            };

            for (int row = 0; row < keyCodes.Length; row++)
            {
                x = 0;
                for (int col = 0; col < keyCodes[row].Length; col++)
                {
                    var key = new Key
                    {
                        Code = keyCodes[row][col],
                        Label = keyLabels[row][col],
                        Rect = new RectF(x, y, x + keyWidth, y + keyHeight)
                    };

                    Console.WriteLine($"Creating key: Code: {key.Code}, Label: {key.Label}, Rect: {key.Rect}");
                    keys.Add(key);
                    x += keyWidth;
                }
                y += keyHeight;
            }

            return keys;
        }
      
    }
}

MainActivity.cs:
using Android.App;
using Android.OS;
using Android.Runtime;
using AndroidX.AppCompat.App;

namespace NewKeyboard
{
    [Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true)]
    public class MainActivity : AppCompatActivity
    {
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
            Xamarin.Essentials.Platform.Init(this, savedInstanceState);

            // Set our view from the "main" layout resource
            SetContentView(Resource.Layout.HowToUse_layout);
        }
        public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
        {
            Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);

            base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
        }
    }
}

And finally MyInputMethodService.cs:
using Android.Content;
using Android.InputMethodServices;
using Android.Runtime;
using Android.Views;
using Android.Views.InputMethods;
using Android.Widget;
using Keycode = Android.Views.Keycode;

namespace NewKeyboard
{
    [Register("com.yourcompanyname.NewKeyboard.MyInputMethodService")]
    public class MyInputMethodService : InputMethodService
    {
        private View layout;
        private CustomKeyboardView keyboardView;
        public override void OnComputeInsets(Insets outInsets)
        {
            base.OnComputeInsets(outInsets);
                outInsets.ContentTopInsets = outInsets.VisibleTopInsets;
        }

        public override bool OnEvaluateFullscreenMode()
        {
            return false;
        }
        public override View OnCreateInputView()
        {
            layout = LayoutInflater.Inflate(Resource.Layout.keyboard_layout, null);
            keyboardView = layout.FindViewById<CustomKeyboardView>(Resource.Id.keyboard);
            keyboardView.InputMethodService = this;

            //LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.WrapContent);
            //layoutParams.Gravity = GravityFlags.Bottom;
            //layout.LayoutParameters = layoutParams;

            return layout;
        }

        public override View OnCreateCandidatesView()
        {
            // Return null if you don't need a candidates view
            return null;
        }
    }
}
c# android keyboard
© www.soinside.com 2019 - 2024. All rights reserved.