簡體   English   中英

為什么自定義視圖的子視圖不會在棉花糖中渲染?

[英]Why won't the child views of my custom view render in Marshmallow?

我正在使用Xamarin開發自定義鍵盤。

我的鍵盤視圖的視圖容器本身及其子鍵視圖都有一個重寫的OnDraw()。 我還為每個視圖適當地使用SetWillNotDraw(false)。 目前,在我的Nexus 10平板電腦上的5.0.1版本中,它運行良好。

在Android 6.0.1中,在Nexus 6和Nexus 6P上,鍵盤視圖會正確繪制自身(只是背景顏色)。 但是,即使我遍歷視圖層次結構並對每個視圖強制無效,也不會繪制子鍵視圖。 這似乎是棉花糖特有的。

我不知道在此版本的Android中是否需要解決一些新問題,或者是否遇到錯誤。

歡迎任何幫助或建議。

碼:

KeyboardView

的KeyView

一些額外的細節可以闡明原始帖子:

我們用於鍵盤渲染的三個主要文件是KeyboardView.csKeyboardRowView.csKeyView.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擴展了ViewView.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);
        }
    }

我很困惑。 KeyboardViewKeyboardRowView都具有SetWillNotDraw(false); 在其構造函數/初始化方法中調用函數。 KeyView也具有相同的函數調用,並成功接收需要呈現的每個鍵值。 我不明白的是為什么它只是...不會...繪制...鍵盤。 (Argh。)當我與原始海報商談此事時,他告訴我所有條件都已得到滿足,以便呈現鍵盤鍵。 我嘗試附加斷點以查看阻止調用KeyView的OnDraw的原因,但是陷入了重復的OnMeasure函數調用中(並且渲染了很多鍵,因此很快就變老了)。

值得一提的是,我們已經在最新的Nexus 6P智能手機(運行時的Android 6.0棉花糖) 舊版的Motorola Droid 4(通過CyanogenMod 13安裝了棉花糖)上進行了測試。 當我們使用Xamarin Android Player模擬器(運行棉花糖)進行嘗試時,它實際上可以工作 ……我的猜測是,模擬器可能毫無問題地渲染了鍵盤,因為實際的手機本身就是

(a)以某種方式限制訪問

(b)可能會保留舊代碼,而我們還沒有完全刪除它們的舊.apks

(c)我沒有想到的其他問題

感謝您的時間。 如果有人能想到一個可行的方向,將不勝感激!

通過使用Android文檔建議的自上而下方法為每個自定義視圖正確實現OnMeasure和OnLayout進行了修復。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM