1

Я разрабатываю пользовательскую клавиатуру с использованием Xamarin.Почему я не вижу, чтобы вид моего пользовательского вида отображался в Зефире?

У меня на клавиатуре есть переопределенная OnDraw() как для самого контейнера представления, так и для представления дочерних ключей. Я также использую SetWillNotDraw (false) для каждого представления. В настоящее время он прекрасно работает в 5.0.1 на моем планшете Nexus 10.

В Android 6.0.1, на Nexus 6 и Nexus 6P, клавиатура правильно рисует (только цвет фона). Однако представления дочерних ключей никогда не рисуются, даже если я повторяю иерархию представлений и накладываю на них недействительные. Это, по-видимому, характерно для Зефира.

Я не знаю, есть ли что-то новое, что мне нужно учитывать в этой версии Android или если я сталкиваюсь с ошибкой.

Любая помощь или предложения приветствуются.

Код:

KeyboardView

KeyView

+1

В основном вы спрашиваете: «Почему мой код не работает», без предоставления каких-либо. Это будет трудно для кого-то угадать, что происходит. Глядя на трекеры по проблеме, я не вижу, чтобы кто-то имел проблемы с вещами, которые не рисовали. – Cheesebaron

+0

Я предоставил код в нижней части сообщения. –

ответ

0

Исправлено из-за правильной реализации OnMeasure и OnLayout для каждого пользовательского представления с помощью подхода сверху вниз, предложенного в документации для Android.

0

Некоторые дополнительные детали, чтобы пролить свет на оригинальный пост:

трех основных файлов, которые мы используем для рендеринга клавиатуры являются KeyboardView.cs , KeyboardRowView.cs и KeyView.cs.

KeyboardView (контейнер для всей клавиатуры)

Это не имеет никаких проблем рендеринга. KeyboardView простирается LinearLayout и его OnDraw работает метод, вызывая Build() функцию, чтобы создать то, что ему нужно (только базовый фон, который будет «держать» отдельные клавиши):

protected override void OnDraw(Canvas canvas) 
    { 
     Build(); 

     base.OnDraw(canvas); 

     // background 
     Paint bg = new Paint(PaintFlags.AntiAlias); 
     bg.Color = BG; // light blue 
     canvas.DrawRect(0, 0, MeasuredWidth, Height, bg); 

     InvalidateKeys(); 
    } 

(... и Build() ниже. ..)

public void Build() 
    { 
     // only build once 
     if (keyLayout != null) 
      return; 

     // clear out children 
     RemoveAllViews(); 

     // define sizes of stuff 
     if (isPortrait) 
     { 
      keyMargin = (int)(MeasuredWidth * .01f); 
     } 
     else 
     { 
      keyMargin = (int)(MeasuredHeight * .01f); 
     } 

     keyWidth = (MeasuredWidth - (keyMargin * 2))/keyboard.MaxCols; 
     keyHeight = (MeasuredHeight - (keyMargin * 2))/keyboard.Rows.Count; 

     // set general padding around keyboardview 
     SetPadding(keyMargin, keyMargin, keyMargin, keyMargin); 

     // build KeyLayout from the keyboard object 
     keyLayout = new List<List<KeyView>>(); 
     int idx = 0; 
     foreach (List<Key> row in keyboard.Rows) 
     { 
      keyLayout.Add(new List<KeyView>()); 

      // create and add new KeyboardRowView 
      KeyboardRowView krv = new KeyboardRowView(Context, this, idx); 
      AddView(krv); 

      // figure out if we need a margin offset for this row 
      int extraMargin = 0; 
      int numCols = CountRowCols(row); 
      if (numCols < keyboard.MaxCols) 
      { 
       // measure full width of the button container and the total row margin 
       int rowWidth = (int)(numCols * keyWidth); 
       int rowMargin = MeasuredWidth - (keyMargin * 2) - rowWidth; 

       // add the offset 
       extraMargin = rowMargin/2; 
      } 

      // build keys and add them to keyLayout and KeyboardRowView 
      int idx2 = 0; 
      foreach (Key key in row) 
      { 
       int leftMargin = idx2 == 0 ? extraMargin : 0; 
       KeyView kv = new KeyView(Context, this, key, leftMargin); 
       keyLayout[idx].Add(kv); 
       krv.AddView(kv); 

       idx2++; 
      } 

      idx++; 
     } 
    } 

(как дружественное напоминание, что мы делаем это, потому что мы нужны пользовательские клавиатуры, которая может отображать только определенные ключи/команды для наших пользователей.)

KeyboardRowView (контейнер для каждой строки ключей)

Это также распространяется на LinearLayout, а также способ его OnDraw называется:

protected override void OnDraw(Canvas canvas) 
    { 
     base.OnDraw(canvas); 
     Paint paint = new Paint(); 
     paint.SetARGB(255, 0, 0, 0); 
     paint.SetStyle(Paint.Style.Stroke); 
     paint.StrokeWidth = 3; 
     canvas.DrawRGB(255, 255, 255); 
     canvas.DrawRect(0, 0, 100, 100, paint); 
    } 

KeyView (класс который загружает и отображает каждый отдельный ключ)

KeyView расширяет View и View.IOnTouchListener.Конструктор KeyView, называется, но его метод OnDraw никогда не вызывается/казнены:

// key views are always dynamically created 
    public KeyView(Context ctx, KeyboardView parent, Key k, int leftMargin) 
     : base(ctx) 
    { 
     // make sure the key will draw 
     SetWillNotDraw(false); 

     keyboard = parent; 
     key = k; 
     isDown = false; 

     // check for an overridden span to adjust width, if needed 
     int span = string.IsNullOrEmpty(key.Span) ? 1 : Convert.ToInt32(key.Span); 
     int keyWidth = keyboard.keyWidth + ((span - 1) * keyboard.keyWidth); 

     width = keyWidth; 
     height = keyboard.keyHeight; 

     // set margin 
     var parameters = new LinearLayout.LayoutParams(
      LinearLayout.LayoutParams.WrapContent, 
      LinearLayout.LayoutParams.MatchParent 
     ); 
     parameters.LeftMargin = leftMargin; 
     LayoutParameters = parameters; 

     // set touch listener 
     SetOnTouchListener(this); 

     // enable haptic feedback for button presses 
     HapticFeedbackEnabled = true; 
    } 

(... и OnDraw)

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

     KeyState primary = key.Primary; 
     KeyState secondary = key.Secondary; 

     if (keyboard.swapped) 
     { 
      primary = key.Secondary != null ? key.Secondary : key.Primary; 
      secondary = key.Secondary != null ? key.Primary : null; 
     } 

     if (keyboard.shifted) 
     { 
      if (primary.Shift != null) 
       primary = primary.Shift; 

      if (secondary != null && secondary.Shift != null) 
       secondary = secondary.Shift; 
     } 

     // figure out what color the key is supposed to be 
     Paint bg = new Paint(PaintFlags.AntiAlias); 
     bg.Color = GetKeyBgColor(key.Style); 
     if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.Lollipop) 
      canvas.DrawRoundRect(keyboard.keyMargin, keyboard.keyMargin, width - keyboard.keyMargin, height - keyboard.keyMargin, keyboard.keyMargin, keyboard.keyMargin, bg); 
     else 
      canvas.DrawRoundRect(new RectF(keyboard.keyMargin, keyboard.keyMargin, width - keyboard.keyMargin, height - keyboard.keyMargin), keyboard.keyMargin, keyboard.keyMargin, bg); 

     // draw primary key state 
     Paint fg = new Paint(PaintFlags.AntiAlias); 
     fg.TextSize = height * .5f; 
     fg.Color = GetKeyFgColor(key.Style); 
     string character = string.IsNullOrEmpty(primary.Character) ? "#" : primary.Character; 
     int charWidth = Convert.ToInt32(fg.MeasureText(character)); 
     int charX = (width - charWidth)/2; 
     canvas.DrawText(character, charX, (height * .7f), fg); 

     // draw secondary key state 
     if (secondary != null) 
     { 
      fg.TextSize = height * .25f; 
      fg.Color = GetKeyFgColor(key.Style, true); 
      character = string.IsNullOrEmpty(secondary.Character) ? "#" : secondary.Character; 
      charWidth = Convert.ToInt32(fg.MeasureText(character)); 
      charX = width - charWidth - (keyboard.keyMargin * 2); 
      canvas.DrawText(character, charX, (height * .35f), fg); 
     } 
    } 

Я смущен. Оба KeyboardView и KeyboardRowView имеют вызов функции SetWillNotDraw(false); в своих конструкторах/методах инициализации. KeyView также имеет тот же вызов функции и успешно получает каждое значение ключа, которое необходимо визуализировать. То, чего я не понимаю, это то, почему он просто ... не ... рисует ... клавиатуру. (Argh.) Когда я поговорил с оригинальным плакатом об этом, он сказал мне, что все условия выполнены для того, чтобы клавиши клавиатуры были визуализированы. Я попытался установить точки останова, чтобы увидеть, что мешает KeyView's OnDraw быть вызванным, но попал в повторные вызовы функций OnMeasure (и есть много ключей, которые получают визуализированы, чтобы получить старое быстро).

Стоит отметить, что мы тестировали его на последнем Nexus 6P смартфон (работает фондовый Android 6,0 ​​Зефир) и старый Motorola Droid 4 (с Зефир установлен с помощью CyanogenMod 13). Когда мы пытались его с помощью эмулятора Xamarin Android Player (работает Зефир), он на самом деле работал ... я думаю, что эмулятор может быть оказание помощи клавиатуры без проблем, потому что сами фактические телефоны либо

(а) ограничение доступа как-то

(б) потенциально держась старого кода, и мы просто не полностью удалены старые .apks

(с) какой-либо другой вопрос, который я не думал о

Thank вы для своего времени. Если кто-то может подумать о возможном направлении, чтобы войти, это было бы оценено!

Смежные вопросы